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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16299029/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 20:14:46  来源:igfitidea点击:

Resolution of std::chrono::high_resolution_clock doesn't correspond to measurements

c++visual-studio-2012c++11chrono

提问by javapowered

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;
}

Output on my machine:

我机器上的输出:

Resolution (nano) = 100

How many nanoseconds does std::cout take?

std::cout takes 1000200 nanoseconds

分辨率(纳米)= 100

std::cout 需要多少纳秒?

std::cout 需要 1000200 纳秒

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

结果我收到1000200or or 1000300or 1000400or 1000500or 1000600or 2000600(= 1 或 2 微秒)。显然,任该决议std::chrono不是100毫微秒我的方式测量的时间std::cout是错误的。(例如,为什么我永远不会收到 1 到 2 微秒之间的信息1500000?)

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# Stopwatchclass on the same machine. So I would just need to correctly use the high-resolution timer that the OS has!

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

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

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

回答by David

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

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

HighResClock.h:

高分辨率时钟.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:

高分辨率时钟.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));
}

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

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

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

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

回答by bames53

The resolution of a clock is not necessarily the same as the smallest duration that can be represented by the data type the clock uses. In this case your implementation uses a data type which can represent a duration as small as 100 nanoseconds, but the underlying clock doesn't actually have such a resolution.

时钟的分辨率不一定与时钟使用的数据类型可以表示的最小持续时间相同。在这种情况下,您的实现使用的数据类型可以表示小至 100 纳秒的持续时间,但底层时钟实际上没有这样的分辨率。



The low resolution of Visual Studio's high_resolution_clockhas been an issue for several years. Microsoft's C++ standard library maintainer, Stephan T. Lavavej, has indicatedthat this has been fixed in Visual Studio 2015 via the use of QueryPerformanceCounter().

high_resolution_clock多年来,Visual Studio 的低分辨率一直是一个问题。Microsoft 的 C++ 标准库维护者 Stephan T. Lavavej表示,这已通过使用QueryPerformanceCounter().

回答by graham.reeds

Maybe the implementation doesn't implement the higher resolution timer?

也许实现没有实现更高分辨率的计时器?

It seems you are using Windows (you mention C#), so if you use a timer and you are indeed using Windows, you can use QueryPerformanceFrequencyand QueryPerformanceCounter.

看来您使用的是 Windows(您提到了 C#),因此如果您使用计时器并且您确实使用的是 Windows,则可以使用QueryPerformanceFrequencyQueryPerformanceCounter