Slow performance using anonymous functions in MATLAB… have others noticed this?

前端 未结 4 2227
花落未央
花落未央 2020-12-15 13:15

In order to refactor my MATLAB code, I thought I\'d pass around functions as arguments (what MATLAB calls anonymous functions), inspired by functional programming.

H

相关标签:
4条回答
  • 2020-12-15 13:26

    Results from a Windows machine, Matlab 2009a

    >> test
    
    ans =
    
         0    0.0156    1.1094
    
    0 讨论(0)
  • 2020-12-15 13:29

    I faced the same issue as Gary, just thought it would be good to check Andrew's answer on a more recent version of Matlab (2014a) (Mac). The results first:

    direct: 0.0722
    anonymous: 0.3916
    subfunction: 0.2277
    

    And the code I used:

    function []=SpeedTest()
    
    fanon = @(x,y) x*x+y*y;
    
    iter=1000000;
    x=1:iter;
    y=1:iter;
    var1=nan(size(x));
    var2=nan(size(x));
    var3=nan(size(x));
    timefor=struct('direct',nan,'anonymous',nan','subfunction',nan);
    
    tic;
    for i=1:iter
        var1(i)=x(i)*x(i)+y(i)*y(i);
    end
    timefor.direct=toc;
    
    tic;
    for i=1:iter
        var2(i)=fanon(x(i),y(i));
    end
    timefor.anonymous=toc;
    
    tic;
    for i=1:iter
        var3(i)=fsub(x(i),y(i));
    end
    timefor.subfunction=toc;
    
    display(timefor);
    end
    
    function [z]=fsub(x,y)
    z=x*x+y*y;
    end
    
    0 讨论(0)
  • 2020-12-15 13:34

    You're cheating with the nested function. :) The anonymous function is being called inside a loop, so you're measuring the cost of calling it 100,000 times. The nested function only gets called once, so its function call overhead is negligible. To compare the cost of calling anonymous vs named functions, you should have the nested function do the same work as the anonymous function and then call it from inside a loop, too.

    I did that and still got similar results. The anonymous function is about 20 times slower.

    However, you can still use function handles with non-anonymous functions, and that doesn't have the same performance hit as anonymous functions. This works with either nested functions (as with the foo in your original test) or non-nested subfunctions (which don't act as closures and may have less overhead).

    function [] = speedtest()
    
    function y = foo(x)
        y = x^2;
    end
    
    r = struct;
    
    ...
    
    %% using nested function through function handle
    fn = @foo;
    y = zeros(1,N);
    t = cputime;
    for i=1:N
        y(i) = fn(x(i));
    end
    r.nested_handle = cputime - t;
    
    ...
    
    %% using subfunction through function handle
    fn = @subfunction_foo;
    y = zeros(1,N);
    t = cputime;
    for i=1:N
        y(i) = fn(x(i));
    end
    r.subfunction_handle = cputime - t;
    
    ...
    
    end % end function speedtest
    
    function y = subfunction_foo(x)
    y = x^2;
    end
    

    I get this on R2009b in Windows.

    >> speedtest
                    direct: 0
                    nested: 0.0469
             nested_handle: 0.0781
               subfunction: 0.0313
        subfunction_handle: 0.0313
                 anonymous: 1.2344
    

    Another way to look at it is to structure your code so it's "vectorized" and operates on arrays, reducing the number of function calls and the cost of the function call doesn't matter so much. That would be more idiomatic Matlab: typical performance advice is to ignore the cost of function calls and loops because you ought to be doing fewer calls on larger arguments anyway.

    0 讨论(0)
  • 2020-12-15 13:37

    I can confirm your findings Grav. The speedtest function returns the following on my computer.

    >> speedtest()
    ans =
             0    0.0313    1.3906
    

    As a sidenote, the function cputime is not the best method for measuring computation time. Use the tic and toc functions instead. see link These functions provides a much higher time resolution, and using them I obtain the following.

    >> speedtest()
    ans =
             0.0062    0.0162    1.3495
    
    0 讨论(0)
提交回复
热议问题