我正在尝试找到在Matlab(零均值,单位方差列)中标准化矩阵的最快方法。归结为这是对矩阵中的所有行应用相同操作的最快方法。我阅读的每篇文章都得出相同的结论:使用bsxfun而不是repmat 。
由Mathworks撰写的这篇文章是一个示例:http://blogs.mathworks.com/loren/2008/08/04/comparing-repmat-and-bsxfun-performance/
但是,在我自己的计算机上尝试此操作时,repmat总是更快。这是使用与文章相同的代码得到的结果:
m = 1e5;
n = 100;
A = rand(m,n);
frepmat = @() A - repmat(mean(A),size(A,1),1);
timeit(frepmat)
fbsxfun = @() bsxfun(@minus,A,mean(A));
timeit(fbsxfun)
结果:
ans =
0.0349
ans =
0.0391
实际上,无论输入矩阵有多大,在这种情况下我都无法使bsxfun的性能优于repmat。
有人可以解释吗?
最佳答案
您正在阅读的大多数建议(包括Loren的博客文章)都可能引用了旧版本的MATLAB,其bsxfun
比repmat
快很多。在R2013b中(请参阅链接中的“性能”部分),重新实现了repmat
,以将其应用于数字,字符和逻辑参数时可大大提高性能。在最新版本中,它的速度可以与bsxfun
相同。
对于它的值(value),在装有R2014a的机器上我得到了
m = 1e5;
n = 100;
A = rand(m,n);
frepmat = @() A - repmat(mean(A),size(A,1),1);
timeit(frepmat)
fbsxfun = @() bsxfun(@minus,A,mean(A));
timeit(fbsxfun)
ans =
0.03756
ans =
0.034831
因此
bsxfun
看起来仍然快一点点,但速度并不快-在您的计算机上,情况似乎恰恰相反。当然,如果更改A
的大小或要应用的操作,则这些结果很可能会再次变化。仍然有其他原因可能会优先选择一种解决方案,例如优雅(如果可能,我更喜欢
bsxfun
)。编辑:评论者出于特定原因要求偏爱
bsxfun
,这意味着通过避免repmat
不会使用的临时副本,它可能比repmat
占用更少的内存。我认为情况并非如此。例如,打开任务管理器(或Linux / Mac上的等效项),观察内存级别,然后键入:
>> m = 1e5; n = 8e3; A = rand(m,n);
>> B = A - repmat(mean(A),size(A,1),1);
>> clear B
>> C = bsxfun(@minus,A,mean(A));
>> clear C
(调整
m
和n
,直到在图表中看到跳转为止,但不要太大,以免耗尽内存)。我从
repmat
和bsxfun
看到了完全相同的行为,那就是内存平稳地上升到新的水平(基本上是A
的两倍),没有临时的额外峰值。即使就地完成操作,情况也是如此。再次,注意内存并键入:
>> m = 1e5; n = 8e3; A = rand(m,n);
>> A = A - repmat(mean(A),size(A,1),1);
>> clear all
>> m = 1e5; n = 8e3; A = rand(m,n);
>> A = bsxfun(@minus,A,mean(A));
同样,我从
repmat
和bsxfun
看到了完全相同的行为,即内存上升到一个峰值(基本上是A
大小的两倍),然后又下降到上一个级别。因此,恐怕
repmat
和bsxfun
之间在速度或内存方面看不到太多技术差异。我对bsxfun
的偏爱实际上只是个人偏爱,因为它感觉更优雅。