Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Slow anonymous function

Suppose you have a loop with 50000 iterations and want to calculate mean values (scalars) from alot of matrices. This is not complete, but roughly like this:

for k=1:50000
...
mean=sum(sum(matrix))/numel(matrix); %Arithmetic mean
...
end

And now want to include different mean equations to choose from. First I tried this:

average='arithmetic'
for k=1:50000
...
switch average
    case 'arithmetic'
        mean=sum(sum(matrix))/numel(matrix); %Arithmetic mean
    case 'geometric'
        mean=prod(prod(matrix)).^(1/numel(matrix)); %Geometric mean
    case 'harmonic'
        mean=numel(matrix)/sum(sum(1./matrix)); %Harmonic mean
end
...
end

This is obviously alot slower than the first loop because it needs to find the matching string for every iteration which feels really unnecessary. Then I tried this:

average='arithmetic'
switch average
    case 'arithmetic'
        eq=@(arg)sum(sum(arg))/numel(arg); %Arithmetic mean
    case 'geometric'
        eq=@(arg)prod(prod(arg)).^(1/numel(arg)); %Geometric mean
    case 'harmonic'
        eq=@(arg)numel(arg)/sum(sum(1./arg)); %Harmonic mean
end

for k=1:50000
...
mean=eq(matrix); %Call mean equation
...
end

This is still about twice as slow as the first loop and I don't get why. The two last loops are almost similar in speed.

Am I doing something wrong here? How can I achieve the same performance as the first loop with this extra feature?

Help is very much appreciated!

like image 843
shant Avatar asked Apr 15 '11 15:04

shant


People also ask

Are anonymous functions slower?

YES! Anonymous functions are faster than regular functions.

Are anonymous functions slow Matlab?

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.

What is meant by anonymous function?

Anonymous functions are often arguments being passed to higher-order functions or used for constructing the result of a higher-order function that needs to return a function. If the function is only used once, or a limited number of times, an anonymous function may be syntactically lighter than using a named function.

What are anonymous functions good for?

The advantage of an anonymous function is that it does not have to be stored in a separate file. This can greatly simplify programs, as often calculations are very simple and the use of anonymous functions reduces the number of code files necessary for a program.


2 Answers

Having the switch inside the loop is performing a comparison 50000 times which only needs to be performed once, something I'd advise against.

The second is a little more subtle, but it's quite probable the eq function is being dynamically looked up every iteration and possibly interpreted each time as well (not sure how MATLAB does optimisation). Your best bet for performance is probably to put the for loop inside of the switch

switch average
    case 'arithmetic'
        for ... end
    case 'geometric'
        for ... end
    case 'harmonic'
        for ... end
end
like image 198
DavW Avatar answered Oct 21 '22 12:10

DavW


Well, every function, even anonymous functions, can be expected to have some amount of extra overhead involved in calling it, making them slightly slower than their single-line expression counterparts in your example. However, in this case there may be extra overhead due to the fact that functions by the name eq already exist in abundance in MATLAB, since eq is the method name of the overloaded == operator. Using the WHICH command like so:

>> which eq -all

Will show you that eq is heavily overloaded, with one existing for each of the fundamental data types and most objects.

I would try using a different name for your anonymous function handle just to see if dispatching may be a factor, although I kinda doubt it based on the function precedence order (i.e. variables always appear to take precedence). Your best solution performance-wise may be to avoid the extra function call overhead by doing something like what DavW suggests.

I would like to make one other suggestion. Many of the mathematical operations you are doing can be greatly improved to make them more efficient, specifically by making use of the function MEAN and the colon operator to reshape an entire matrix into a column vector:

result = mean(matrix(:));  %# For the arithmetic mean

result = prod(matrix(:))^(1/numel(matrix));  %# For the geometric mean

result = 1/mean(1./matrix(:));  %# For the harmonic mean

Note that I didn't use the name mean for my variable since that is already used for the built-in function, and you definitely don't want to shadow it.

like image 34
gnovice Avatar answered Oct 21 '22 13:10

gnovice