一、了解RDTSC指令
rdtsc指令, 该指令返回CPU自启动以来的时钟周期数;该时钟周期数,即处理器的时间戳。
在CPU通电启动后,首先会重置EDX和EAX,在每个时钟周期上升或下降沿到来时,会自动累计周期数,并被记录到EDX和EAX寄存器中,EDX是高位,EAX是低位。
rdtsc指令就是从该寄存器中进行获取的。
周期和频率的关系公式:T(周期)=1/f(频率)
如CPU频率f为1GHz,则其时钟周期T=1/1GHz秒,意味着每隔T秒,CPU完成一个最基本的动作,并在寄存器中,对周期数加1。
故,假设当前时钟周期数为m,则可计算出CPU自启动后,累计运行时间X=m*T,整理下:
X=m/f
时钟周期与时钟频率互为倒数, 我们可以找出以下关系:
时钟频率 | 时钟周期 |
---|---|
1Hz | 1s |
1KHz | 1ms |
1MHz | 1μs |
1GHz | 1ns |
注意计算时,单位要搭配好,比如:
- f为Hz时,计算得到的X为秒;
- f为GHz时,计算得到的X为纳秒。
小结:
CPU累计运行时间=时钟周期数/CPU频率
二、RDTSC指令在win和linux上的实现
我们已经知道RDTSC可以获取CPU运行时间,另外win平台上也已经有了一个类似的函数:
DWORD GetTickCount();
该函数返回值是系统启动后经过的毫秒数,最长为49.7天。
其微软帮助为:
https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-gettickcount
win和linux下RDTSC的实现
#include <stdint.h>
// rdtsc
#if _WIN32
#include <intrin.h>
uint64_t rdtsc() // win
{
return __rdtsc();
}
#else
uint64_t rdtsc() // linux
{
unsigned int lo, hi;
__asm__ volatile ("rdtsc" : "=a" (lo), "=d" (hi));
return ((uint64_t)hi << 32) | lo;
}
#endif
win下,__rdtsc()函数的微软帮助为:
https://docs.microsoft.com/zh-cn/cpp/intrinsics/rdtsc?view=vs-2019
linux下,则需要内联汇编来实现。
RDTSC指令结合CPU频率,也可以用来计算代码段的执行时间。
参考链接:
若对你有帮助,欢迎点赞、收藏、评论,你的支持就是我的最大动力!!!
同时,阿超为大家准备了丰富的学习资料,欢迎关注公众号“超哥学编程”,即可领取。