什么比std :: pow更快?

qua*_*ant 18 c++ performance

我的程序在该std::pow(double,int)函数中花费了90%的CPU时间.准确性不是这里的主要关注点,所以我想知道是否有更快的替代品.我想要尝试的一件事是铸造浮动,执行操作然后再加倍(尚未尝试过); 我担心这不是一种提高性能的可移植方式(不管大多数CPU本质上都是双重操作吗?)

干杯

Sha*_*our 15

看起来Martin Ankerl有一些关于此的文章,C/C++中的Optimized Approximative pow()是一个,它有两个快速版本,一个如下:

inline double fastPow(double a, double b) {
  union {
    double d;
    int x[2];
  } u = { a };
  u.x[1] = (int)(b * (u.x[1] - 1072632447) + 1072632447);
  u.x[0] = 0;
  return u.d;
}
Run Code Online (Sandbox Code Playgroud)

从草案标准部分9.5 [class.union]中依赖于C++中未定义行为的联合类型惩罚:

在并集中,至多一个非静态数据成员可以在任何时间处于活动状态,也就是说,任何时候最多一个非静态数据成员的值都可以存储在并集中.[...]

但是包括gcc在内的大多数编译器都支持定义良好的行为:

从不同的工会成员阅读的做法比最近写的那个(称为"打字式")很常见.即使使用-fstrict-aliasing,只要通过union类型访问内存,就允许类型为punning

但是这并不是普遍的,正如本文所指出的那样,正如我在这里的回答中所指出的,使用memcpy应生成相同的代码并且不会调用未定义的行为.

他还链接到第二个优化的pow()近似Java,C/C++和C#.

第一篇文章还链接到自己的微基准这里


hob*_*bbs 10

根据您的需要,在日志域中操作可能会起作用 - 也就是说,您将所有值替换为其对数; 乘法变为加法,除法成为减法,取幂成为乘法.但现在加法和减法变得昂贵且有些容易出错的操作.


Dav*_*men 5

您的整数有多大?他们在编译时知道吗?这是好得多计算x^2x*x,而不是pow(x,2)。注意:几乎所有pow()对整数次幂的应用都涉及将某个数字提高到第二或三次幂(如果是负指数,则乘以逆)。pow()在这种情况下,使用是过大的。为这些小的整数幂使用模板,或仅使用x*x

如果整数很小,但在编译时未知(例如在-12和+12之间),则乘法仍然有效pow()并且不会丢失精度。您不需要十一个乘法即可计算x ^ 12。四个会做。使用x ^(2n)=(x ^ n)^ 2和x ^(2n + 1)= x *((x ^ n)^ 2)的事实。例如x ^ 12是((x * x * x)^ 2)^ 2。两次乘法计算x ^ 3(x * x * x),再乘一次计算x ^ 6,最后一次乘法计算x ^ 12。