Windows中的C++高精度时间测量

Kel*_*ton 30 c c++ windows

我有兴趣在Windows中使用C++测量一个特定的时间点到纳秒.这可能吗?如果不是,是否有可能至少以微秒为单位获得特定时间?任何库都应该这样做,除非我认为托管代码是可能的.谢谢

And*_*nck 34

如果在多核计算机上运行的线程应用程序QueryPerformanceCounter可以(并且将)根据代码执行的核心返回不同的值.请参阅 MSDN文章.(rdtsc有同样的问题)

这不仅仅是一个理论问题; 我们用我们的应用程序遇到它并且必须得出结论,唯一可靠的时间源timeGetTime只有ms精度(幸运的是在我们的情况下是足够的).我们还尝试为我们的线程修复线程亲和性,以保证每个线程始终从中获得一致的值QueryPerformanceCounter,但是它确实有效,但它绝对杀死了应用程序中的性能.

总而言之,Windows上没有一个可靠的计时器,可用于以微秒精度计时(至少在多核计算机上运行时).

  • +1用于向QueryPerformanceCounter指出鲜为人知的陷阱.Windows上的高性能计时器并不可靠,这对某些系统来说是一个巨大的PITA.与基于Unix的系统进行比较和对比,基于Unix的系统可以轻松实现... (11认同)
  • 这在2013年仍然如此吗?http://msdn.microsoft.com/en-us/library/windows/desktop/dn553408%28v=vs.85%29.aspx说*通常,性能计数器结果在多核和所有处理器中都是一致的多处理器系统,即使在不同的线程或进程上进行测量.* (11认同)
  • 如今,QPC在多核计算机中得到了完美支持.有关详细信息,请参阅https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx.基本上,处理器计数器在很长一段时间内都是时间不变的,如果不是,Windows将使用另一个(可能不太精确的)源来测量时间. (6认同)

Kon*_*lph 14

Windows有一个高性能的计数器API.

您需要获取刻度形式QueryPerformanceCounter并除以处理器的频率QueryPerformanceFrequency.

LARGE_INTEGER frequency;
if (::QueryPerformanceFrequency(&frequency) == FALSE)
    throw "foo";

LARGE_INTEGER start;
if (::QueryPerformanceCounter(&start) == FALSE)
    throw "foo";

// Calculation.


LARGE_INTEGER end;
if (::QueryPerformanceCounter(&end) == FALSE)
    throw "foo";

double interval = static_cast<double>(end.QuadPart - start.QuadPart) / frequency.QuadPart;
Run Code Online (Sandbox Code Playgroud)

interval应该是几秒钟.

  • 因此,Windows的最新版本不会将rdtsc用于QPC,因此不会为QPF返回处理器频率。他们可能使用1.193182 MHz可编程中断定时器(PIT)或高速(&gt; 10 MHz)HPET。 (2认同)

小智 6

对于将来参考,对于Windows Vista,2008及更高版本,Windows需要硬件支持"HPET".它独立于CPU及其时钟和频率运行.有可能获得精度达到亚微秒的时间.

为了实现这一点,您需要使用QPC/QPF.问题是QPF(频率)是NOMINAL值,因此使用原始调用将导致时间漂移超过每天几分钟.为了达到这个目的,您必须测量实际频率并检查其随时间的漂移,因为热量和其他物理操作条件会影响它.

可以在此链接上的MSDN(大约2004年!)上找到描述此内容的文章. http://msdn.microsoft.com/en-us/magazine/cc163996.aspx

我自己实现了类似的东西(今天刚刚找到了上面的链接!)但是不想使用"微秒时间",因为与其他Windows调用(如GetSystemTimeAsFileTime)相比,QPC调用本身相当冗长,并且同步会增加更多开销.所以我更喜欢使用毫秒时间戳(比使用QPC少约70%的通话时间),特别是当我试图每秒钟数十万次时.


Arn*_*rno 5

最好的选择是功能QueryPerformanceCounterQueryPerformanceFrequency.

Microsoft最近(2014年)发布了有关QueryPerformanceCounter的更多详细信息:

有关详细信息,请参阅获取高分辨率时间戳(MSDN 2014).

这是一篇包含大量示例和详细说明的综合性文章.必须为QPC用户阅读.


Rob*_*son 5

我认为微秒有点不合理(没有硬件帮助)。毫秒是可行的,但即使如此,由于各种邪恶的计数器分辨率问题,也不是那么准确。无论如何,我包括我自己的计时器类(基于 std::chrono)供您考虑:

#include <type_traits>
#include <chrono>


class Stopwatch final
{
public:

    using elapsed_resolution = std::chrono::milliseconds;

    Stopwatch()
    {
        Reset();
    }

    void Reset()
    {
        reset_time = clock.now();
    }

    elapsed_resolution Elapsed()
    {
        return std::chrono::duration_cast<elapsed_resolution>(clock.now() - reset_time);
    }

private:

    std::chrono::high_resolution_clock clock;
    std::chrono::high_resolution_clock::time_point reset_time;
};
Run Code Online (Sandbox Code Playgroud)

请注意,在 Windows std::chrono::high_resolution_clock 上,底层使用的是 QueryPerformanceCounter,因此它是相同的但可移植。

  • 您是少数不会使用“.count()”立即跳出“&lt;chrono&gt;”类型系统并返回裸整数类型的人之一。为此+1!:-) (2认同)