Go编译器是否足够聪明,可以进行微优化?
我很好奇像这样使用微优化是否有意义Go编译器是否足够聪明,可以进行微优化?,go,Go,我很好奇像这样使用微优化是否有意义 当a是整数时,a/2与a>>1 a*2vsa简短回答,是的,编译器优化了这些。 但是对于int和uint(以及任何有符号和无符号整数类型,如byte)来说,情况略有不同 在这两种情况下,都避免了乘法和除法指令,但对于无符号整数,它只是一条指令(对于有符号整数,则只有少量指令)。 这是因为您的语句对仅对无符号整数完全等效,而对有符号整数不完全等效 更长的回答: 采用以下简单程序: package main func main() {} func div2(
- 当a是整数时,
与a/2
a>>1
vsa*2
a简短回答,是的,编译器优化了这些。 但是对于
和int
(以及任何有符号和无符号整数类型,如uint
)来说,情况略有不同 在这两种情况下,都避免了乘法和除法指令,但对于无符号整数,它只是一条指令(对于有符号整数,则只有少量指令)。 这是因为您的语句对仅对无符号整数完全等效,而对有符号整数不完全等效 更长的回答: 采用以下简单程序:byte
这里,package main func main() {} func div2(a int) { b := a / 2 c := a >> 1 _, _ = b, c } func mul2(a int) { b := a * 2 c := a << 1 _, _ = b, c } func mod2(a int) { b := a % 2 c := a & 1 _, _ = b, c }
是参数,BX
和DX
似乎是两个结果 (BX
被重新用作结果之一)。 在这里,它们略有不同,但只有一些说明 (查看所示的源行号) 没有任何除法或乘法指令 (所以基本上也一样快)。 这种差异是由于算法移位和逻辑移位以及mod如何处理负值造成的 您可以通过在程序中将BX
更改为int
来确认这一点,然后输出包含以下内容:uint
i、 e.完全相同的说明。0x0008 00008 (…/opt.go:18) ANDQ $1,CX 0x000c 00012 (…/opt.go:19) ANDQ $1,BX
您给出的每个示例都是这样。对您来说很明显,但可能不是下一个处理代码的人:)难道不可能检查Go字节代码以查看编译器是否进行了任何优化吗?要确定发生了什么,您需要查看编译器输出,可能需要使用
。您尝试过任何基准测试吗?至少二十年来,这些类型的优化已经成为编译器的标准。编写有意义的代码,并让编译器进行优化。如果您遇到编译器无法处理的情况,请以道歉的形式写一条评论,说明您为什么要编写如此奇怪的代码。Go build-gcflags=“-s”
如果这些技术非常明显,你为什么要在你的问题中进行并列比较?提示hintI真的不在乎。评论中压倒性的观点似乎与您的观点不一致。这里需要注意的是,编译器正确地识别了可以进行优化的情况,例如在无符号整数上,并避免了无法进行优化的情况,例如有符号整数,其中可能会移动符号位,这将是完全错误的。实际上,它不仅仅是“一两条指令”,但它没有“正常”数学运算中看到的因为这些技术非常明显,甚至不是优化,更像是如何编写代码的偏好问题。
、DIVQ
、或MULQ
,正如塔德曼正确指出的那样,它们确实需要更长的时间才能完全正确地表示有符号整数。IMULQ
0x0008 00008 (…/opt.go:18) ANDQ $1,CX 0x000c 00012 (…/opt.go:19) ANDQ $1,BX