将int值添加到双精度时是否存在性能优势/惩罚?

时间:2013-11-25 11:11:50

标签: c++

给出一个向量加法:

  NPNumber NPNumber::plus(const double o) const {
    vector<double> c;
    for (double a : values)
       c.push_back(a + o);

    return NPNumber(width, c);
  }

当NPNumber包含双精度矢量(字段值)时,当我只添加一个整数而不是另一个NPNumber时,与转换该整数并使用上述函数相比,是否存在性能优势或损失?

即,在任何架构上这都更快/更慢:

  NPNumber NPNumber::plus(const int i) const {
    vector<double> c;
    for (double a : values)
       c.push_back(a + i);

    return NPNumber(width, c);
  }

2 个答案:

答案 0 :(得分:4)

强烈依赖编译器,你应该在你的代码中测量它。在我的机器上进行快速简单的观察(32位MinGW / gcc 4.9)显示+本身在两种情况下都是相同的,但积分运算看起来好一些。

添加两个double

!        double d = 0.2;
fldl   0x409070
fstpl  -0x10(%ebp)

!        double y = 1.0;
fld1   
fstpl  -0x18(%ebp)

!        double z = d + y;
fldl   -0x10(%ebp)
faddl  -0x18(%ebp)
fstpl  -0x20(%ebp)

添加两个int

!        double d = 0.2;
fldl   0x409070
fstpl  -0x28(%ebp)

!        int y = 1;
movl   $0x1,-0x2c(%ebp)

!        double z = d + y;
fildl  -0x2c(%ebp)
faddl  -0x28(%ebp)
fstpl  -0x38(%ebp)

两者都使用faddl来添加,但编译器在添加之前使用更好的指令来加载整数。因此,将一个整数添加到double中没有任何惩罚(它可能更好,而不是添加两个双精度)。

在您的应用程序中,分析是找出哪个更好的最佳方式。

答案 1 :(得分:2)

需要考虑的另一件事是编译器优化。

浮点单元往往有自己的寄存器。在某些情况下,这些甚至可能比典型的操作数具有更高的精度(例如,80位临时实数;)但是,请参阅注释,因为这可能会有很大差异。

我希望对已加载到FPU中的值进行操作会更便宜,编译器应该知道这一点。因此,它可以提升你的常量值从循环中提升并保持值加载到FPU中,在这种情况下,大矢量上的差异可以忽略不计。

无论如何,我希望如果intdouble转换在给定平台上很昂贵,那么可敬的编译器就不会冗余地执行它。因此,我可能会做的是使它成为一种模板方法,这样你就可以接受任何类型的&amp;精度恒定数据自然来自;这允许编译器在任何给定情况下为特定平台“做正确的事情”。

话虽如此,编译器的优化策略确实有很大不同,平台的功能和功能各不相同。性能特征,所以如果你试图挤出每一个微秒,你应该对你感兴趣的平台进行分析。