假设 a 是双倍的,2.0*a 比 2*a 快吗?
Assuming a is double, is 2.0*a faster than 2*a?
很久以前,在一本关于古代FORTRAN的书中,我看到过这样的说法,即使用带有浮点变量的整数常量会更慢,因为常量需要先转换为浮点形式:
double a = ..;
double b = a*2; // 2 -> 2.0 first
double c = a*2.0;
在现代C++中编写 2.0 而不是 2 仍然有益吗?如果没有,可能应该首选"整数版本",因为 2.0 更长并且对人类读者没有任何区别。
我使用复杂的长表达式,其中这些".0"将在性能或可读性方面产生影响(如果有的话)。
首先要涵盖其他答案,没有2
vs2.0
不会造成性能差异,这将在编译时检查以创建正确的值。但是要回答这个问题:
在现代C++中写 2.0 而不是 2 仍然有益吗?
绝对。
但这不是因为性能,而是可读性和错误。想象一下以下操作:
double a = (2 / someOtherNumber) * someFloat;
someOtherNumber
的类型是什么?因为如果它是integer
类型,那么您会因为整数除法而遇到麻烦。2.0
或2.0f
具有明显的优势:
- 告诉代码的读者您的意图。
- 避免您无意的整数除法错误。
原始问题:
让我们比较一下程序集输出。
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
在这里,您可以看到从类型到双精度的(运行时)转换,这当然会导致(运行时)开销。
No.
以下代码:
double f1(double a) {
double b = a*2;
return b;
}
double f2(double a) {
double c = a*2.0;
return c;
}
。当使用 Clang 在 gcc.godbolt.org 上编译时,生成以下程序集:
f1(double): # @f1(double)
addsd xmm0, xmm0
ret
f2(double): # @f2(double)
addsd xmm0, xmm0
ret
您可以看到两个函数完全相同,编译器甚至用加法替换了乘法。我希望这个千年的任何C++编译器都是一样的 - 相信他们,他们非常聪明。
不,它不是更快。如果编译器知道整数是什么,为什么还要等到运行时才将整数转换为浮点数?我想如果你完全禁用了优化,你可能会说服一些非常迂腐的编译器这样做,但我所知道的所有编译器都会理所当然地进行优化。
现在,如果您使用浮点类型a
a*b
,b
整数类型,并且两者都不是编译时文字,则在某些体系结构上可能会导致严重的性能影响(特别是如果您最近计算b
)。但是在文字的情况下,编译器已经支持你了。
- 对于 http 请求,python 比 c++ 快吗?
- 如果要求比较器是严格的总排序,而不仅仅是严格的弱排序,C++标准算法会更快吗?
- 假设 a 是双倍的,2.0*a 比 2*a 快吗?
- “std::p ow(double, int)”比“std::p ow(double, double)”快吗?如果是,快
- 类方法变量,如果将它们存储在类本身中会更快吗?
- 在 GPU 上计算积分图像真的比在 CPU 上更快吗?
- C 中的unordered_map/set的哈希功能更快吗?
- C++映射:创建一个临时变量或每次使用键访问值会更快吗
- 是x+=a比x=x+a快吗
- Qt:QML比c++小部件快吗
- 模块会使模板编译更快吗
- CUDA内核2x2 ZgemmBatched:比CuBLAS快5倍.它能跑得更快吗
- 在实践中,无序映射真的比映射快吗
- isdigit() 在 c++ 中不应该更快吗?
- "!="比较运算符比">"快吗?
- 这是可移植C++代码吗?(假设多维数组具有连续的内存布局)
- 循环真的比递归快吗?
- 使用二进制堆从数组中获取前x个整数会更快吗?还是使用快速排序
- 如果程序中没有结构,c++代码运行得更快吗?< / h1 >
- 如果没有if,std::count_if会更快吗