【问题标题】:C++ optimizer call function after delay延迟后的C ++优化器调用函数
【发布时间】:2018-09-12 23:21:25
【问题描述】:

我正在尝试在 C++ 上对递归斐波那契序列计算器进行基准测试。但令人惊讶的是程序输出0纳秒,并在打印结果后开始计算。 (打印0纳秒后CPU使用率增加)

我认为这是编译器的优化功能。

#include <iostream>
#include <chrono>

int fib2(int n) {
    return (n < 2) ? n : fib2(n - 1) + fib2(n - 2);
}

int main(int argc, char* argv[])
{
    auto tbegin = std::chrono::high_resolution_clock::now();
    int a = fib2(50);
    auto tend = std::chrono::high_resolution_clock::now();

    std::cout << (tend - tbegin).count() << " nanoseconds" << std::endl;

    std::cout << "fib => " << a << std::endl;
}

输出:

0 nanoseconds

是特色吗?如果是,如何禁用此功能?

【问题讨论】:

  • 仅供参考 - 第 50 斐波那契数绝对不适合 int
  • 首先,正如其他人指出的那样,int 可能不适合fib2(50);,这意味着您可能有signed int 溢出,这是未定义的行为,可能导致您的程序执行任何操作。其次,您的结果(如果它适合 int)在编译时很容易计算。编译器可以看到a 将始终具有相同的值,并且可以在编译时计算它。尝试接受用户输入而不是总是计算第 50 项,然后编译器无法假设结果。最后,您永远不会检查 high_resolution_clock::now() 返回的类型。验证时钟的repperiod
  • 考虑使用duration_cast 到纳秒以确保计数符合您的预期。
  • 我尝试使用 uint 并转换为纳秒,但它在打印 0 纳秒后再次计算。似乎编译器重新排序执行。我也发现了这个:stackoverflow.com/questions/26190364/…
  • @CrazyDeveloper 你用的是什么编译器?你使用什么编译标志?编译器可能被允许相对于其他代码对now 重新排序,但没有合理的实现会允许它。请务必尝试让您的 fib2 参数依赖于用户输入,以减少优化的可能性。

标签: c++


【解决方案1】:

问题是这个函数调用的结果是50 不适合int 类型,它太大了。尝试改用int64_t


Live demo

请注意,我将原来的 Fibbonachi 函数替换为更优化的函数,因为执行时间过长,并且在线工具会在一段时间后中断执行。那不是程序或代码的错,只是对在线工具的保护。

【讨论】:

  • 您的示例是对原始代码的改进,但它并没有表明这绝对是 OP 看到的问题的原因。这可能是问题的原因,它肯定是一个问题,但我不相信它回答了这个问题。编辑:虽然我猜这是 UB 的问题,但你不能真正证明 this UB 是问题的根源。
  • @FrançoisAndrieux 这是一个很好的观点,虽然我认为错误的增量时间输出的问题是由 UB 引起的,但这个答案并不能真正证明这一点。跨度>
  • OP 发表了评论,指出传递给unsigned int 并没有解决问题。由于unsigned int 溢出已明确定义,因此问题肯定有其他原因。
  • @FrançoisAndrieux 由于n 可能永远不会低于2,它可能会导致调用堆栈溢出?
  • 如果你暗示无限递归,我不明白怎么做。尽管足够大的n 可能会导致堆栈溢出。请注意,OP 的输出包括经过的时间,但不包括斐波那契计算的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-19
  • 2017-09-06
  • 1970-01-01
相关资源
最近更新 更多