Floating point 为什么非规范浮点值处理起来比较慢?

Floating point 为什么非规范浮点值处理起来比较慢?,floating-point,Floating Point,通常情况下,使用或产生非规范化的浮点值比其他值慢,有时慢得多 为什么会这样?如果这是因为它们被困在软件中,而不是像某些CPU上所说的那样直接在硬件中处理,那么为什么它们必须这样做呢?对于IEEE-754浮点运算,遇到的大多数操作数都是规范化的浮点数,处理器中的内部数据路径都是为规范化的操作数构建的。额外的指数位可用于内部表示,以使浮点操作数始终在数据路径内标准化 因此,任何低于正常值的输入都需要额外的工作,首先确定前导零的数量,然后在调整指数的同时左移正常化的有效位。低于正常值的结果需要将有效位

通常情况下,使用或产生非规范化的浮点值比其他值慢,有时慢得多


为什么会这样?如果这是因为它们被困在软件中,而不是像某些CPU上所说的那样直接在硬件中处理,那么为什么它们必须这样做呢?

对于IEEE-754浮点运算,遇到的大多数操作数都是规范化的浮点数,处理器中的内部数据路径都是为规范化的操作数构建的。额外的指数位可用于内部表示,以使浮点操作数始终在数据路径内标准化

因此,任何低于正常值的输入都需要额外的工作,首先确定前导零的数量,然后在调整指数的同时左移正常化的有效位。低于正常值的结果需要将有效位右移适当的量,四舍五入可能需要推迟到发生之后

如果纯粹在硬件中解决,这项额外的工作通常需要额外的硬件和额外的管道阶段:一个,甚至两个,额外的时钟周期,每个用于处理低于正常的输入和低于正常的输出。但是,典型CPU的性能对指令的延迟非常敏感,需要花费大量精力来保持较低的延迟。FADD、FMUL或FMA指令的延迟通常在3到6个周期之间,具体取决于实现和频率目标

因此,为潜在的次正常操作数处理增加50%的额外延迟是不吸引人的,因为在大多数用例中,次正常操作数是罕见的。因此,使用“使普通情况快速,使不常见情况正常”的设计理念,将次正常操作数的处理从“快速路径”(纯硬件)推到“慢速路径”(现有硬件加软件的组合)是一个巨大的激励

我参与了x86处理器浮点单元的设计,处理次规范的常用方法是在需要处理时调用内部微代码级异常。这种次正常处理可能有100个时钟周期。其中最昂贵的部分通常不是修复代码本身的执行,而是进入和退出微码异常处理程序

我知道一些特定的用例,例如数字信号处理中的特定滤波器,在这些用例中,经常会遇到次正常值。为了快速支持此类应用程序,许多浮点单元支持非标准的齐平归零模式,在这种模式中,次正常编码被视为零

请注意,有些面向吞吐量的处理器设计具有显著的延迟容忍度,特别是GPU。我对NVIDIA GPU很熟悉,我能说的最好的情况是,它们在不增加额外开销的情况下处理低于正常值的操作数,并且在过去十几年中一直如此。这可能是以额外的流水线阶段为代价的,但供应商没有记录这些处理器的许多微体系结构细节,因此很难确定。下面的文章可能会提供一些关于不同硬件设计如何处理低于正常值的操作数的一般见解,其中一些操作数的开销非常小:

E.M.Schwarz,M.Schmookler和S.D.Trong,“非规范化数字的FPU实现”,《计算机上的IEEE交易》,第54卷,第7期,2005年7月,第825-836页