关于 高精度性能计数器的频率 和 cpu 频率 不一致问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | /* 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 高精度性能计数器的频率是不变的,而且比cpu(平均)频率低得多 */ #include <iostream> #include <windows.h> using namespace std; #define read_tsc(tsc) \ long long tsc; \ _asm rdtsc \ _asm mov dword ptr[tsc],eax \ _asm mov dword ptr[tsc+4],edx #define read_hrpc(pc) \ LARGE_INTEGER pc; \ QueryPerformanceCounter(&pc); int main() { read_hrpc(pc1); read_tsc(tsc1); cout << "waiting..." << endl; Sleep(1000); read_tsc(tsc2); read_hrpc(pc2); LARGE_INTEGER freq; QueryPerformanceFrequency(&freq); double elapse = (pc2.QuadPart - pc1.QuadPart) / ( double )freq.QuadPart; double cpu_freq = (tsc2 - tsc1) / elapse; cout << "perf freq:\t" << freq.QuadPart / 1000.0 / 1000 << "\tMHz" << endl; cout << "cpu freq:\t" << cpu_freq / 1000 / 1000 / 1000 << "\tGHz" << endl; return 0; } |
备注:
QueryPerformanceFrequency将获得一个频率Freq,它表示高性能计时器1秒钟的计数次数,也就是说QueryPerformanceCounter获得的时间是一个计数值,其单位是秒。
高性能计时器的精度:在笔者的电脑上,频率Freq为3134267,一个计数的时间是秒,也就是0.319微秒或319纳秒。这也就是高性能计时器的精度。
高性能计时器的归零:QueryPerformanceCounter获得的计数是一个有符号的64位整数。频率Freq为3134267的Windows在连续运行9.3万年后,QueryPerformanceCounter获得的计数才可能归零。
需要注意:并不是所有的电脑都支持QueryPerformanceCounter,返回0不支持。
内联汇编VS 64位 改 32位。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
2022-02-02 VS编译lua和C调用lua