Chrono C++ 计时不正确

Chrono C++ timings not correct

我只是比较几个斐波那契函数的速度,一个几乎立即给出输出并读取它在 500 纳秒内完成,而另一个,取决于深度,可能会坐在那里加载很多秒,然而当它完成时,它会显示只用了 100 纳秒......在我坐在那里等了 20 秒之后。

这没什么大不了的,因为我可以证明另一个只是人类原始感知速度较慢,但​​为什么 chrono 不起作用?与递归有关?

PS 我知道 fibonacci2() 在奇数深度上没有给出正确的输出,我只是在测试一些东西,输出实际上就在那里,所以编译器没有优化它离开什么的。继续,只需复制此代码,您将立即看到 fibonacci2() 输出,但您必须等待 5 秒才能看到 fibonacci()。谢谢。

#include <iostream>
#include <chrono>


int fibonacci2(int depth) {

    static int a = 0;
    static int b = 1;

    if (b > a) { 
        a += b; //std::cout << a << '\n'; 
    }
    else { 
        b += a; //std::cout << b << '\n'; 
    }

    if (depth > 1) {
        fibonacci2(depth - 1);
    }

    return a;
}

int fibonacci(int n) {

    if (n <= 1) {
        return n;
    }

    return fibonacci(n - 1) + fibonacci(n - 2);
}


int main() {

    int f = 0;

    auto start2 = std::chrono::steady_clock::now();
    f = fibonacci2(44);
    auto stop2 = std::chrono::steady_clock::now();
    std::cout << f << '\n';
    auto duration2 = std::chrono::duration_cast<std::chrono::nanoseconds>(stop2 - start2);
    std::cout << "faster function time: " << duration2.count() << '\n';

    auto start = std::chrono::steady_clock::now();
    f = fibonacci(44);
    auto stop = std::chrono::steady_clock::now();
    std::cout << f << '\n';
    auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(stop - start);
    std::cout << "way slower function with incorrect time: " << duration.count() << '\n';

}

我不知道您使用的是什么编译器以及使用哪些编译器选项,但我在 godbolt 中使用 /O2 测试了 x64 msvc v19.28。这里编译的指令被重新排序,这样它在调用 fibonacci(int) 函数之前查询 perf_counter 两次,在代码中看起来像

auto start = ...;
auto stop = ...;
f = fibonacci(44);

禁止这种重新排序的解决方案可能是在 fibonacci 函数调用前后使用 atomic_thread_fence

正如 Mestkon 回答的那样,编译器可以重新排序您的代码。 如何防止编译器重新排序的示例 Memory Ordering - Compile Time Memory Barrier

如果您提供有关您使用的编译器的信息,这将对将来有所帮助。

例如带有 -O2 的 gcc 7.5 不会在此给定场景中重新排序定时器指令。