【问题标题】:Matlab - bsxfun no longer faster than repmat?Matlab - bsxfun 不再比 repmat 快?
【发布时间】:2015-04-27 15:58:15
【问题描述】:

我正在尝试找到在 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 更好。

谁能解释一下?

【问题讨论】:

  • 对我来说,bsxfun 方法总是更快,对于更大的数组也是如此。 (Matlab 2014a)
  • 在最近的 MATLAB 版本中,repmat 是一个类似 bsxfun 的编译函数,而在以前的版本中它是一个 m 文件,所以我期待它的性能提升。在我的系统上,使用您的示例代码,bsxfun 的性能与稍好一点的性能相同(正如我所说的那样,区别在于“在洗涤中”)。但是,bsxfun 仍然具有不将额外数组分配到内存中的优势。
  • bsxfun 总是更好。不管需要多长时间:-P
  • 对于这些时间,我建议尝试更大的矩阵,例如,至少m=1e5;n=1e3;A=rand(m,n);
  • @user89161:更可能归结为内存和缓存。要在计算机和操作系统之间进行真正公平的比较,我们需要了解所涉及的 CPU、RAM 等。

标签: arrays matlab bsxfun


【解决方案1】:

您正在阅读的大部分建议,包括 Loren 的博客文章,都可能涉及旧版本的 MATLAB,bsxfunrepmat 快很多。在R2013b(请参阅链接中的“性能”部分)中,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的偏爱实际上只是个人喜好,因为它感觉更优雅一些。

【讨论】:

  • bsxfun 仍然具有占用更少内存的优势,因为它在内部避免了数据重复,对吗?我的意思是,给出一个理由来证明对bsxfun 的偏好是合理的! :-)
  • @LuisMendo 是否有可能重新实现 repmat 避免显式内存复制?是否有可能实现“惰性”副本?我无法访问最新的 Matlab 版本...
  • @Shai 是的,这就是我的问题的意思。可能是repmat 在内部进行了某种优化。我不知道。但我还是更喜欢bsxfun
  • @SamRoberts 谢谢。是的,关于内存,我在这里得到相同的行为。另一方面,至于运行时间,bsxfun 似乎更快; see Divakar's tests
  • @SamRoberts 现在还有更多! stackoverflow.com/questions/29800560/…
猜你喜欢
  • 2015-06-25
  • 2014-09-15
  • 2018-03-01
  • 1970-01-01
  • 2017-07-22
  • 2012-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多