首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >exp2应该比exp更快吗?

exp2应该比exp更快吗?
EN

Stack Overflow用户
提问于 2015-05-13 18:40:46
回答 2查看 4.5K关注 0票数 6

我主要对C/C++中的"exp“和"exp2”函数感兴趣,但这个问题可能更多地与IEEE754标准有关,而不是特定的语言特性。

在我大约10年前做的一个家庭作业问题中,它试图按照所需的周期对不同的浮点运算进行排序,C函数

代码语言:javascript
复制
double exp2 (double)

看上去比

代码语言:javascript
复制
double exp (double)

考虑到"double“对尾数使用二进制表示,我认为这个结果是合理的。

然而,今天,在以几种不同的方式再次测试这两者之后,我看不到任何可衡量的不同之处。所以我的问题是

  • exp2应该(理论上)比exp更快吗?和
  • 应该有什么可衡量的差别吗?和
  • 最近几年,答案是否有所改变?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-05-13 18:51:28

有许多平台对它们的数学库不太在意,exp2(x)只是在其上实现为exp(x * log(2)),反之亦然。这些实现不能提供良好的准确性(或特别好的性能),但它们是相当常见的。在这样做的平台上,一个函数和另一个函数完全一样昂贵,但是对于一个额外的乘法的代价来说,无论哪个函数得到额外的乘法,两者中的任何一个都是慢的。

在积极调整数学库并试图提供良好准确性的平台上,这两个函数的性能非常相似。用exp2生成结果的指数比较容易,但是要获得高精度的意义,可能需要稍微多做一些工作;这两个因素大致相等于通常在10-15%的倍数内的性能。从广义上讲,exp2通常是两者中速度更快的。

票数 10
EN

Stack Overflow用户

发布于 2019-11-24 18:42:10

我做了一些测量,我希望你们中的一些人会发现它有用。

条件:

  • 英特尔(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz (服务器在测试期间有很高的CPU负载)
  • 编译器版本: g++ (Ubuntu5.4.0-6 ubuntu1~16.04.12) 5.4.0 20160609
  • 编译器选项:-static -std=gnu++0x -ffast-math -Ofast -flto

守则:

代码语言:javascript
复制
#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)分组。

结果

下表显示了平均运行时(时间)、毫秒标准差和最快的情况。

代码语言:javascript
复制
|   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是开着的,这与公认的答案是一致的。

手动循环通过将总和分组为四组而展开,没有帮助。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30222836

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档