我写了一个代码,数字上使用勒让德多项式达到某个高n阶。例如:
....
case 8
p = (6435*x.^8-12012*x.^6+6930*x.^4-1260*x.^2+35)/128; return
case 9
...
如果向量x
很长,则会变慢。我看到说x.^4
和x.*x.*x.*x
之间存在性能差异,并认为我可以使用它来改进我的代码。我使用timeit
并找到了:
x=linspace(0,10,1e6);
f1= @() power(x,4)
f2= @() x.4;
f3= @() x.^2.^2
f4= @() x.*x.*x.*x
f4
更快 因子2 比其余<。但是,当我转到x.^6
时,(x.*x.*x).^2
和x.*x.*x.*x.*x.*x
之间的差异很小(而所有其他选项都较慢)。
有没有告诉我最有效的方法来获取向量的力量? 你能解释为什么性能会有这么大的差异吗?
答案 0 :(得分:8)
这不是您问题的答案,但它可以解决您的问题:
x2 = x.*x; % or x.^2 or power(x,2), whichever is most efficient
p = ((((6435*x2-12012)*x2+6930)*x2-1260)*x2+35)/128
这种方式只需执行一次幂,并且仅使用指数2.此技巧可应用于所有勒让德多项式(在奇数次多项式中,x2
由x
替换。
答案 1 :(得分:1)
以下是一些想法:
power(x,4)
和x.^4
相同(只需阅读文档)。
x.*x.*x.*x
可能已针对类似x.^2.^2
x.^2.^2
可能被评估为:取每个元素的平方(快),然后再取正方形(再次快速)。
x.^4
可能直接评估为:取每个元素的四次幂(慢)。
看到2个快速操作比1个慢速操作花费的时间少,这并不奇怪。太糟糕了,在功率4的情况下没有执行优化,但也许它不会总是有效或成本(输入检查,内存?)。
关于时间:实际上比2因素有更多的区别!
正如你现在在函数中调用它们一样,在每种情况下都会添加函数开销,使相对差异变小:
y=x;tic,power(x,4);toc
y=x;tic,x.^4;toc
y=x;tic,x.^2.^2;toc
y=x;tic,x.*x.*x.*x;toc
会给:
Elapsed time is 0.034826 seconds.
Elapsed time is 0.029186 seconds.
Elapsed time is 0.003891 seconds.
Elapsed time is 0.003840 seconds.
所以,差不多是10倍。但请注意,以秒为单位的时差仍然很小,因此对于大多数实际应用,我只想采用简单的语法。
答案 2 :(得分:1)
似乎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
会出错。 (当然,在您的情况下,请遵循路易斯的建议,并在每个学期内使用中间结果!)
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