30

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

#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

std::cout 需要多少纳秒?

std::cout 需要 1000200 纳秒

我收到1000200or 1000300or 1000400or 1000500or 1000600or2000600作为结果(= 1 或 2 微秒)。显然,要么分辨率std::chrono不是100 纳秒,要么测量时间的方式是错误的。(例如,为什么我从来没有收到 1 到 2 微秒之间的信息?)std::cout1500000

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

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

4

3 回答 3

53

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

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

高分辨率时钟.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 上从上述代码编译。)

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

于 2013-04-30T12:09:32.830 回答
6

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


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

于 2014-12-30T19:55:03.277 回答
1

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

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

于 2013-04-30T11:54:13.770 回答