我想知道exp()
是否比更一般的pow()
更快。我在JsPerf http://jsperf.com/pow-vs-exp上运行快速基准测试,它为我显示了有趣的结果。
Math.exp(logBase * exponent); // fastest
Math.exp(Math.log(base) * exponent); // middle
Math.pow(base, exponent); // slowest
我知道结果会因架构和语言而异,但我也对理论观点感兴趣。将pow(a, b)
实现为exp(log(a) * b)
还是有一些更聪明的方式来“直接”计算能力(在C ++,C#或JavaScript中)。在某些体系结构上是否有针对exp,log或pow的CPU指令?
据我所知,exp()
和log()
都是使用一些泰勒级数计算的,计算成本非常高。这让我相信,对于恒定的功率基础,这段代码
double logBase = log(123.456);
for (int i = 0; i < 1024; ++i) {
exp(logBase * 654.321);
}
比这更好
for (int i = 0; i < 1024; ++i) {
pow(123.456, 654.321);
}
这是正确的假设吗?
答案 0 :(得分:10)
是的,exp
一般会比pow
快。
exp
和log
函数将针对目标平台进行优化;可以使用许多技术,例如Pade近似,线性或二进制缩减,然后近似等等。
pow
函数通常会以exp(log(a) * b)
的形式实现,因此它明显比单独exp
慢。 pow
有许多特殊情况,例如负指数,积分指数,等于1/2或1/3的指数等。这些将在一般情况下进一步减慢pow
因为这些测试很贵。
答案 1 :(得分:1)
作为部分答案,有些架构上有exp,log或pow的说明。但是,这并不一定意味着很多。
例如,在x86上有
f2xm1
计算2 x - 1 fscale
计算y * 2 (int)x fyl2x
计算y * log 2 x fyl2xp1
计算y * log 2 (x + 1)(对输入范围有限制)但是,它们使用不多。它从建筑到建筑各不相同,但它们永远不会快。作为一个更极端的例子,fyl2x
在Sandy Bridge上有一个724的延迟(非常近期!),在同一个处理器上你可以做大约700个独立浮点加法,或者大约240个依赖浮点加法,或大约2000个独立的简单整数运算。
这和它一样糟糕,但它们通常很慢。足够慢,手动实施可以击败他们或至少不会明显失败。
此外,FPU代码正在慢慢消失,转而支持SSE代码。这些指令没有SSE等价物。
答案 2 :(得分:1)
无论架构详细信息如何,Math.pow
都必须在错误检查方面做得更多(例如,如果基数为负,会发生什么?)。比Math.exp
(因此我希望pow
更慢)。
规范的相关部分:
http://ecma-international.org/ecma-262/5.1/#sec-15.8.2.8
15.8.2.8 exp(x)
返回指数的依赖于实现的近似值 x的函数(e增加到x的幂,其中e是x的基数) 自然对数)。
如果x是NaN,则结果为NaN。如果x为+0,则结果为1.如果x为 -0,结果为1.如果x为+∞,则结果为+∞。如果x是-∞,那么 结果是+0。
http://ecma-international.org/ecma-262/5.1/#sec-15.8.2.13
15.8.2.13 pow(x,y)
返回与结果相关的依赖于实现的近似值 将x提高到y。
如果y是NaN,则结果为NaN。如果y为+0,则结果为1,即使x为x 是NaN。如果y为-0,则结果为1,即使x为NaN。如果x是NaN和 y非零,结果是NaN。如果abs(x)> 1且y是+∞,则结果如此 是+∞。如果abs(x)> 1且y为-∞,则结果为+0。如果abs(x)== 1和y 是+∞,结果是NaN。如果abs(x)== 1且y为-∞,则结果为NaN。 如果abs(x)<1且y为+∞,则结果为+0。如果abs(x)<1且y是-∞, 结果是+∞。如果x是+∞且y> 0,则结果是+∞。如果x是+∞和 y <0,结果为+0。如果x是-∞且y> 0且y是奇数,则 结果是-∞。如果x是-∞且y> 0且y不是奇数,则 结果是+∞。如果x是-∞并且y <0并且y是奇数,则结果 是-0。如果x是-∞且y <0且y不是奇数,则结果为 + 0。如果x是+0且y> 0,则结果为+0。如果x是+0且y <0,则结果是+∞。如果x是-0且y> 0且y是奇数,则结果 是-0。如果x是-0且y> 0且y不是奇数,则结果为 + 0。如果x是-0并且y <0并且y是奇数,则结果是-∞。如果x是-0并且y <0并且y不是奇数,则结果是+∞。如果x <0 并且x是有限的,y是有限的,y不是整数,结果是 为NaN。