我主要对C/C++中的"exp“和"exp2”函数感兴趣,但这个问题可能更多地与IEEE754标准有关,而不是特定的语言特性。
在我大约10年前做的一个家庭作业问题中,它试图按照所需的周期对不同的浮点运算进行排序,C函数
double exp2 (double)看上去比
double exp (double)考虑到"double“对尾数使用二进制表示,我认为这个结果是合理的。
然而,今天,在以几种不同的方式再次测试这两者之后,我看不到任何可衡量的不同之处。所以我的问题是
发布于 2015-05-13 18:51:28
有许多平台对它们的数学库不太在意,exp2(x)只是在其上实现为exp(x * log(2)),反之亦然。这些实现不能提供良好的准确性(或特别好的性能),但它们是相当常见的。在这样做的平台上,一个函数和另一个函数完全一样昂贵,但是对于一个额外的乘法的代价来说,无论哪个函数得到额外的乘法,两者中的任何一个都是慢的。
在积极调整数学库并试图提供良好准确性的平台上,这两个函数的性能非常相似。用exp2生成结果的指数比较容易,但是要获得高精度的意义,可能需要稍微多做一些工作;这两个因素大致相等于通常在10-15%的倍数内的性能。从广义上讲,exp2通常是两者中速度更快的。
发布于 2019-11-24 18:42:10
我做了一些测量,我希望你们中的一些人会发现它有用。
条件:
-static -std=gnu++0x -ffast-math -Ofast -flto守则:
#include <iostream>
#include <random>
#include <cmath>
#include <chrono>
using namespace std;
int main()
{
double g = 1/log(2);
mt19937 engine(1000);
uniform_real_distribution<double> u(0, 1);
double sum = 0;
auto begin = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 1e7/4; ++i) // for non-parallel, `for (int i = 0; i < 1e7; ++i)`
{
sum += exp2(u(engine)*g); // for exp versions, sum += exp(u(engine)); for empty versions, sum += u(engine)*g;
sum += exp2(u(engine)*g); // removed for non-parallel
sum += exp2(u(engine)*g); // removed for non-parallel
sum += exp2(u(engine)*g); // removed for non-parallel
}
auto end = std::chrono::high_resolution_clock::now();
cout << chrono::duration_cast<chrono::nanoseconds>(end - begin).count()/1000./1000 << "ms" << "\t"
<< sum << "\t" << g << " exp2 p4" << endl;
}使用:for i in {1..100}; do ./empty.bin && ./exp2_p4.bin && ./exp_p4.bin && ./exp.bin && ./exp2.bin; done执行
其中,文件名指示可执行文件是调用exp还是exp2,以及求和是否按4 (p4)分组。
结果
下表显示了平均运行时(时间)、毫秒标准差和最快的情况。
| name | time (ms) | std (ms) | smallest (ms) |
|:-------:|:---------:|:--------:|:-------------:|
| empty | 244.7 | 26.2 | 130.9 |
| exp | 591.7 | 95.8 | 422.5 |
| exp2 | 536.5 | 85.4 | 393.7 |
| exp p4 | 612.3 | 89.6 | 433.2 |
| exp2 p4 | 557.2 | 87.6 | 396.8 |对于一个操作,需要使用1e7来划分它。我通过从指数中减去空版本的时间(即做循环和求和而不计算exp)来近似指数的成本。这些值如下所示:

结论
exp2可以比英特尔Xeon和gcc的exp快11%,即使-ffast-math是开着的,这与公认的答案是一致的。
手动循环通过将总和分组为四组而展开,没有帮助。
https://stackoverflow.com/questions/30222836
复制相似问题