我经常注意到gcc在可执行文件中将乘法转换为移位。当将int和float相乘时,可能会发生类似的情况。例如,2 * f可以简单地将f的指数递增1,从而节省一些周期。编译器,也许如果有人要求他们这样做(例如,通过-ffast-math),通常会这样做吗?
编译器通常是否足够智能来完成这项工作,或者我是否需要使用scalb*()或ldexp()/frexp()函数族自己完成这项工作?
发布于 2012-10-17 00:33:24
例如,
2* f可以简单地将f的指数递增1,从而节省一些周期。
这根本不是真的。
首先,您有太多的角例,如0、无穷大、Nan和非正规化。然后你就有了性能问题。
误解是递增指数的速度并不比乘法快。
如果您查看硬件指令,就会发现没有直接递增指数的方法。所以你需要做的是:
将exponent.
在整数和浮点执行单元之间移动数据通常有中等到较大的等待时间。因此,最终,这种“优化”变得比简单的浮点乘法更糟糕。
所以编译器不做这种“优化”的原因是因为它并不快。
发布于 2012-10-17 01:49:50
在现代CPUs上,乘法通常具有每周期一次的吞吐量和低延迟。如果这个值已经在一个浮点寄存器中,你就不可能通过改变它来在表示上做整数运算来超越它。如果它一开始在内存中,并且假设当前值和正确结果都不是零、非正规、nan或无穷大,那么执行下面这样的操作可能会更快
addl $0x100000, 4(%eax) # x86 asm example乘以2;我认为只有当你在一个从零到无穷大的浮点数据的整个数组上进行操作时,这才是有益的,而2的幂缩放是你唯一要执行的操作(所以你没有任何现有的理由将数据加载到浮点寄存器中)。
发布于 2012-10-17 00:26:43
这不是编译器或编译器编写者不聪明的问题。它更像是遵循标准并产生所有必要的“副作用”,如Infs、Nans和非规范化。
此外,它还可以是关于不产生其他不必要的副作用,例如读取内存。但我确实认识到,在某些情况下,它可能会更快。
https://stackoverflow.com/questions/12919184
复制相似问题