std::chrono::high_resolution_clock 的分辨率与测量值不对应

2021-12-27 00:00:00 c++ c++11 visual-studio-2012 chrono

让我通过这个测试程序问我的问题:

Let me ask my question by this test program:

#include <iostream>
#include <chrono>

using std::chrono::nanoseconds;
using std::chrono::duration_cast;

int main(int argc, char* argv[])
{
    std::cout 
      << "Resolution (nano) = " 
      << (double) std::chrono::high_resolution_clock::period::num / 
                  std::chrono::high_resolution_clock::period::den * 
                  1000 * 1000 * 1000 
      << std::endl;

    auto t1 = std::chrono::high_resolution_clock::now();
    std::cout << "How many nanoseconds does std::cout take?" << std::endl;
    auto t2 = std::chrono::high_resolution_clock::now();

    auto diff = t2-t1;
    nanoseconds ns = duration_cast<nanoseconds>(diff);

    std::cout << "std::cout takes " << ns.count() << " nanoseconds" 
              << std::endl;
    return 0;
}

我机器上的输出:

分辨率(纳米)= 100

Resolution (nano) = 100

std::cout 需要多少纳秒?

How many nanoseconds does std::cout take?

std::cout 需要 1000200 纳秒

std::cout takes 1000200 nanoseconds

我收到 100020010003001000400100050010006002000600 结果(= 1 或 2 微秒).很明显,要么std::chrono的分辨率不是 100纳秒或者我测量std时间的方式::cout 是错误的.(为什么我从来没有收到 1 到 2 微秒之间的信息,例如 1500000?)

I receive either 1000200 or 1000300 or 1000400 or 1000500 or 1000600 or 2000600 as a result (= 1 or 2 microsecond). Obviously, either the resolution of std::chrono is not 100 nano-seconds or the way I measure the time of std::cout is wrong. (Why do I never receive something between 1 and 2 microseconds, for example 1500000?)

我需要一个高分辨率的 C++ 计时器.操作系统本身提供了一个高分辨率计时器,因为我能够在同一台机器上使用 C# Stopwatch 类以微秒精度测量事物.所以我只需要正确使用操作系统拥有的高分辨率计时器!

I need a high-resolution timer in C++. The OS itself provides a high-resolution timer, because I'm able to measure things with microsecond-precision using the C# Stopwatch class on the same machine. So I would just need to correctly use the high-resolution timer that the OS has!

如何修复我的程序以产生预期的结果?

How do I fix my program to produce the expected results?

推荐答案

我猜您正在使用 Visual Studio 2012.如果不是,请忽略此答案.Visual Studio 2012 typedefhigh_resolution_clocksystem_clock.可悲的是,这意味着它的精度很差(大约 1 毫秒).我写了一个更好的高分辨率时钟,它使用 QueryPerformanceCounter 在 Visual Studio 2012 中使用...

I'm going to guess you are using Visual Studio 2012. If not, disregard this answer. Visual Studio 2012 typedef's high_resolution_clock to system_clock. Sadly, this means it has crappy precision (around 1 ms). I wrote a better high-resolution clock which uses QueryPerformanceCounter for use in Visual Studio 2012...

HighResClock.h:

    struct HighResClock
    {
        typedef long long                              rep;
        typedef std::nano                              period;
        typedef std::chrono::duration<rep, period>     duration;
        typedef std::chrono::time_point<HighResClock>  time_point;
        static const bool is_steady = true;

        static time_point now();
    };

HighResClock.cpp:

namespace
{
    const long long g_Frequency = []() -> long long
    {
        LARGE_INTEGER frequency;
        QueryPerformanceFrequency(&frequency);
        return frequency.QuadPart;
    }();
}

HighResClock::time_point HighResClock::now()
{
    LARGE_INTEGER count;
    QueryPerformanceCounter(&count);
    return time_point(duration(count.QuadPart * static_cast<rep>(period::den) / g_Frequency));
}

(我省略了断言和 #ifs 以查看它是否在 Visual Studio 2012 上从上述代码编译.)

(I left out an assert and #ifs to see if it's being compiled on Visual Studio 2012 from the above code.)

您可以在任何地方使用此时钟,使用方式与标准时钟相同.

You can use this clock anywhere and in the same way as standard clocks.

相关文章