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
(调整 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
真的只是个人喜好,感觉更优雅一些。
我试图找到在 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
(调整 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
真的只是个人喜好,感觉更优雅一些。