开发者

Is there a way to perform function inlining in MATLAB?

开发者 https://www.devze.com 2023-02-16 19:05 出处:网络
What language feature or outside-the-box hack can I use to accomplish function inlining in MATLAB? Annoyingly, a Google search for \"matlab inline function\" reveals that MATLAB\'s designers thought t

What language feature or outside-the-box hack can I use to accomplish function inlining in MATLAB? Annoyingly, a Google search for "matlab inline function" reveals that MATLAB's designers thought that "to inline" means "to construct an anonymous function out of a string" (...wtf?).

The reason I ask is I am writing a script that needs to run fast, and I am encountering a lot of situations where it would be nice to have a helper function handle some simple addition or something to avoid off-by-one errors. However, the cost of a function call (as measured by tic/toc) would not be worth it. I refuse to believe that MATLAB would lack a function inlining feature because that would discourage decomposition!

Worst case, I could resort to using M4 macros.


EDIT: In response to eat's comment, here is a situation where I might like to inline a helper:

At one p开发者_运维问答oint, I need to loop (yeah, I know) over all windows of width windowWidth within a list:

lastWindowStartIdx = length(list) - windowWidth + 1;
for windowStartIdx = 1:lastWindowStartIdx
   display(list[windowStartIdx:windowStartIdx+windowWidth-1]); %the window we're looking at
end

It would be nice to be able to factor out those tricky, off-by-one-error-prone windowWidth calculations. E.g.:

lastWindowStartIdx = calcLastWindowStartIdx(length(list), windowWidth);
for windowStartIdx = 1:lastWindowStartIdx
   display(list[windowStartIdx:calcWindowEndIdx(windowStartIdx, windowWidth)]); %the window we're looking at
end


Specific answer:

In reference to your example use-case, this honestly strikes me as a sort of micro-optimization. These plus-one operations are certainly not the bottleneck in your code keeping it from running fast, so you should instead focus on speeding up the parts of your code where the bulk of your computations take place.

If you are only wanting to make this change for aesthetic (spelled it on the first try!) reasons, or because you just don't like keeping track of the extra ones, then creating a function to handle it as in your example is a bad choice in my opinion because it just makes the code that much harder to read and understand. I would suggest simply creating a new variable like so:

windowOffset = windowWidth - 1;
lastWindowStartIdx = length(list) - windowOffset;
for windowStartIdx = 1:lastWindowStartIdx
   display(list[windowStartIdx:windowStartIdx + windowOffset]);
end

General answer:

Regarding your more general question about how to create true inline functions in MATLAB like you can in C or C++, I don't believe there's any way to do this. I thought perhaps that an anonymous function may fit the bill, but after doing some simple timing comparisons with a number of different types of functions in MATLAB I found that an anonymous function is actually slower than a good ol' subfunction for a simple +1 operation.

Here were the sample functions I tested:

function parent_function
  add_one_anon = @(A) A+1;         %# An anonymous function
  add_one_inline = inline('A+1');  %# An "inline" function
  function add_one_nest            %# A nested function
    A = A+1;
  end
  %# Did the timing here ...
end
function A = add_one_sub(A)        %# A subfunction
  A = A+1;
end

I ran each of these 100,000 times incrementing a scalar value that started at 1, and here are the results:

            | Time (sec)
------------+------------       
subfunction |   0.0507
anonymous   |   0.0672
nested      |   0.0932
inline      |  14.7095

If anonymous functions acted like true inline functions, I would have expected them to be the fastest solution.


In short, you can't inline, in C++ terms, functions in MATLAB. You probably already know this, but loops in MATLAB are slow and you should replace them with vectorized operations instead.

If you need to accelerate just the function call, you should probably pre-compute all your indices as a vectorized operation and then loop over the results.

windows = window_ranges(1, length(list), windowWidth);
for i = 1:size(windows,1),
   display(list[windows(i,1):windows(i,2)]);
end

function [ windows ] = window_ranges ( lower, upper, span )
    count = upper - span;
    windows = zeros(count, 2);
    windows(:,1) = 1:count;
    windows(:,2) = windows(:,1)+span-1;
end
0

精彩评论

暂无评论...
验证码 换一张
取 消