【问题标题】:calculation performance for mean2 in MATLABMATLAB中mean2的计算性能
【发布时间】:2015-12-10 16:04:17
【问题描述】:

为什么直接实现 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' 可能是原因吗?

【问题讨论】:

  • 就是这样。 mean2 将二维矩阵展开为向量并直接取平均值。展开可能是您获得性能提升的原因。我不记得我在哪里看到了它,但是(这里)进行了一些时序测试,其中在计算之前展开有助于使事情变得更快......但是随着阵列变大,性能会下降,因为你正在展开更多元素。
  • 也许用timeit 来确定时间?
  • @rayryeng 但这里不是数组变大了;这只是重复的次数(如果我理解正确的话)
  • @LuisMendo - 当我误读代码时会发生这种情况。是的,你是对的......这是一个奇怪的异常情况。
  • 反正差别很小

标签: performance matlab mean


【解决方案1】:

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

结果是:

经过的时间是 2.115313 秒。 对于 sum(sum(Ig))/numel(Ig) 250x250

经过的时间是 5.753932 秒。 对于 mean2(Ig) 250x250

经过的时间是 5.626373 秒。 对于 sum(Ig(:),'double')/numel(Ig) 250x250

经过的时间是 5.425690 秒。 对于 sum(Ig(:))/numel(Ig) 250x250

经过的时间是 6.349700 秒。 对于 sum(sum(Ig))/numel(Ig) 500x500

经过的时间是 6.810287 秒。 对于 mean2(Ig) 500x500

经过的时间是 6.840604 秒。 对于 sum(Ig(:),'double')/numel(Ig) 500x500

经过的时间是 6.455498 秒。 对于 sum(Ig(:))/numel(Ig) 500x500

经过的时间是 23.772897 秒。 对于 sum(sum(Ig))/numel(Ig) 1000x1000

经过的时间是 22.071418 秒。 对于 mean2(Ig) 1000x1000

经过的时间是 21.862069 秒。 对于 sum(Ig(:),'double')/numel(Ig) 1000x1000

经过的时间是 21.498514 秒。 对于 sum(Ig(:))/numel(Ig) 1000x1000

【讨论】:

  • 我不确定我是否向您发出了这个邀请,但是如果您有时间,请到我们的 MATLAB 和 Octave 聊天室 :) 我看到您经常在这里回答问题。我们经常在那里谈论事情并建立联系。完全取决于你。如果没有,不用担心。祝你好运! chat.stackoverflow.com/rooms/81987/matlab-and-octave
  • 感谢邀请 :) 我一定会偶尔光顾的!我从你们那里学到了很多东西!
猜你喜欢
  • 2014-10-10
  • 2021-10-16
  • 2019-03-08
  • 1970-01-01
  • 2012-10-18
  • 2011-12-27
  • 2012-03-09
  • 1970-01-01
  • 2021-03-28
相关资源
最近更新 更多