NAN传播和IEEE 754标准
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NAN传播和IEEE 754标准相关的知识,希望对你有一定的参考价值。
我正在设计一个新的微处理器指令集(www.forwardcom.info),我想使用NAN传播来跟踪错误。但是,IEEE 754浮点标准中有许多奇怪的事情可以防止这种情况发生。
首先,我想使用NAN传播而不是错误捕获的原因是我有可变长度的向量寄存器。例如,如果我有一个带有8个元素的浮点向量,并且我在第一个元素中有1/0而在第六个元素中有0/0,那么我只得到一个陷阱,但如果我在计算机上运行相同的程序矢量长度的一半然后我得到两个陷阱:一个用于无穷大,一个用于NAN。我希望结果与向量长度无关,所以我需要依赖于NAN和INF的传播而不是陷阱。 NAN和INF值将通过计算传播,以便在最终结果中检查它们。 NAN表示包含一些称为有效负载的位,可用于有关错误源的信息。
但是,IEEE 754浮点标准中存在两个阻止NAN值可靠传播的问题。
第一个问题是具有不同有效载荷的两个NAN的组合只是两个值中的一个。例如,NAN1 + NAN2给出NAN1。这违反了a + b = b + a的基本原则。编译器可以交换操作数,以便在不同的编译器或不同的优化选项上获得不同的结果。我更喜欢得到两个有效载荷的按位OR组合。如果每个错误条件都有一位,那么这将起作用,但当然,如果有效负载包含更复杂的信息(例如具有动态类型的语言中的NAN装箱),则无效。标准委员会实际上讨论了OR'ing解决方案(参见http://grouper.ieee.org/groups/754/email/msg01094.html)。我不知道他们为什么拒绝这个提议。
第二个问题是如果只有一个输入是NAN,则min和max函数不传播NAN。换句话说,min(1,NAN)= 1.可靠的NAN传播当然需要min(1,NAN)= NAN。我不知道为什么标准会说这个。
在名为ForwardCom的新微处理器系统中,我想避免这些不幸的怪癖并指定NAN1 + NAN2 = NAN1 | NAN2和min(1,NAN)= NAN。
现在我的问题是:首先,我是否需要一个选项切换来在严格的IEEE一致性和可靠的NAN传播之间进行切换?引用标准:
安静的NaN应该由实施者自行决定提供从无效或不可用的数据和结果中继承的回顾性诊断信息。为了便于传播NaN中包含的诊断信息,应尽可能多地保留NaN操作结果中的信息。
注意标准在这里说“应该”,在其他地方有“应该”。这是否意味着我允许偏离建议?
第二个问题:我找不到任何实际使用NAN传播来跟踪错误的例子。也许这是因为标准的弱点。我想为不同的错误条件定义不同的有效负载位,例如:
- 0 / 0,0 *∞,∞/∞,模(1,0),模(∞,1),∞-∞,以及涉及无穷大和除零的其他误差。
- sqrt(-1),log(-1),pow(-1,0.1)以及从对数和幂导出的其他错误。
- asin(2)和其他数学函数。
- 明确的分配。当变量初始化为NAN时,这可能很有用。
用户定义的错误代码有很多空位。
这是否已经完成,或者我是否必须从零开始创造一切?我有什么问题需要考虑(除了某些语言的NAN拳击)
是的,你被允许偏离“应该”。从规范(§1.6):
- 可以表明在标准范围内允许的行动方案,没有隐含的偏好(“可以”表示“允许”)
- 应表明严格遵守强制性要求,以符合标准,并且不允许偏离(“应”表示“需要”)
- 应表明在几种可能性中,建议特别适合一种,不提及或排除其他可能性;或者某种行动方案是首选但不一定是必需的;或者(以否定的形式)某种行为被弃用但不被禁止(“应该”的意思是“推荐给”)。
关于min
的行为,英特尔的实现也与IEEE规范不同。来自MINSD
的Intel指令集参考:
如果第二源操作数中的值是SNaN,则SNaN不变地返回到目的地(即,不返回SNaN的QNaN版本)。
如果该指令只有一个值是NaN(SNaN或QNaN),则将第二个源操作数(NaN或有效浮点值)写入结果。如果不是这种行为,则需要返回NaN源操作数(来自第一个或第二个源),MINSD的操作可以使用一系列指令进行模拟,例如,比较后跟AND,ANDN和要么。
换句话说,它对应于x < y ? x : y
。我不确定他们心中有什么特定的序列,但是这里有一种替代方法https://github.com/JuliaLang/julia/issues/7866#issuecomment-51845730。
一些想法:
第二个问题是如果只有一个输入是NAN,则min和max函数不传播NAN。换句话说,min(1,NAN)= 1.可靠的NAN传播当然需要min(1,NAN)= NAN。我不知道为什么标准会说这个。
下一个IEEE 754修订版的当前草案包含NaN-favoring minimum
和maximum
以及有利于minimumNumber
和maximumNumber
的数字。这意味着应用程序可以选择适合它的内容,但是如果您打算提供一致性,那么您的指令集必须支持两者。 (注意“支持”而不是“实现”。指令集不需要在单个指令中直接实现IEEE 754操作,以使计算平台符合IEEE 754 - 它只需要提供符合要求的平台的指令如果IEEE 754操作需要来自操作系统或库的多个指令或支持,则可以构建。)
现在我的问题是:首先,我是否需要一个选项切换来在严格的IEEE一致性和可靠的NAN传播之间进行切换?
由于您返回的NaN只是标准中的“应该”,因此您无需返回推荐的NaN来声明一致性。但是,minimum(1, NaN)
必须返回NaN。
当然,您不必通过开关来做到这一点,并且环境状态由于其性能拖累而不受欢迎。可以通过附加寄存器或伴随正常寄存器内容的附加位,利用指令的不同指令或不同输入来完成行为之间的选择。
第二个问题:我找不到任何实际使用NAN传播来跟踪错误的例子。
我记得至少有一个IEEE 754委员会成员利用NaN有效载荷,但我不记得是谁或细节。
关于添加两个NAN。当您添加两个具有不同有效负载的NAN时,您只需获得其中一个,通常是第一个。这使得a + b与b + a不同,这是不可接受的,因为编译器可以交换操作数。上面,我建议返回两个有效负载的按位OR组合。考虑到这一点,还有另一种可能的解决方案:返回两个有效载荷中最大的一个。
'OR'解决方案的优点是它很简单。缺点是它会将有效负载中的有用信息限制为每个可能的错误条件一位。但是,它仍然非常有用,因为可以生成NaN的不同事件的数量小于有效载荷比特的数量。
返回两个有效载荷中最大的有效载荷的第二个解决方案需要稍多的硬件。优点是您可以在有效负载中获得更详细的信息,可能包括有关故障发生位置的信息。缺点是您只传播有关两个最差故障的信息。该解决方案与当前标准完全兼容。新的处理器可以实现这一点而无需向后兼容的开关。
为了补充这一讨论,ieee标准明确允许Nan中的错误编码灵活性,但表明它是通过编程语言实现而不是在硬件层完成的。这就是说:我确实喜欢在硬件级别上使用按位或语义支持纳米中毒语义的观点。我一直在探索将这个相同的语义添加到ghc Haskell编译器中。
也就是说,我确实认为捕获语义/信令语义仍然有用。在许多编程语言/程序中,启用的陷阱集可以被视为基础计算中的中止异常。这意味着平台变化的问题是,串联报告一对二错误是不会改变本地计算的“含义”。 (事实上可以说,很多高级编程语言都会受益于支持将信令nans视为异常。这似乎很大程度上缺乏)
以上是关于NAN传播和IEEE 754标准的主要内容,如果未能解决你的问题,请参考以下文章
这是根据 IEEE-754 标准均衡两个不同数字的指数的正确方法吗?