MATLAB 中 mean2 的计算性能

calculation performance for mean2 in MATLAB

为什么直接执行 mean 函数更快?

Ig = rgb2gray(imread('test.png'));
n = 100000;
tic;
for ii=1:n
    M1 = sum(sum(Ig))/numel(Ig);
end
toc
tic;
for ii=1:n
    M2 = mean2(Ig);
end
toc

大约 n = 1000,但 mean2 更快。但是随着迭代次数的增加,速度变慢了。

Elapsed time is 45.934058 seconds.
Elapsed time is 46.392206 seconds.

我怀疑 mean2 内部正在做这样的事情:

out = sum(x(:),'double') / numel(x)

x(:)'double' 可能是原因吗?

运行一些测试代码后的结论:1)在你的代码中,当迭代次数大于 1000 时,mean2 显得更慢的原因是因为将代码组织成的惩罚功能。 MATLAB 需要为函数创建一个作用域,并在函数调用结束时终止它。从下面的测试条件可以看出,我在代码中直接实现了 mean2。 2) 根据@rayryeng 的评论,当数组很大时(至少在我的测试条件下),首先展开会加快计算速度。 3) sum(Ig(:),'double') 中的 'double' 参数占用了一些时间,实际上是不必要的,因为 sum returns double 数据类型即使没有该参数。

我用来测试的代码如下:

Img = rgb2gray(imread('test2.tif'));  % this is an rgb image larger than 1000x1000
Ig = Img(1:250,1:250);
n = 100000;
tic
for ii=1:n
    M1 = sum(sum(Ig))/numel(Ig);
end
toc
disp('  for sum(sum(Ig))/numel(Ig) 250x250') 

tic;
for ii=1:n
    M2 = mean2(Ig);
end
toc
disp('  for mean2(Ig) 250x250') 

tic;
for ii=1:n
    M3 = sum(Ig(:),'double')/numel(Ig);
end
toc
disp('  for sum(Ig(:),''double'')/numel(Ig) 250x250') 

tic;
for ii=1:n
    M4 = sum(Ig(:))/numel(Ig);
end
toc
disp('  for sum(Ig(:))/numel(Ig) 250x250')
clear M1 M2 M3 M4 

Ig = Img(1:500,1:500);

tic
for ii=1:n
    M1 = sum(sum(Ig))/numel(Ig);
end
toc
disp('  for sum(sum(Ig))/numel(Ig) 500x500') 

tic
for ii=1:n
    M2 = mean2(Ig);
end
toc
disp('  for mean2(Ig) 500x500') 

tic
for ii=1:n
    M3 = sum(Ig(:),'double')/numel(Ig);
end
toc
disp('  for sum(Ig(:),''double'')/numel(Ig) 500x500') 

tic
for ii=1:n
    M4 = sum(Ig(:))/numel(Ig);
end
toc
disp('  for sum(Ig(:))/numel(Ig) 500x500')

Ig = Img(1:1000,1:1000);
tic
for ii=1:n
    M1 = sum(sum(Ig))/numel(Ig);
end
toc
disp('  for sum(sum(Ig))/numel(Ig) 1000x1000') 

tic
for ii=1:n
    M2 = mean2(Ig);
end
toc
disp('  for mean2(Ig) 1000x1000') 

tic
for ii=1:n
    M3 = sum(Ig(:),'double')/numel(Ig);
end
toc
disp('  for sum(Ig(:),''double'')/numel(Ig) 1000x1000') 

tic
for ii=1:n
    M4 = sum(Ig(:))/numel(Ig);
end
toc
disp('  for sum(Ig(:))/numel(Ig) 1000x1000')

结果是:

Elapsed time is 2.115313 seconds. for sum(sum(Ig))/numel(Ig) 250x250

Elapsed time is 5.753932 seconds. for mean2(Ig) 250x250

Elapsed time is 5.626373 seconds. for sum(Ig(:),'double')/numel(Ig) 250x250

Elapsed time is 5.425690 seconds. for sum(Ig(:))/numel(Ig) 250x250

Elapsed time is 6.349700 seconds. for sum(sum(Ig))/numel(Ig) 500x500

Elapsed time is 6.810287 seconds. for mean2(Ig) 500x500

Elapsed time is 6.840604 seconds. for sum(Ig(:),'double')/numel(Ig) 500x500

Elapsed time is 6.455498 seconds. for sum(Ig(:))/numel(Ig) 500x500

Elapsed time is 23.772897 seconds. for sum(sum(Ig))/numel(Ig) 1000x1000

Elapsed time is 22.071418 seconds. for mean2(Ig) 1000x1000

Elapsed time is 21.862069 seconds. for sum(Ig(:),'double')/numel(Ig) 1000x1000

Elapsed time is 21.498514 seconds. for sum(Ig(:))/numel(Ig) 1000x1000