C ++计时,自上一秒以来的毫秒数
我正在开发一个C ++应用程序,该应用程序需要详细的时序信息,直到毫秒级。
我们打算使用<ctime>中的标准time()
函数将时间收集到秒精度。我们还想收集自time()给出的最后一秒以来经过的毫秒数。
有谁知道获取此信息的便捷方法?
解决方案
如果这适用于Windows,请查看QueryPerformanceCounter方法。
由于ANSI C没有定义标准的毫秒级精确时间函数,因此没有可移植的解决方案。如果使用Windows,则可以使用GetTickCount(),timeGetTime()或者QueryPerformanceCounter()/ QueryPerformanceFrequency()。请记住,它们具有不同的精度和不同的运行时成本。
其他操作系统中还有其他类似的功能。我不确定它们在我头顶上什么。
(c)time.h标头中没有的任何内容都需要特定于操作系统的方法。我相信所有这些方法都是第二种解决方法。
我们正在使用什么操作系统?
如果基础平台支持的话,Boost.DateTime具有毫秒和纳秒的表示形式。当它使用平台特定的代码时,它将那些细节保留在代码之外。
如果这很重要,那么他们确实有另一种独立于平台的亚秒级分辨率的方法。此页面几段下来讨论了如何执行此操作。
(来自页面)
例如,假设我们要使用代表十分之一秒的计数进行构造。也就是说,每个刻度是0.1秒。
int number_of_tenths = 5; //create a resolution independent count -- divide by 10 since there are //10 tenths in a second. int count = number_of_tenths*(time_duration::ticks_per_second()/10); time_duration td(1,2,3,count); //01:02:03.5 //no matter the resolution settings
英特尔处理器的高分辨率,低开销时序
如果我们使用的是Intel硬件,则以下是读取CPU实时指令计数器的方法。它会告诉我们自处理器启动以来执行的CPU周期数。这可能是我们可以用来进行性能评估的最细粒度的计数器。
请注意,这是CPU周期数。在Linux上,我们可以从/ proc / cpuinfo获取CPU速度,然后除以秒数。将其转换为双精度非常方便。
当我在盒子上运行它时,我得到
11867927879484732 11867927879692217 it took this long to call printf: 207485
这是英特尔开发人员指南,其中提供了大量详细信息。
#include < stdio.h > // stackoverflow bug: pre tag eats the filenames, #include < stdint.h > // so i had to put spaces in the angle brackets inline uint64_t rdtsc() { uint32_t lo, hi; __asm__ __volatile__ ( "xorl %%eax, %%eax\n" "cpuid\n" "rdtsc\n" : "=a" (lo), "=d" (hi) : : "%ebx", "%ecx"); return (uint64_t)hi << 32 | lo; } main() { unsigned long long x; unsigned long long y; x = rdtsc(); printf("%lld\n",x); y = rdtsc(); printf("%lld\n",y); printf("it took this long to call printf: %lld\n",y-x); }
Windows中的GetTickCount
- nix中的gettimeofday
Windows中的QueryPerformanceCounter可提供更好的解析度(尽管GetTickCount应该可以做到)
如果我们使用的是Unix,gettimeofday()将返回秒和微秒,直到系统时钟的分辨率为止。
int gettimeofday(struct timeval *tv, struct timezone *tz); struct timeval { time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* microseconds */ };
#include <ctime> clock_t elapsed = static_cast<double>(clock() / CLOCKS_PER_SEC);
经过的时间是经过的处理器时间(以秒为单位)。
分辨率取决于操作系统,但通常在大多数系统上都优于毫秒级分辨率。
英特尔的线程构建模块库具有此功能,但是TBB当前仅在英特尔和克隆上可用(也就是说,在SPARC,PowerPC,ARM等上不可用)。
就像其他人所说的那样,没有便携式的方法可以做到这一点。
我要做的(在msvc ++和linux / g ++上)是我使用以下类,这些类在Windows上使用QueryPerformanceCounter,在Linux上使用gettimeofday。这是一个计时器类,可以让我们了解两次通话之间的经过时间。我们可能需要对其进行修改以适合需求。
#if defined(_MSC_VER) # define NOMINMAX // workaround un bug dans windows.h qui define des macros // "min" et "max" qui entrent en conflit avec la STL. # include <windows.h> #else # include <sys/time.h> #endif namespace Utils { /** * Implémente un chronométre qui mesure le temps etre deux appels. */ class CTimer { private: # if defined(_MSC_VER) LARGE_INTEGER m_depart; # else timeval m_depart; # endif public: /** * Démarre le timer. * * Cette fonction sert à démarrer le timer. Si le timer est déja * démarrer, elle le redémarre simplement. */ inline void start() { # if defined(_MSC_VER) QueryPerformanceCounter(&m_depart); # else gettimeofday(&m_depart, 0); # endif }; /** * Retourne le nombre de secondes depuis le départ du timer. * * @return Nombre de secondes écoulés depuis le départ du timer */ 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 }; }; }