开发者

Slow anonymous function

开发者 https://www.devze.com 2023-02-25 07:28 出处:网络
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:

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 'geomet开发者_开发问答ric'
        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!


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


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.

0

精彩评论

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

关注公众号