rdtsc可直接读取cpu时间戳计数器获取主频周期数,但需lfence序列化、volatile防止优化,并确认tsc invariant;std::chrono返回校准后系统时间,非原始周期数,无法精确换算瞬时频率。

用 rdtsc 读取 CPU 时间戳计数器(TSC)最直接
在 x86/x64 上,rdtsc 指令返回自 CPU 上电以来的 TSC 计数值,单位是「主频周期」——前提是 TSC 是 invariant(现代 Intel/AMD 大多默认支持)。它不依赖操作系统调度,精度极高,适合测小段代码的底层耗时。
但要注意:rdtsc 不序列化指令执行,编译器和 CPU 可能乱序执行,导致前后读到的值不对应实际目标代码段。必须配合 lfence(或 cpuid)强制串行化:
uint64_t start, end;
asm volatile ("lfence\n\t rdtsc" : "=a"(start), "=d"(start >> 32) :: "rax", "rdx");
// your target code here
asm volatile ("lfence\n\t rdtsc" : "=a"(end), "=d"(end >> 32) :: "rax", "rdx");
uint64_t cycles = end - start;
- 务必用
volatile防止编译器优化掉内联汇编 -
lfence比cpuid轻量,且在大多数场景下足够保证顺序(cpuid更重,但兼容性略好) - 不要用
RDTSCP除非你明确需要隐式序列化——它比rdtsc+lfence略慢,且某些旧 CPU 不支持
为什么不能直接用 std::chrono 测主频周期
std::chrono::high_resolution_clock 返回的是「系统时间」或「单调时钟」,单位通常是纳秒,背后依赖 OS 提供的定时源(如 HPET、APIC timer 或 TSC 映射后的虚拟时间),已做过频率校准和漂移补偿,**不是原始 CPU 周期数**。
它适合测毫秒级以上逻辑耗时,但无法反映真实主频周期——比如你在 3.5 GHz CPU 上跑一段代码耗时 1000 ns,std::chrono 给你 1000 ns,但实际周期数可能是 3500 左右(取决于当时睿频、P-state、是否降频)。
-
std::chrono的分辨率 ≠ 精度:即使period::den是 1,底层仍可能插值或降采样 - 跨核调用时,不同 CPU 核心的 TSC 可能未同步(启用
constant_tsc和nonstop_tscBIOS 设置可解决) - 若需把
std::chrono结果换算成周期,必须实时读取当前 CPU 频率(通过/proc/cpuinfo或 MSR 寄存器),但该频率是平均值,非瞬时值
使用 rdtsc 前必须确认 TSC 是否 invariant
非 invariant TSC 在频率切换(如节能降频)时会停走或跳变,导致差值失真。Linux 下可通过以下命令快速验证:
grep -o "constant_tsc\|nonstop_tsc" /proc/cpuinfo | sort -u
输出含 constant_tsc 表示 TSC 频率恒定(与标称主频一致);含 nonstop_tsc 表示即使 CPU 进入 C-state 也不停走。两者同时存在是最理想状态。
- Windows 用户可用
coreinfo -v(Sysinternals 工具)查看 “TSC” 行标记 - 若无
constant_tsc,rdtsc结果不可用于周期换算,只能作相对比较(如 A 段比 B 段多多少 tick) - 某些虚拟机(如早期 VirtualBox)会虚拟化 TSC 并禁用 invariant,此时
rdtsc返回值无物理周期意义
实际测量中容易被忽略的干扰项
哪怕 TSC 正确、指令序列化到位,真实测量仍受多种底层干扰影响:
- CPU 预取和分支预测:首次运行常比后续慢,建议预热 10–100 次再开始采样
- 缓存污染:目标代码若触发 cache miss,周期数暴涨,需用
clflush清理相关内存地址(慎用,本身也耗周期) - 中断和上下文切换:尽量绑核(
taskset -c 0 ./a.out)、关闭无关服务、禁用 NMI watchdog(echo 0 > /proc/sys/kernel/nmi_watchdog) - 编译器插入的 padding 或对齐指令:检查生成的 asm(
g++ -S),确保测量区间严格包裹目标指令
单次 rdtsc 差值波动可能达 ±50 周期,可靠结论需统计至少 1000 次测量并取中位数,而非平均值(避免异常尖峰污染)。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











