很久以前,在一本有关古代FORTRAN的书中,我看到过这样的说法:将整数常量与浮点变量一起使用会比较慢,因为首先需要将常量转换为浮点形式:

double a = ..;

double b = a*2;   // 2 -> 2.0 first
double c = a*2.0;

在现代C++中编写2.0而不是2仍然有益吗?如果不是这样,可能应该首选“整数版本”,因为2.0更长,并且对人类读者没有任何影响。

我使用复杂的长表达式,这些表达式中的“.0”会影响性能或可读性(如果有的话)。

最佳答案

原始问题:

让我们比较一下程序集的输出。

double foo(double a)
{
        return a * 2;
}

double bar(double a)
{
        return a * 2.0f;
}

double baz(double a)
{
        return a * 2.0;
}

结果是
0000000000000000 <foo>: //double x int
   0:   f2 0f 58 c0             addsd  %xmm0,%xmm0          // add with itself
   4:   c3                      retq                        // return (quad)
   5:   90                      nop                         // padding
   6:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1) // padding
   d:   00 00 00

0000000000000010 <bar>: //double x float
  10:   f2 0f 58 c0             addsd  %xmm0,%xmm0          // add with itself
  14:   c3                      retq                        // return (quad)
  15:   90                      nop                         // padding
  16:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1) // padding
  1d:   00 00 00

0000000000000020 <baz>: //double x double
  20:   f2 0f 58 c0             addsd  %xmm0,%xmm0          // add with itself
  24:   c3                      retq                        // return (quad)

如您所见,它们都是相等的,根本不执行乘法。

即使进行实数乘法(a*5),它们也都相等,并且执行到
0:  f2 0f 59 05 00 00 00    mulsd  0x0(%rip),%xmm0        # 8 <foo+0x8>
7:  00
8:  c3                      retq

加成:

@ Goswin-Von-Brederlow说,使用非常量表达式将导致不同的汇编。让我们像上面的例子那样测试它,但是带有以下签名。
double foo(double a, int b); //int, float, double for foo/bar/baz

导致输出:
0000000000000000 <foo>: //double x int
   0:   66 0f ef c9             pxor   %xmm1,%xmm1  // clear xmm1
   4:   f2 0f 2a cf             cvtsi2sd %edi,%xmm1 // convert edi (second argument) to double
   8:   f2 0f 59 c1             mulsd  %xmm1,%xmm0  // mul xmm1 with xmm0
   c:   c3                      retq                // return
   d:   0f 1f 00                nopl   (%rax)       // padding

0000000000000010 <bar>: //double x float
  10:   f3 0f 5a c9             cvtss2sd %xmm1,%xmm1 // convert float to double
  14:   f2 0f 59 c1             mulsd  %xmm1,%xmm0   // mul
  18:   c3                      retq                 // return
  19:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)     // padding

0000000000000020 <baz>: //double x double
  20:   f2 0f 59 c1             mulsd  %xmm1,%xmm0   // mul directly
  24:   c3                      retq                 // return

在这里,您可以看到(运行时)从类型到 double 类型的转换,这当然会导致(运行时)开销。

关于c++ - 假设a是两倍,2.0 * a比2 * a快吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51261457/

10-09 05:12