Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows环境下C++高精度时间测量 我感兴趣的是在Windows中用C++测量特定的时间点到纳秒。这可能吗?如果不是,是否可以获得至少以微秒为单位的特定时间?。任何库都应该这样做,除非我认为托管代码是可能的。 谢谢_C++_C_Windows - Fatal编程技术网

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

Windows环境下C++高精度时间测量 我感兴趣的是在Windows中用C++测量特定的时间点到纳秒。这可能吗?如果不是,是否可以获得至少以微秒为单位的特定时间?。任何库都应该这样做,除非我认为托管代码是可能的。 谢谢,c++,c,windows,C++,C,Windows,Windows有一个 您需要从QueryPerformanceCounter获取刻度,然后除以QueryPerformanceFrequency提供的处理器频率 此间隔应以秒为单位。使用windows时,您可以使用Konrad Rudolf建议的性能计数器API,但应注意它是基于CPU频率的。例如,启用节能模式时,该频率不稳定。如果要使用此API,请确保CPU处于恒定频率 否则,您可以创建某种“统计”系统,将CPU时钟与PC BIOS时钟相关联。后者不太精确,但恒定。关于Konrad Rudol

Windows有一个

您需要从QueryPerformanceCounter获取刻度,然后除以QueryPerformanceFrequency提供的处理器频率

此间隔应以秒为单位。

使用windows时,您可以使用Konrad Rudolf建议的性能计数器API,但应注意它是基于CPU频率的。例如,启用节能模式时,该频率不稳定。如果要使用此API,请确保CPU处于恒定频率


否则,您可以创建某种“统计”系统,将CPU时钟与PC BIOS时钟相关联。后者不太精确,但恒定。

关于Konrad Rudolph的答案,请注意,根据我的经验,性能计数器的频率约为3.7MHz,因此精度为亚微秒,但肯定不是纳秒。实际频率取决于硬件和节能模式。纳秒精度在任何情况下都有些不合理,因为中断延迟和进程/线程上下文切换时间远远超过纳秒,这也是单个机器指令的数量级。

是最准确的。

如果多核计算机上运行线程应用程序,QueryPerformanceCounter可以并且将返回不同的值,具体取决于代码在哪个核上执行。见MSDN文章。rdtsc也有同样的问题

这不仅仅是一个理论问题;我们在应用程序中遇到了它,并得出结论,唯一可靠的时间源是timeGetTime,它只有毫秒精度,幸运的是,在我们的例子中,这已经足够了。我们还尝试固定线程的线程关联性,以确保每个线程始终从QueryPerformanceCounter获得一致的值,这是可行的,但绝对会降低应用程序的性能


总而言之,windows上没有一个可靠的计时器可以用来以微秒的精度计时,至少在多核计算机上运行时是这样。

这里有一个计时器类,它既适用于windows,也适用于Linux:

#ifndef INCLUDE_CTIMER_HPP_
#define INCLUDE_CTIMER_HPP_

#if defined(_MSC_VER)
#  define NOMINMAX // workaround a bug in windows.h
#  include <windows.h>
#else
#  include <sys/time.h>
#endif

namespace Utils
{
   class CTimer
   {
   private:
#     if defined(_MSC_VER)
         LARGE_INTEGER m_depart;
#     else
         timeval m_depart;
#     endif

   public:
      inline void start()
      {
#        if defined(_MSC_VER)
            QueryPerformanceCounter(&m_depart);
#        else
            gettimeofday(&m_depart, 0);
#        endif
      };

      inline float GetSecondes() const
      {
#        if defined(_MSC_VER)
            LARGE_INTEGER now;
            LARGE_INTEGER freq;

            QueryPerformanceCounter(&now);
            QueryPerformanceFrequency(&freq);

            return (now.QuadPart - m_depart.QuadPart) / static_cast<float>(freq.QuadPart);
#        else
            timeval now;
            gettimeofday(&now, 0);

            return now.tv_sec - m_depart.tv_sec + (now.tv_usec - m_depart.tv_usec) / 1000000.0f;
#        endif
      };
   };
}
#endif // INCLUDE_CTIMER_HPP_

感谢您的输入…虽然我无法获得纳秒或微秒的分辨率,这将是很好的,但我能够想出这个…也许其他人会发现它有用

    class N_Script_Timer
{
    public:
        N_Script_Timer()
        {
            running = false;
            milliseconds = 0;
            seconds = 0;
            start_t = 0;
            end_t = 0;
        }
        void Start()
        {
            if(running)return;
            running = true;
            start_t = timeGetTime();
        }
        void End()
        {
            if(!running)return;
            running = false;
            end_t = timeGetTime();
            milliseconds = end_t - start_t;
            seconds = milliseconds / (float)1000;
        }
        float milliseconds;
        float seconds;

    private:
        unsigned long start_t;
        unsigned long end_t;
        bool running;
};

作为将来的参考,对于Windows Vista、2008及更高版本,Windows需要硬件支持HPET。这与CPU及其时钟和频率无关。可以获得精确到亚微秒的时间

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

一篇描述这一点的文章可以在MSDN circa 2004上找到!点击这个链接。

我自己也实现了类似的东西,今天才找到上面的链接!但是我们不希望使用微秒时间,因为QPC调用本身比其他Windows调用(如GetSystemTimeAsFileTime)要长,并且同步会增加更多开销。因此,我更喜欢使用毫秒时间戳,比使用QPC少70%的通话时间,特别是当我试图每秒获得数十万次的通话时间时。

声称-

场景对象是记录ETW事件的高精度计时器 启动和停止Windows时的事件跟踪。它是专门设计的 用于性能检测和基准测试,并且 在C和C++版本中…作为现代社会的经验法则 硬件,对开始或结束的调用按 微秒,得到的时间戳精确到100ns,即。 0.1微秒。。。版本既可用于.NET 3.5,也可用于本地C++,并可在x86和x64上运行。 平台。Scenario类最初是使用Visual Studio开发的 Studio 2008,但现在面向使用Visual Studio的开发人员 2010年。]

从。据我所知,它是由与PPL相同的人提供的


此外,您还可以阅读此内容。

最好的选择是函数QueryPerformanceCounter和QueryPerformanceFrequency

微软最近发布了关于QueryPerformanceCounter的更多详细信息:

有关详细信息,请参见MSDN 2014

这是一篇全面的文章,有很多例子和详细的描述。在较新的Windows版本中,QPC用户必须阅读 s看


根据硬件和操作系统版本的不同,这方面的差异很大。

如果您可以使用Visual Studio compiler 2012或更高版本,则可以使用标准库

#include <chrono>

::std::chrono::steady_clock::time_point time = std::chrono::steady_clock::now();

请注意。较新的版本应该精确到微秒。

我认为没有硬件帮助,微秒有点不合理。毫秒是可行的,但由于各种邪恶的反分辨率问题,即使如此也不那么准确。不管怎样,我基于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;
};


请注意,在Windows std::chrono::high_resolution_clock的引擎盖下使用的是QueryPerformanceCounter,因此它是一样的,但可移植。

请注意,intel的SpeedStep技术可能会在您的代码未注意到的情况下改变性能顺序…@xtofl:实话告诉你,QPF的值可能并不那么准确,无论如何,在某个地方对风险有一个很好的描述。但是,重复测量往往能相对较好地平均出这一点。QueryPerformanceFrequency/Coutner不一定因为这个原因而使用系统时钟。然而,这意味着它使用另一个较低频率的定时器。PIC定时器、ACPI定时器或全新系统上的HPET。有关此原因的一些详细信息,请参阅,最新版本的Windows不会将rdtsc用于QPC,因此不会返回QPF的处理器频率。他们可能会使用1.193182 MHz可编程中断计时器PIT或高速>10 MHz的HPET.FWIW。Windows 7似乎使用HPET:获得更好的分辨率,因为我从Vista升级。英文版,但内容不同。抱歉。我没有注意。修正了+1用于指出QueryPerformanceCounter鲜为人知的缺陷。Windows上的高性能计时器并不可靠,这对于某些系统来说是一个巨大的PITA。与基于Unix的系统进行比较和对比,基于Unix的系统很容易做到这一点……2013年仍然如此吗?一般来说,多核和多处理器系统中所有处理器的性能计数器结果都是一致的,即使是在不同的线程或进程上进行测量。@Martin Thompson我不知道,实际上,我写这个答案已经四年多了,在这段时间里,情况可能发生了变化。如今,QPC在多核计算机中得到了完美的支持。有关这方面的更多精度,请参阅。基本上,处理器计数器在很长一段时间内都是时不变的,如果不是,windows将使用另一个可能不太精确的源来测量时间。为了提高分辨率,您可能希望在开始和结束时分别添加timeBeginPeriod1和timeEndPeriod1。根据我的经验,不是这样。看见它读取每个CPU时钟周期更新的计数器。@JonasByström:Windows性能计数器API不使用TSC,原因如下所述。TSC分辨率更高,但一致性较差。同样,这个答案已经有五年历史了,它的内容可能仍然有效,也可能仍然无效。@JonasByström:同样,可以看出,在我的电脑上的结果与讨论中的问题的结果非常不同。YMMV。它完全依赖于硬件实现。你是对的,它是特定于实现的,但我只见过它使用TSC或更好的实现。对于21年前推出的P5而言,3.7MHz似乎是一个非常低的数字。为了更好的便携性,您可能希望使用std::chrono::high_resolution_clock来代替它,它可能与Standy_clock相同,也可能不同,但至少在语义上,它是一个更好的选择。使用分时操作系统,您无法获得纳秒级的准确时间,在用户空间中。不要听那些给你一个返回纳秒计数的函数的人说——这些数据是无用的。不过,内核模块可以做到这一点,如果您有硬件时间戳,那么就设置好了。这个问题需要更多的细节。您是少数不会立即跳出类型系统的人之一。使用.count并返回裸整数类型+我要为此付出代价!:-我可以在商业项目中使用你的代码吗?当然可以。
#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;
};