use*_*108 46 c c++ optimization performance compiler-optimization
我经常注意到gcc将乘法转换为可执行文件中的移位.当乘以a int和a 时,可能会发生类似的事情float.例如,2 * f可能只是将指数递增f1,从而节省了一些周期.编译器,也许是一个人请求他们这样做(例如通过-ffast-math),一般来说,这样做吗?
编译器通常是否足够聪明,或者我是否需要使用scalb*()或ldexp()/frexp()函数系列自己完成此操作?
Mys*_*ial 80
例如,2*f,可能只是将f的指数递增1,从而节省了一些周期.
这根本不是真的.
首先你有太多的角落情况,如零,无穷大,楠和非正规.然后你就遇到了性能问题.
误解是增加指数并不比进行乘法更快.
如果查看硬件指令,则无法直接增加指数.所以你需要做的是:
在整数和浮点执行单元之间移动数据通常存在中到大延迟.所以最后,这种"优化"变得比简单的浮点乘法更糟糕.
因此,编译器不执行此"优化"的原因是因为它不是更快.
R..*_*R.. 22
在现代CPU上,乘法通常具有每周期一个吞吐量和低延迟.如果该值已经存在于浮点寄存器中,则无法通过对其进行处理以对表示进行整数运算来击败它.如果它在内存中开始,如果你假设当前值和正确的结果都不是零,非正规,纳米或无穷大,那么执行类似的东西可能会更快
addl $0x100000, 4(%eax) # x86 asm example
Run Code Online (Sandbox Code Playgroud)
乘以2; 唯一一次我能看到这是有益的,如果你在一系列浮点数据上操作,这些浮点数据与零和无穷大有限,并且以2的幂为单位缩放是你将要执行的唯一操作(所以您没有任何现有理由将数据加载到浮点寄存器中).
Eri*_*hil 18
常见的浮点格式(尤其是IEEE 754)不会将指数存储为简单整数,并将其视为整数将不会产生正确的结果.
在32位浮点或64位双精度中,指数字段分别为8或11位.指数代码1到254(浮点数)或1到2046(双精度数)的行为类似于整数:如果您将这些值中的一个添加到其中一个,并且结果是这些值之一,则表示的值会加倍.但是,在这些情况下添加一个会失败:
(以上是积极的迹象.情况是对称的,有负面的迹象.)
正如其他人所指出的,某些处理器没有快速操作浮点值位的工具.即使在这样做的情况下,指数字段也不会与其他位隔离,因此通常无法在上面的最后一种情况下将符号位添加到符号位中.
虽然某些应用程序可以容忍快捷方式,例如忽略次正规或NaN甚至无穷大,但应用程序很少会忽略零.因为向指数添加一个无法正确处理零,所以它不可用.
这不是编译器或编译器编写者不聪明.它更像是遵守标准并产生所有必要的"副作用",如Infs,Nans和denormals.
此外,它可能不会产生其他不需要的副作用,例如读取内存.但我确实认识到在某些情况下会更快.
| 归档时间: |
|
| 查看次数: |
3844 次 |
| 最近记录: |