似乎 Mathworks 在其幂函数中具有特殊的大小写正方形(不幸的是,它都是我们看不到的内置封闭源代码)。在我对 R2013b 的测试中,它看起来好像.^
,power
和realpow
使用相同的算法。对于正方形,我相信他们已经将其特例化为x.*x
.
1.0x (4.4ms): @()x.^2
1.0x (4.4ms): @()power(x,2)
1.0x (4.5ms): @()x.*x
1.0x (4.5ms): @()realpow(x,2)
6.1x (27.1ms): @()exp(2*log(x))
对于立方体,情况就不同了。它们不再是特殊情况。再一次,.^
,power
和realpow
所有都是相似的,但这次要慢得多:
1.0x (4.5ms): @()x.*x.*x
1.0x (4.6ms): @()x.*x.^2
5.9x (26.9ms): @()exp(3*log(x))
13.8x (62.3ms): @()power(x,3)
14.0x (63.2ms): @()x.^3
14.1x (63.7ms): @()realpow(x,3)
让我们跳到 16 次方,看看这些算法是如何扩展的:
1.0x (8.1ms): @()x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x
2.2x (17.4ms): @()x.^2.^2.^2.^2
3.5x (27.9ms): @()exp(16*log(x))
7.9x (63.8ms): @()power(x,16)
7.9x (63.9ms): @()realpow(x,16)
8.3x (66.9ms): @()x.^16
所以: .^
,power
并且realpow
所有关于指数的运行时间都是恒定的,除非它是特殊情况(-1 也似乎是特殊情况)。使用这个exp(n*log(x))
技巧也是关于指数的恒定时间,而且速度更快。唯一的结果我不太明白为什么重复平方比乘法慢。
正如预期的那样,将 的大小x
增加 100 倍同样会增加所有算法的时间。
那么,这个故事的寓意是什么?使用标量整数指数时,请始终自己进行乘法运算。和朋友们有很多聪明才智power
(指数可以是浮点数、向量等)。唯一的例外是 Mathworks 为您完成优化的地方。在 2013b 中,它似乎是x^2
和x^(-1)
. 希望随着时间的推移他们会增加更多。但是,一般来说,求幂很困难,而乘法很容易。在对性能敏感的代码中,我认为你不会因为总是输入而出错x.*x.*x.*x
。(当然,在您的情况下,请遵循 Luis 的建议,并利用每个学期的中间结果!)
function powerTest(x)
f{1} = @() x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x.*x;
f{2} = @() x.^2.^2.^2.^2;
f{3} = @() exp(16.*log(x));
f{4} = @() x.^16;
f{5} = @() power(x,16);
f{6} = @() realpow(x,16);
for i = 1:length(f)
t(i) = timeit(f{i});
end
[t,idxs] = sort(t);
fcns = f(idxs);
for i = 1:length(fcns)
fprintf('%.1fx (%.1fms):\t%s\n',t(i)/t(1),t(i)*1e3,func2str(fcns{i}));
end