Matlab - bsxfun不再比repmat快吗?

use*_*337 21 arrays matlab bsxfun

我正在尝试找到在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)
Run Code Online (Sandbox Code Playgroud)

结果:

ans =

    0.0349


ans =

    0.0391
Run Code Online (Sandbox Code Playgroud)

事实上,无论输入矩阵有多小或多大,我都无法在这种情况下使bsxfun表现得比repmat更好.

有人可以解释一下吗?

Sam*_*rts 11

您正在阅读的大多数建议,包括Loren的博客文章,可能都是指旧版本的MATLAB,其bsxfun速度要快得多repmat.在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
Run Code Online (Sandbox Code Playgroud)

所以它看起来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
Run Code Online (Sandbox Code Playgroud)

(调节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));
Run Code Online (Sandbox Code Playgroud)

同样,我清楚地看到从两个相同的行为repmatbsxfun,这是记忆上升到峰值(基本上是双重的大小A),然后回落到以前的水平.

所以,恐怕我不能看到速度或之间存储器方面多少技术差别repmatbsxfun.我的偏好bsxfun实际上只是个人偏好,因为它感觉更优雅.