【发布时间】:2012-09-13 10:12:17
【问题描述】:
考虑以下arrayfun 的简单速度测试:
T = 4000;
N = 500;
x = randn(T, N);
Func1 = @(a) (3*a^2 + 2*a - 1);
tic
Soln1 = ones(T, N);
for t = 1:T
for n = 1:N
Soln1(t, n) = Func1(x(t, n));
end
end
toc
tic
Soln2 = arrayfun(Func1, x);
toc
在我的机器上(Linux Mint 12 上的 Matlab 2011b),这个测试的输出是:
Elapsed time is 1.020689 seconds.
Elapsed time is 9.248388 seconds.
什么?!? arrayfun 虽然公认是一个看起来更干净的解决方案,但速度要慢一个数量级。这是怎么回事?
此外,我对cellfun 进行了类似的测试,发现它比显式循环慢了大约 3 倍。同样,这个结果与我的预期相反。
我的问题是: 为什么arrayfun 和cellfun 这么慢?鉴于此,是否有任何充分的理由使用它们(除了让代码看起来不错)?
注意:我在这里说的是arrayfun 的标准版本,而不是并行处理工具箱中的GPU 版本。
编辑:为了清楚起见,我知道上面的 Func1 可以像 Oli 指出的那样被矢量化。我之所以选择它,是因为它会针对实际问题进行简单的速度测试。
编辑:按照 grunetta 的建议,我使用 feature accel off 重新进行了测试。结果是:
Elapsed time is 28.183422 seconds.
Elapsed time is 23.525251 seconds.
换句话说,很大一部分差异似乎在于 JIT 加速器在加速显式 for 循环方面比 arrayfun 做得更好。这对我来说似乎很奇怪,因为arrayfun 实际上提供了更多信息,即它的使用表明对Func1 的调用顺序无关紧要。另外,我注意到无论 JIT 加速器是打开还是关闭,我的系统都只使用一个 CPU...
【问题讨论】:
-
幸运的是,“标准解决方案”仍然是迄今为止最快的:tic; 3*x.^2+2*x-1; toc 经过的时间是 0.030662 秒。
-
@Oli 我想我应该预料到有人会指出这一点并使用无法矢量化的函数:-)
-
我很想看看当 JIT 加速器关闭时这个时间是如何变化的。执行命令“feature accel off”,然后重新运行您的测试。
-
@grungetta 有趣的建议。我已将结果与一些 cmets 添加到问题中。
标签: arrays performance matlab