问题标签 [denormal-numbers]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 将刷新非规范化设置为零的强大、便携的方法?
我正在使用一些代码,这些代码使用内联 Intel X86_64 程序集来设置处理器的 SSE 标志,以包括 flush-denormal-to-zero 和 Treat-denormals-as-zero:stmxcsr
然后ldmxcsr
.
我不是特别喜欢这种方法(我们将其称为方法 1)。Wikipedia page on denormals建议了其他一些选项:
- 使用环境变量:
- 使用 XMM 寄存器的标头之一:
- 使用更多标题和一些宏:
...但我也不太喜欢这些。它们不在任何通用/标准库中;当然,它们是特定于英特尔的。如果我在 ARM 上怎么办?我可能还想这样做。我也不确定其中哪些将与哪个编译器一起使用(维基百科说其中一些它们“可能工作”)。
那么,我应该如何最好地告诉我的处理器将非规范化刷新为零?
注意:我的问题并没有真正区分 C 和 C++。我对 C++ 习语感兴趣,但如果只有“C'ish”习语,我可以接受。
floating-point - 当我们考虑将 DAZ 标志用于 SSE 浮点时,“非正规输入”在汇编中究竟意味着什么
我已经阅读了这篇文章和do-denormal-flags-like-denormals-are-zero-daz-affect-comparisons-for-equality,我了解 FTZ 和 DAZ 标志之间的用法和区别。
DAZ 适用于输入,FTZ 适用于 FP 操作的输出。
让我感到困惑的是,如果设置了 FTZ,那么汇编视图中的非规范值来自哪里。我认为它只能是常量值,既可以是直接操作数,也可以是节.rodata
(通过 RIP 相对寻址访问)。
但是我在我的二进制文件中发现,这些地方没有异常值,但它仍然存在 FP-ASSIST 问题,导致性能不佳。
如果我同时设置 DAZ 和 FTZ,问题就会消失并且性能会变得更好。实际上,我什至在我的源代码中都没有找到任何非正规输入。我真的很困惑,异常值来自哪里?
另外一个问题,对于指令vmovsd 0x9498(%rip),%xmm0
,假设0x9498(%rip)
是一个非正规值,xmm0
如果我们分别设置 FTZ 或 DAZ,这条指令执行后会发生什么?
据我了解,DAZ 会将其0x9498(%rip)
设为零并0
移至 xmm0;FTZ 将移动0x9498(%rip)
到 xmm0 并发现它是非正规的,因此刷新xmm0
为零。我不确定,是否正确?
performance - 非规范化浮点数:哪些操作会触发昂贵的特殊情况?
非规范化浮点数在某些运算(加法、乘法)中需要昂贵的特殊处理。虽然这是众所周知的,但在我看来,还有许多相对简单的操作可能不会受到这种惩罚的影响。我无法很好地了解不同平台上哪些东西是“安全的”,并且想知道这里的其他人是否知道更多。对于以下几类操作,我对 x86-64 和 CUDA/PTX 的答案特别感兴趣。
- 浮点比较
- 绝对值
- 舍入操作(ceil、floor、trunc、round)
- 转换(单 ↔ 双,浮点 ↔ 整数)
assembly - 是否非规范化 2 个浮点数的乘积
我试图在不使用浮点指令的情况下将 2 个浮点数相乘。在我遇到非规范化数字之前,一切都很顺利。我如何知道我应该对产品进行规范化还是非规范化?这种不确定性使得对产品进行四舍五入变得困难。我的直觉告诉我,如果两个因素都是非规范化的数字,则产品应该是非规范化的。
assembly - cmpeqpd 有时会返回错误的值
出于某种原因,有时在我的程序中我看到
where xmm0 == {0x2cd000000000, 0x2cd000000000}
andxmm3 == {0x0, 0x2011d0800000000}
恰好在 xmm3 中返回{0xffffffffffffffff, 0x0}
,这是错误的,因为(double)0x0
不等于(double)0x2cd000000000
.
我注意到它只是偶尔发生。我已经用 rr 记录了程序的执行,以便一致地重现它。有趣的是,在一个超级简化的简单程序中,我再也无法重现这个问题了。我想知道,是否有任何隐藏的微架构状态可以改变 cmpeqpd (cmppd) 行为?
请注意,我检查了相应 ymm 寄存器中的高 128 位是否为零。
c++ - 为什么将小浮点数与零进行比较会产生随机结果?
我知道浮点数很棘手。但是今天我遇到了一个我无法解释的案例(并且无法使用独立的 C++ 代码重现)。
大型项目中的代码如下所示:
这段代码会导致随机行为。使用gdb,可以确定随机行为是由于比较f == 0
给出随机结果,即有时为真,有时为假。代码中的错误是,在使用之前f
,它应该检查 4 字节是否应该被解释为整数(使用其他辅助信息)。解决方法是先将其转换回整数,然后将整数与 0 进行比较。然后问题就解决了。
此外,如果需要进行浮点数比较(在这种情况下,浮点数不是如上所示从整数转换),我还将比较更改为abs(f) < std::numeric_limits<float>::epsilon()
, 以更安全。
之后,我也想用一个简单的测试程序来重现它,但似乎我无法重现它。(但用于项目的编译器与我用于编译测试程序的编译器不同)。以下是测试程序:
我想知道,与零比较的随机行为可能是什么原因?