c++ - NAN 传播和 IEEE 754 标准

标签 c++ floating-point nan cpu-architecture ieee-754

我正在设计一个新的微处理器指令集 ( www.forwardcom.info ),我想使用 NAN 传播来跟踪错误。然而,IEEE 754 浮点标准中有许多奇怪之处阻止了这一点。

首先,我想使用 NAN 传播而不是错误捕获的原因是我有可变长度的 vector 寄存器。例如,如果我有一个包含 8 个元素的浮点 vector ,第一个元素为 1/0,第六个元素为 0/0,那么我只会得到一个陷阱,但是如果我在计算机上运行相同的程序 vector 长度的一半然后我得到两个陷阱:一个用于无穷大,一个用于 NAN。我希望结果独立于 vector 长度,因此我需要依赖 NAN 和 INF 的传播而不是捕获。 NAN 和 INF 值将通过计算传播,以便可以在最终结果中检查它们。 NAN 表示包含一些称为有效载荷的位,可用于有关错误源的信息。

但是,IEEE 754 浮点标准中有两个问题阻碍了 NAN 值的可靠传播。

第一个问题是两个具有不同有效负载的 NAN 的组合只是两个值中的一个。例如 NAN1 + NAN2 得到 NAN1。这违反了 a+b = b+a 的基本原则。编译器可以交换操作数,以便您在不同的编译器或使用不同的优化选项时获得不同的结果。我更喜欢获取两个有效载荷的按位或组合。如果每个错误条件都有一位,这将起作用,但如果有效负载包含更复杂的信息(例如具有动态类型的语言中的 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 传播之间切换?引用标准:

Quiet NaNs should, by means left to the implementer’s discretion, afford retrospective diagnostic information inherited from invalid or unavailable data and results. To facilitate propagation of diagnostic information contained in NaNs, as much of that information as possible should be preserved in NaN results of operations.

请注意,标准在这里说“应该”,而在其他地方说“应该”。这是否意味着我可以偏离建议?

第二个问题: 我找不到任何实际使用 NAN 传播来跟踪错误的示例。也许这是因为标准的弱点。我想为不同的错误条件定义不同的有效负载位,例如:

  1. 0/0、0*∞、∞/∞、模 (1,0)、模 (∞,1)、∞-∞ 和其他涉及无穷大和被零除的错误。

  2. sqrt(-1)、log(-1)、pow(-1,0.1) 和其他源自对数和幂的错误。

  3. asin(2) 和其他数学函数。

  4. 显式赋值。这在将变量初始化为 NAN 时非常有用。

用户定义的错误代码有很多空位。

这是以前做过的吗,还是我必须从头开始发明一切?有什么我必须考虑的问题吗(除了某些语言的 NAN 装箱)

最佳答案

是的,您可以偏离“应该”。来自规范(§1.6):

may indicates a course of action permissible within the limits of the standard with no implied preference (“may” means “is permitted to”)

shall indicates mandatory requirements strictly to be followed in order to conform to the standard and from which no deviation is permitted (“shall” means “is required to”)

should indicates that among several possibilities, one is recommended as particularly suitable, without mentioning or excluding others; or that a certain course of action is preferred but not necessarily required; or that (in the negative form) a certain course of action is deprecated but not prohibited (“should” means “is recommended to”).

关于 min 的行为, Intel 的实现也不同于 IEEE 规范。来自 MINSD 的 Intel 指令集引用:

If a value in the second source operand is an SNaN, then SNaN is returned unchanged to the destination (that is, a QNaN version of the SNaN is not returned).

If only one value is a NaN (SNaN or QNaN) for this instruction, the second source operand, either a NaN or a valid floating-point value, is written to the result. If instead of this behavior, it is required that the NaN source operand (from either the first or second source) be returned, the action of MINSD can be emulated using a sequence of instructions, such as, a comparison followed by AND, ANDN and OR.

也就是说对应于x < y ? x : y . (有关详细信息,请参阅 Argument order to std::min changes compiler output for floating-point:这是 C++ std::min不是包装 IEEE-754 NaN 传播 fmin 操作的 C 数学库 minimum。)

我实际上不确定他们在想什么特定的顺序,但这里有一个建议的替代方法 https://github.com/JuliaLang/julia/issues/7866#issuecomment-51845730 .

关于c++ - NAN 传播和 IEEE 754 标准,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49011370/

相关文章:

c++ - noexcept 关键字和 _NOEXCEPT 宏有什么区别?

c++ - 将数组分配给 std::vector 会给出不正确的输出

python - pylab直方图去掉nan

c++ - Callgrind:分析我的代码的特定部分

C++, boost : How to store objects of an abstract type in a map container

c# - 将 float 从 Fortran 传递到 .Net

python - 为什么 is_integer() 方法不起作用?

c++ - float 倍数和除法精度问题

javascript - 为什么 typeof 的结果与传入的表达式的计算结果不同?

c# - double.NaN MS 测试中的相等性