### C++精确读取时钟数 在计算机编程领域,特别是在Windows平台上,精确地测量时间是非常重要的需求之一,尤其对于那些需要高精度时间计量的应用场景,例如实时图形处理、多媒体数据流处理或实时系统构建等。本文将详细介绍两种常用的时间计数方法:`timeGetTime` 多媒体计时器和 `QueryPerformanceCount` 计数器,并重点讨论后者如何为用户提供更精准的时间度量。 #### 一、timeGetTime多媒体计时器 `timeGetTime` 是Windows API提供的一个函数,它可以提供毫秒级别的计时精度。该函数返回自系统启动以来经过的毫秒数,包括挂起时间。虽然它足够简单易用,但对于许多需要更高精度的应用来说,其精度仍然不够。 **示例代码**: ```cpp #include <windows.h> int main() { DWORD startTime = timeGetTime(); // Do something time-intensive DWORD endTime = timeGetTime(); DWORD duration = endTime - startTime; printf("Duration: %d ms\n", duration); return 0; } ``` #### 二、QueryPerformanceCount计数器 对于需要更高精度计时的应用,Windows提供了 `QueryPerformanceCount` 函数,它可以提供比 `timeGetTime` 更高的精度,通常达到微秒级别。为了获取当前性能计数器的值,需要调用此函数;而为了获得性能计数器每计数一次所代表的时间(即频率),则需要调用 `QueryPerformanceFrequency` 函数。 **示例代码**: ```cpp #include <windows.h> int main() { LARGE_INTEGER frequency, start, end; QueryPerformanceFrequency(&frequency); QueryPerformanceCounter(&start); // Do something time-intensive QueryPerformanceCounter(&end); double duration = (double)(end.QuadPart - start.QuadPart) / frequency.QuadPart * 1000000; printf("Duration: %.6f μs\n", duration); return 0; } ``` #### 三、RDTSC指令 除了以上两种方法外,对于更高级的开发者而言,直接利用处理器提供的指令 `RDTSC`(Read Time Stamp Counter)也是一个选择。此指令可以直接读取处理器的时间戳计数器,从而获取极其精确的时间信息。需要注意的是,`RDTSC` 的精度依赖于处理器的速度,并且可能会受到其他因素的影响。 **示例代码**: ```cpp #include <intrin.h> unsigned __int64 GetCycleCount() { __asm RDTSC } int main() { unsigned __int64 start = GetCycleCount(); // Do something time-intensive unsigned __int64 end = GetCycleCount(); unsigned __int64 duration = end - start; printf("Duration: %llu cycles\n", duration); return 0; } ``` #### 四、比较与总结 1. **精度**: - `timeGetTime` 提供毫秒级精度。 - `QueryPerformanceCount` 可以根据系统配置达到微秒级精度。 - `RDTSC` 提供最精细的时钟周期级别精度。 2. **使用场景**: - 对于大多数应用程序来说,`timeGetTime` 的精度已经足够。 - 当需要更高精度的计时时,`QueryPerformanceCount` 是更好的选择。 - 对于极端情况下的高性能计算或实时系统,直接使用 `RDTSC` 可能是最合适的方法。 3. **注意事项**: - 使用 `RDTSC` 需要注意其精度会受到处理器速度和其他系统负载的影响。 - `QueryPerformanceCount` 和 `QueryPerformanceFrequency` 的组合可以提供稳定且精确的时间度量。 - `timeGetTime` 虽然简单易用,但在某些需要高精度计时的应用中可能不适用。 根据具体的应用需求选择合适的计时方法至关重要。在Windows平台上,`QueryPerformanceCount` 和 `QueryPerformanceFrequency` 是实现高精度计时的理想选择,而对于需要更高精度的应用,可以直接使用 `RDTSC` 指令。
一、Windows平台下
在Windows平台下,常用的计时器有两种,一种是timeGetTime多媒体计时器,它可以提供毫秒级的计时。但这个精度对很多应用场合而言还是太粗糙了。另一种是QueryPerformanceCount计数器,随系统的不同可以提供微秒级的计数。对于实时图形处理、多媒体数据流处理、或者实时系统构造的程序员,善用QueryPerformanceCount/QueryPerformanceFrequency是一项基本功。
本文要介绍的,是另一种直接利用Pentium CPU内部时间戳进行计时的高精度计时手段。以下讨论主要得益于《Windows图形编程》一书,第15页-17页,有兴趣的读者可以直接参考该书。关于RDTSC指令的详细讨论,可以参考Intel产品手册。本文仅仅作抛砖之用。
在Intel Pentium以上级别的CPU中,有一个称为“时间戳(Time Stamp)”的部件,它以64位无符号整型数的格式,记录了自CPU上电以来所经过的时钟周期数。由于目前的CPU主频都非常高,因此这个部件可以达到纳秒级的计时精度。这个精确性是上述两种方法所无法比拟的。
在Pentium以上的CPU中,提供了一条机器指令RDTSC(Read Time Stamp Counter)来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C++语言保存函数返回值的寄存器,所以我们可以把这条指令看成是一个普通的函数调用。像这样:
inline unsigned __int64 GetCycleCount()
{
__asm RDTSC
}
但是不行,因为RDTSC不被C++的内嵌汇编器直接支持,所以我们要用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31,如下:
inline unsigned __int64 GetCycleCount()
{
__asm _emit 0x0F
__asm _emit 0x31
}
以后在需要计数器的场合,可以像使用普通的Win32 API一样,调用两次GetCycleCount函数,比较两个返回值的差,像这样:
unsigned long t;
t = (unsigned long)GetCycleCount();
//Do Something time-intensive ...
t -= (unsigned long)GetCycleCount();
- s189054815222013-03-25东西很不错,工程需要的定时器模块已经解决了 谢谢楼主分享
- 粉丝: 0
- 资源: 1
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- Spring Cloud商城项目专栏 049 支付
- sensors-18-03721.pdf
- Facebook.apk
- 推荐一款JTools的call-this-method插件
- json的合法基色来自红包东i请各位
- 项目采用YOLO V4算法模型进行目标检测,使用Deep SORT目标跟踪算法 .zip
- 针对实时视频流和静态图像实现的对象检测和跟踪算法 .zip
- 部署 yolox 算法使用 deepstream.zip
- 基于webmagic、springboot和mybatis的MagicToe Java爬虫设计源码
- 通过实时流协议 (RTSP) 使用 Yolo、OpenCV 和 Python 进行深度学习的对象检测.zip