为什么编译器不将浮点 *2优化到指数增量中?[英] Why doesn't a compiler optimize floating-point *2 into an exponent increment?

本文是小编为大家收集整理的关于为什么编译器不将浮点 *2优化到指数增量中?的处理方法,想解了为什么编译器不将浮点 *2优化到指数增量中?的问题怎么解决?为什么编译器不将浮点 *2优化到指数增量中?问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

我经常注意到GCC将乘法转换为可执行文件中的变化.乘以int和a float时可能会发生类似的事情.例如,2 * f可以简单地将f的指数递增1,节省一些周期.编译器,如果有人要求他们这样做(例如,通过-ffast-math),通常会这样做吗?

编译器通常足够聪明,可以做到这一点,或者我需要使用scalb*()或ldexp()/frexp()函数自己自己做?

推荐答案

例如,2 * f,可以简单地将f的指数增加到1, 节省一些周期.

这根本不是真的.

首先,您有太多的角病例,例如零,无穷大,nan和denormals.然后您有性能问题.

误解是,增加指数的速度不比执行乘法更快.

如果您查看硬件说明,则没有直接的方法来增加指数. 因此,您需要做的是:

  1. 位转换为整数.
  2. 增加指数.
  3. 位转换回浮点.

通常,在整数和浮点执行单元之间移动数据的中等至大延迟.因此,最后,这种"优化"变得比简单的浮点倍数差得多.

因此,编译器不执行此"优化"的原因是因为它不会更快.

其他推荐答案

在现代 cpus ,乘法通常通常具有单周期吞吐量和低度吞吐量潜伏.如果该值已经在浮点寄存器中,则不可能通过将其杂乱无章地在表示形式上进行整数算术来击败它.如果首先要记忆,并且如果您假设当前值和正确的结果既不为零,denormal,nan或infinity,则可以更快地执行 /p>

addl $0x100000, 4(%eax)   # x86 asm example

乘以两个;我唯一可以看到这是有益的是,如果您在一系列浮点数据上进行操作,这些数据远离零和无穷大,而按两个功率缩放是您要执行的唯一操作(所以您没有任何现有的理由将数据加载到浮点寄存器中).

其他推荐答案

公共浮点格式,尤其是IEEE 754,不要将指数存储为简单的整数,并且将其视为整数不会产生正确的结果.

在32位浮点或64位双重的情况下,指数字段分别为8或11位.指数代码1至254(以浮点)或1至2046(以双重)的形式起作用,确实像整数:如果将其中一个添加到其中一个值,结果是这些值之一,则表示代表的值双打.但是,在这些情况下添加一个失败:

  • 初始值为0或亚正常.在这种情况下,指数字段始于零,并在其中添加一个 -126 (在float中)或2 -1022 (以双重)为数字;它不会使数字翻倍.
  • 初始值超过2 127 (在float中)或2 1023 (以双重).在这种情况下,指数字段从254或2046开始,然后将一个字段添加到NAN.它不会使数字翻倍.
  • 初始值是无穷大或nan.在这种情况下,指数字段从255或2047开始,然后将其添加到零(并且很可能溢出到符号位).结果是零或亚正常,但应分别为无穷大或nan.

(以上是正符号.情况是对称的,带有负标志.)

正如其他人所指出的那样,某些处理器没有快速操纵浮点值的设施.即使在那些执行的操作上,指数字段也不是与其他位隔离的,因此您通常不会在上面的最后一个情况下不流入符号位.

.

尽管某些应用可以忍受诸如忽视亚正常或NAN甚至无限的捷径,但很少有应用可以忽略零.由于将一个添加到指数无法正确处理零,因此无法使用.

本文地址:https://www.itbaoku.cn/post/359138.html