Matlab - bsxfun 不再比 repmat 快?

Matlab - bsxfun no longer faster than repmat?

我试图找到在 Matlab 中标准化矩阵的最快方法(零均值、单位方差列)。这一切都归结为对矩阵中的所有行应用相同操作的最快方法。我读过的每个 post 都得出相同的结论:使用 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 的博客 post,可能是指旧版本的 MATLAB,bsxfun 比 [=14= 快很多].在 R2013b 中(参见 link 中的 "Performance" 部分),repmat 被重新实现以在应用于数字、字符和逻辑参数时提供较大的性能改进。在最近的版本中,它可以与 bsxfun.

大致相同的速度

为了它的价值,在我的 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

(调整 mn 直到跳跃在图表中可见,但不要太大以至于 运行 内存不足)。

我从 repmatbsxfun 中看到完全相同的行为,即内存平稳地上升到新的水平(基本上是 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));

再次,我从 repmatbsxfun 中看到完全相同的行为,即内存上升到峰值(基本上是 A 的两倍),然后回落到之前的水平。

所以恐怕我看不出 repmatbsxfun 在速度或内存方面有太大的技术差异。我喜欢bsxfun真的只是个人喜好,感觉更优雅一些。