问题描述
可以在同一空间中存储一对32位单精度浮点数,这将由64位双精度浮点数占用。例如,SSE2指令集的XMM寄存器可以存储四个单精度数字或两个双精度数字。
根据IEEE 754标准,单精度和双精度之间的区别不仅在于精度本身,还在于可用范围:分别为8和11个指数位。
直觉上,在我看来,如果您要设计一个FPU来并行处理2N个单精度数字或N个双精度数字,那么如果您偏离IEEE标准并使两者都使用相同的电路,则电路设计应该更简单。指数位数。例如,bfloat16半精度格式折衷了一些尾数位,以保持与单精度相同数量的指数位;给出的理由的一部分是,在bfloat16和单精度之间进行转换更容易。
任何实际的矢量指令集是否使用相同数量的指数位用于单精度和双精度?如果是这样,它们是单精度接近8位还是双精度接近11位?
解决方法
AFAIK,没有人这样做。与在整体上构建FPU执行单元的晶体管成本相比,符号扩展和零扩展在硬件上显得微不足道。
将指数和尾数位放在需要的地方并不重要,与构建一个可以用作一个52位乘法器或2个单独的23位乘法器的乘法器相比,这没什么大不了的。 (这样一来,相同的晶体管可用于单重和双倍乘法/ FMA的尾数;这是FMA /乘法器单元裸片面积的很大一部分。)
AFAIK,所有足够现代的CPU都具有SIMD的都使用IEEE-754格式,因为这是人们想要的,并且没有令人信服的理由这样做。当然,其中绝大多数使用标准格式。
例如,ARM NEON最初不支持完整的IEEE 754,但是他们所忽略的是逐渐下溢(超常态)。他们仍然使用IEEE binary32和binary64(标准的float和double)数据格式。
,任何实际的矢量指令集对单精度和双精度使用相同数量的指数位吗?
我不清楚。但是,如果您不一定需要矢量,则x87硬件就是这样做的。硬件的位数比双精度还要多,内部格式为80位,它们的指数使用15位,尾数使用64位。
FPU有一个控制寄存器,它指定了3个可能的值(32、64或80位)来指定精度。设置为32位时,每条指令舍入尾数并截断指数,使±INF或为零。
现代编译器不再发出这些指令,而是使用SSE向量寄存器的最低通道。
如果您偏离IEEE标准并使用相同数量的指数位,则电路设计应该更简单。
是的。这正是英特尔在1980年推出8087 FPU的方式,整个芯片只有4.5万个晶体管。
但是,现代CPU拥有数十亿个晶体管的预算。设计的简单性不再是重中之重。性能和功耗。
就性能而言,8087最多花费200个周期来划分两个浮点数。我当前的CPU(AMD Zen2)最多花费10个周期划分32位浮点数(一次8个),最多花费13个周期划分64位浮点数(一次4个)。从200个周期开始有了巨大的进步,但是代价是复杂性和晶体管数量。