gpt4 book ai didi

c - gcc编译器优化影响浮点比较的结果

转载 作者:行者123 更新时间:2023-12-01 01:24:23 25 4
gpt4 key购买 nike

问题

在使用自动化 CI 测试时,我发现了一些代码,如果 gcc 的优化设置为 -O2,则会中断。如果 double 值在任一方向越过阈值,代码应增加计数器。

解决方法

转到 -O1 或使用 -ffloat-store 选项可以解决此问题。

示例

这是一个显示相同问题的小示例。update()每当 *pNextState * 1e-6 的序列时,函数都应返回 true超过 0.03 的阈值。我使用引用调用,因为这些值是完整代码中大型结构的一部分。

使用 < 背后的想法和 >=就是如果一个序列正好命中了这个值,函数这次应该返回1,下一个循环返回0。

test.h:

extern int update(double * pState, double * pNextState);

test.c:

#include "test.h"

int update(double * pState, double * pNextState_scaled) {
static double threshold = 0.03;
double oldState = *pState;
*pState = *pNextState_scaled * 1e-6;

return oldState < threshold && *pState >= threshold;
}

main.c:

#include <stdio.h>
#include <stdlib.h>

#include "test.h"

int main(void) {

double state = 0.01;
double nextState1 = 20000.0;
double nextState2 = 30000.0;
double nextState3 = 40000.0;

printf("%d\n", update(&state, &nextState1));
printf("%d\n", update(&state, &nextState2));
printf("%d\n", update(&state, &nextState3));

return EXIT_SUCCESS;
}

使用至少 -O2 的 gcc 输出是:

0
0
0

将 gcc 与 -O1、-O0 或 -ffloat-store 一起使用会产生所需的输出

0
1
0

据我了解,如果编译器优化堆栈上的局部变量 oldstate 并与精度更高(80 位)的浮点寄存器中的中间结果和值 *pState 进行比较,则会出现问题。比阈值小一点。如果用于比较的值以 64 位精度存储,则逻辑不会错过阈值。由于乘以 1e-6,结果可能存储在浮点寄存器中。

你会认为这是一个 gcc 错误吗?clang 没有显示问题。

我在 Intel Core i5、Windows 和 msys2 上使用 gcc 版本 9.2.0。

更新

我很清楚浮点比较并不精确,我认为以下结果是有效的:

0
0
1

这个想法是,如果 (*pState >= threshold) == false在一个周期中,然后将相同的值 (oldstate = *pState) 与后续调用中的相同阈值 (*pState < threshold) 进行比较必须是真的。

最佳答案

[免责声明:这是一个通用的,从臀部射击的答案。浮点问题可能很微妙,我没有仔 segmentation 析过这个问题。偶尔,像这样看起来可疑的代码 毕竟可以移植且可靠地工作,并且根据接受的答案,这里似乎就是这种情况。尽管如此,通用答案仍然适用于一般情况。]

我认为这是测试用例中的错误,而不是 gcc。这听起来像是一个典型的代码示例,在精确的浮点相等方面不必要地脆弱。

我会推荐:

  • 重写测试用例,或者也许
  • 删除测试用例。

我会推荐:

  • 通过切换编译器来解决这个问题
  • 通过使用不同的优化级别或其他编译器选项来解决它
  • 提交编译器错误报告[尽管在这种情况下,它似乎存在一个编译器错误,尽管它不需要提交,因为它已经提交了]

关于c - gcc编译器优化影响浮点比较的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58733033/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com