std::cos 在使用 valgrind 运行时给出不同的结果

std::cos gives different result when run with valgrind

提问人:Yattabyte 提问时间:1/12/2023 最后编辑:phuclvYattabyte 更新时间:1/12/2023 访问量:535

问:

我发现了一个影响我工作中几个单元测试的问题,这仅在使用 valgrind 运行单元测试时才会发生,因为对于相同的输入,从 std::cos 和 std::sin 返回的值不同,具体取决于单元测试是单独运行还是在 valgrind 下运行。

此问题似乎只发生在某些特定输入中,因为许多单元测试通过相同的代码运行。

这是一个最低限度的可重复示例(略微恶化,以便我的编译器不会优化任何逻辑):

#include <complex>
#include <iomanip>
#include <iostream>

int main()
{
    std::complex<long double> input(0,0), output(0,0);

    input = std::complex<long double>(39.21460183660255L, -40);
    std::cout << "input: " << std::setprecision(20) << input << std::endl;

    output = std::cos(input);
    std::cout << "output: " << std::setprecision(20) << output << std::endl;

    if (std::abs(output) < 5.0)
    {
        std::cout << "TEST FAIL" << std::endl;
        return 1;
    }

    std::cout << "TEST PASS" << std::endl;
    return 0;
}

正常运行时输出:

input: (39.21460183660254728,-40)
output: (6505830161375283.1118,117512680740825220.91)
TEST PASS

在 valgrind 下运行时的输出:

input: (39.21460183660254728,-40)
output: (0.18053126362312540976,3.2608771240037195405)
TEST FAIL

笔记:

  • 操作系统: Red Hat Enterprise Linux 7
  • 编译器:英特尔 OneAPI 2022 下一代 DPP/C++ 编译器
  • Valgrind:3.20(使用相同的编译器构建),也出现在 3.17 的官方发行版上
  • 当使用 GCC-7(无法返回到该编译器)或 GCC-11(boost 的另一个更大的错误阻止我们在 valgrind 中使用它)构建单元测试时,问题没有出现
  • -O0/1/2/3 在这个问题上没有区别
  • 我设置的唯一编译器标志是“-fp-speculation=safe”,否则,如果未设置,则会导致其他单元测试中的数值精度问题

有没有更好的方法可以弄清楚发生了什么来解决这种情况,或者我应该向 valgrind 提交错误报告?我希望这个问题是良性的,但我希望能够信任我的 valgrind 输出。

C 浮点 精度 valgrind c++-standard-library

评论

1赞 bolov 1/12/2023
编译器(不带 valgrind)是否用 和 给出相同的输出?-O0-O2-O3
2赞 Ted Lyngmo 1/12/2023
是否在一个版本中启用了或任何其他“使浮点数学快速”选项,而在另一个版本中未启用?请显示您在这两种情况下使用的所有编译器选项。-ffast-math-Ofast
2赞 Ted Lyngmo 1/12/2023
如果您展示了所使用的确切选项集,我们也许可以帮助排除在valgrind运行程序时使其行为异常的任何选项中的任何一个。也许牵强附会,但是,你永远不知道。编辑:我自己刚刚测试了它,它确实给出了两种不同的输出。g++ -o valtry valtry.cpp
2赞 Eric Postpischil 1/12/2023
如果您使用而不是 ?如果将虚部设置为 0,它们会有所不同吗?如果将虚部设置为 0,将实部设置为 0,它们会有所不同吗?π/2?π?到2π?到8?16?32?顺便说一句,为什么要使用带有 的常量,而不是?doublelong doubleinputdoublelong double39.2146018366025539.21460183660255L
9赞 Paul Floyd 1/12/2023
这听起来像是这个 bugs.kde.org/show_bug.cgi?id=333625 问题的重复。它需要调试到操作码级别,以查看差异所在。最有可能的情况是 ICC 正在使用 Valgrind VM 未正确模拟的操作码。

答: 暂无答案