【问题标题】:Inaccuracy in std::chrono::high_resolution_clock? [duplicate]std::chrono::high_resolution_clock 不准确? [复制]
【发布时间】:2012-11-27 23:24:21
【问题描述】:

所以我试图使用 std::chrono::high_resolution_clock 来计时执行某件事需要多长时间。我想你可以找到开始时间和结束时间之间的差异......

为了检查我的方法是否有效,我编写了以下程序:

#include <iostream>
#include <chrono>
#include <vector>

void long_function();

int main()
{
    std::chrono::high_resolution_clock timer;
    auto start_time = timer.now();

    long_function();

    auto end_time = timer.now();
    auto diff_millis = std::chrono::duration_cast<std::chrono::duration<int, std::milli>>(end_time - start_time);

    std::cout << "It took " << diff_millis.count() << "ms" << std::endl;
    return 0;
}

void long_function()
{
    //Should take a while to execute.
    //This is calculating the first 100 million
    //fib numbers and storing them in a vector.
    //Well, it doesn't actually, because it
    //overflows very quickly, but the point is it
    //should take a few seconds to execute.
    std::vector<unsigned long> numbers;
    numbers.push_back(1);
    numbers.push_back(1);
    for(int i = 2; i < 100000000; i++)
    {
        numbers.push_back(numbers[i-2] + numbers[i-1]);
    }
}

问题是,它只是精确地输出 3000 毫秒,而实际上显然不是这样。

在较短的问题上,它只输出 0ms...我做错了什么?

编辑:如果有任何用处,我正在使用带有 -std=c++0x 标志的 GNU GCC 编译器

【问题讨论】:

  • 在我的 windows 框中,它使用 MSVC 17.00.50727.1 (VSExpress2012) 和 GCC 4.8.0 20120924 报告准确的时间
  • Nitpick:更喜欢 typedef std::chrono::high_resolution_clock timer; auto start_time = timer::now(); 因为 now() 是静态成员
  • 我看不出代码有什么问题,对于较短的时间,您可能只需将句点更改为std::nano等。
  • 嗯,定时器的实际滴答周期是未指定的。您将其转换为毫秒(顺便说一句,您可以只使用预定义的持续时间std::chrono::milliseconds)但它可以是任何东西。如果周期是秒,那么预计会得到 1000 的精确倍数。 (当然 high_resolution_clock 希望使用更小的周期,而 IIRC libstdc++ 使用纳秒...)
  • 其实你目前使用的duration-cast可以对你得到的时间有影响,因为你投到duration&lt;int,milli&gt;,这意味着用于内部的类型时间表示变为int。在int 很小的平台上,这可能会导致问题。如果你真的想选择自己的表现类型,intmax_t 会是更好的选择。

标签: c++ c++11 timing chrono


【解决方案1】:

high_resolution_clock 的分辨率取决于平台。

打印以下内容将使您了解您使用的实现的分辨率

    std::cout << "It took " << std::chrono::nanoseconds(end_time - start_time).count() << std::endl;

【讨论】:

    【解决方案2】:

    window7 下的 g++ (rev5, Built by MinGW-W64 project) 4.8.1 也有类似的问题。

    int main()
    {
        auto start_time = std::chrono::high_resolution_clock::now();
        int temp(1);
        const int n(1e7);
        for (int i = 0; i < n; i++)
            temp += temp;
        auto end_time = std::chrono::high_resolution_clock::now();
        std::cout << std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count() << " ns.";
        return 0;
    }
    

    如果 n=1e7 则显示 19999800 ns 但如果 n=1e6 它显示 0 ns。

    精度似乎很弱。

    【讨论】:

    • 您也应该将 'temp' 变量发送到 std::cout,否则,编译器可能只是将它与整个循环一起消除,巧妙地看到您没有对它做任何事情。跨度>
    • 也许 mingw 的高分辨率时钟在那个版本上实际上并不是高分辨率的。看起来大约一到两毫秒(n = 1e6)的东西可能最终为零。也许重复该措施会显示“爆发”,例如在 10 或 15 毫秒,表示大约 10-15 毫秒的低分辨率(Windows 的默认“HZ”值,在 linux 用语中)
    猜你喜欢
    • 2015-05-14
    • 2017-09-02
    • 2014-03-23
    • 2017-08-31
    • 2015-06-04
    • 2017-11-25
    • 2016-09-22
    • 2018-05-21
    • 1970-01-01
    相关资源
    最近更新 更多