关于__rdtsc使用最佳实践及精准CPU周期测量的技术问询
__rdtsc测量CPU周期的常见问题解答
你的代码是不是测量CPU周期的最佳实践?
这是最基础的用法,但算不上最佳实践,存在两个关键缺陷:
- CPU乱序执行干扰:现代CPU的乱序执行特性可能导致
__rdtsc指令被重排到被测代码的前后,比如CPU先执行了部分被测函数指令才记录start,或者先记录end再完成被测函数的剩余指令,直接导致测量结果失真。 - 缺少序列化保证:
__rdtsc本身不具备序列化功能,无法确保测量区间外的指令不会影响时间戳的准确性。
更可靠的写法需要加入序列化操作,比如使用自带序列化的__rdtscp指令(它会在读取时间戳前完成所有前置指令,还能返回当前CPU核心ID),或者配合内存屏障指令_mm_mfence:
#include <x86intrin.h> void func() { unsigned long long start, end; unsigned int cpu_id; // 序列化,确保前置指令全部执行完毕 _mm_mfence(); start = __rdtscp(&cpu_id); _mm_mfence(); // 这里放入要测量的操作/函数调用 // 序列化,确保被测操作全部执行完毕再取时间戳 _mm_mfence(); end = __rdtscp(&cpu_id); _mm_mfence(); unsigned long long cycles = end - start; }
测量区间内CPU会不会切换进程?如何精准测量?
确实会出现这种情况。操作系统调度器随时可能将当前线程切换到其他核心,或者让其他进程抢占当前核心,此时统计的周期会包含其他进程的执行时间,导致结果偏差极大。
实现精准测量可以从这几个方面入手:
- 绑定CPU核心:将被测线程绑定到固定的CPU核心上,既避免跨核心调度带来的抢占,也能规避不同核心TSC(时间戳计数器)不同步的问题。Linux下用
sched_setaffinity函数,Windows下用SetThreadAffinityMask函数。 - 提升线程优先级:提高被测线程的调度优先级,降低被其他进程抢占的概率,但无法完全杜绝,需搭配其他方法。
- 多次采样过滤异常值:重复执行多次测量,去掉包含抢占情况的最大值,取最小值或多次测量的平均值,这样得到的结果更接近真实的执行周期。
- 使用专业性能工具:如果需要更高精度的测量,可借助系统自带的性能分析工具(比如Linux的
perf、Windows的Xperf),这类工具能在内核层面统计,大幅减少调度干扰。
内容的提问来源于stack exchange,提问作者chenzhongpu
相关产品推荐
相关产品推荐

