在 C/C++ 程序中常用 time( ) 来获取系统时间,但它是以秒为单位的,一需要小于1秒的时间间隔或者精度高于1秒的时间时就不再适用。
此时可以利用一种直接利用Pentium CPU内部时间戳进行计时的高精度计时手段来实现,可以用RDTSC指令来得到这个时间戳,祥见Kacker的文章,在Programming版精华区X-4-11-8。
得到CPU内部时间戳的方法如下:
inline unsigned __int64 GetCycleCount() |
这里得到的是 CPU 自上电起经过的时钟周期数,假设 CPU 的时钟频率为 1G,则一秒钟内该数值的变化约为 2^30,CPU 内部是一个 64 位的计数器,那么在 2^34 秒(即 544.8 年)内不会回归零,就当前来说,一台机器的持续运行时间是不会超过这个的,因而不用考虑计数器溢出。
用上面的函数得到的只是CPU的经过的时钟周期数,并不是时间,得考虑用其他方法将它转化成时间。不知道有没有办法通过读取BIOS信息来得到CPU频率的方法,目前好多计算 CPU 频率的方法就是利用 RDTSC 指令来实现。其中会用到 sleep() 或 delay() 等方法来得到一段粗略的时间,然后根据这段时间内计数器的变化得到相应的计数器变化值对应的粗略时间。
在对时间精度要求不高的情况下,比如只要精确到几十毫秒,sleep() 或者 delay() 来对计数器进行标定的方法是可以满足要求的。
可以把计数器的标定等封装起来,便于使用,如下:
watch.h文件:
#ifndef __WATCH_H__ #include "sys/types.h" //typedef __int64 UINT64; class CWatch #endif |
watch.cpp文件:
#include "watch.h" INT64 CWatch::count_per_second = 0; inline INT64 CWatch::GetCycleCount() void CWatch::init() double currTime = (double)GetCycleCount() / count_per_second; inline double CWatch::GetTime() |
由于对计数器进行时间标定时用到了 time() ,因而绝对时间的精度只有秒,而时间差的精度可以达到 1%(由Sleep的相对精度决定)。比如想得到 1ms 的时间差,其误差只有 0.01ms。
如果有了得到准确的 CPU 频率的方法,就比较完美了 :-)