什么样的 GCC 优化可能会根据是否打印来更改双精度?
What kind of GCC optimizations may change a double based on whether it is printed or not?
>我正在调试实现算法的代码,该算法的主循环在语句为真时终止 à las >= u || s <= l
,其中s
、u
和l
double
在主循环中更新。在此示例中,所有三个变量始终介于0.5
和1.5
之间。我在这里不包括代码,因为它不是我写的,提取 MWE 很难。我对代码在不同架构上的行为不同感到困惑,我希望下面的线索可以帮助我缩小算法中的错误范围。
一些浮点舍入似乎是该错误的根本原因。以下是我到目前为止所确定的:
- 该算法在 x86-64 上的所有优化级别上正确终止。
- 该算法在 arm64、mips64 和 ppc64 上以 -O3(未尝试其他选择级别(正确终止。
- 该算法在 i686 上以 -O0 正确终止。
- 该算法在 i686 上无限期地循环使用 -O1、-O2 和 -O3。
-
主要问题点:在算法无限循环的情况下,如果在与
l
和u
进行比较之前打印s
(std::cout << s << std::endl
(,则可以使其正确终止。
什么样的编译器优化可能与这里相关?
上述所有行为都是在GNU/Linux系统上观察到的,并在GCC 6.4、7.3和8.1中重现。
由于您说您的代码在 x86-64 和其他指令集上按预期工作,但在 i686 上中断,但仅在一些优化级别下中断,因此可能的罪魁祸首是 x86 扩展精度。
在 x86 上,浮点指令将结果存储在寄存器中,其精度高于随后将这些值存储在内存中时。因此,当编译器可以重用寄存器中已加载的相同值时,与必须保存并重新加载值时相比,结果可能会有所不同。打印值可能需要保存并重新加载它。
这是GCC中一个众所周知的非错误。
GCC 提供了一个-ffloat-store
命令行选项,可能会有所帮助:
-ffloat-store
不要在寄存器中存储浮点变量,并禁止其他选项,这些选项可能会更改浮点值是从寄存器还是存储器中获取的。
此选项可防止在诸如 68000 之类的机器上出现不希望的过分精度,其中浮动寄存器(68881 的(保持比双精度更高的精度。x86 体系结构也是如此。对于大多数程序来说,过多的精度只会有好处,但少数程序依赖于IEEE浮点的精确定义。在修改此类程序以将所有相关的中间计算存储到变量中后,对此类程序使用
-ffloat-store
。
正如那里提到的,它不会自动让你的代码像在其他指令集上一样工作。您可能需要修改代码以将结果显式存储在变量中。
- 只需要知道我在c ++中打印模式的方式是否有效,或者有另一种方法可以有效地做到这一点
- 有没有办法搜索向量的元素,<String>然后检查它是否包含特定的字符,如果它确实打印了它
- 我的 if 语句打印在我的 while 循环中的每个 if 语句上,无论它是否为假
- 是否有一个标准函数可以打印/监视stdin文件的内容,同时将数据留在stdin中
- 是否可以让 Bitset 将位打印到一行?
- 什么样的 GCC 优化可能会根据是否打印来更改双精度?
- 是否打印指向已定义 int 的成员指针
- QGraphicsItem::p aint(): 如何检查 QGraphicsScene 是否已打印
- 在打印浮点数之前检查浮点数是否为偶数
- 是否有一个很好的方法可以在C 11中打印出像JSON一样的Trie结构(仅迭代解决方案)的扁平命名空间
- 是否有任何操纵器将枚举值打印为字符串?
- C 是否可以使用宏从称呼的地方进行类函数打印
- TCP是否支持不可打印的字符
- CLion 会自动从标准输入打印回输入,是否有任何解决方法
- 是否有任何打印2D阵列C 的快捷方式
- cout.put() 是否推荐使用 cout<< 打印字符
- C++中是否已经有一些类可以打印到 cout,但在未定义某些宏时可以关闭(例如 DEBUG)
- 是否可以在控制台中使用C打印孟加拉语
- 是否可以调试打印当前函数的调用方
- 是否可以通过NM仅打印用户定义的变量