用 std::chrono 测单次任务耗时不准,必须多次采样求平均;推荐 1000–10000 次循环,配合 volatile sink、编译器屏障和纳秒累加,避免 clock()/time() 等低精度或非 wall-clock 方法。

用 std::chrono 测单次任务耗时不准?别直接取 duration_cast 后的毫秒值
直接拿一次 std::chrono::high_resolution_clock::now() 差值转成毫秒或微秒,结果常为 0 或剧烈抖动——因为现代 CPU 指令执行远快于时钟精度下限,尤其对轻量计算。平均时间必须靠多次采样,且要排除系统噪声干扰。
实操建议:
- 最少运行 100 次,推荐 1000–10000 次(视任务耗时而定:若单次约 1μs,跑 10000 次总耗时仍可控)
- 每次调用前加
asm volatile("" ::: "memory")防止编译器优化掉重复计算(尤其纯算术任务) - 用
std::chrono::nanoseconds累加总耗时,最后再除以次数——避免中间转double引入浮点误差
为什么不能用 clock() 或 time()?
clock() 返回的是进程 CPU 时间,受线程调度、系统负载影响大;time() 精度只有秒级。两者都不反映真实 wall-clock 执行延迟,测出来的“平均时间”会严重偏离实际。
典型错误现象:
立即学习“C++免费学习笔记(深入)”;
- 多线程环境下
clock()返回值可能倒退或跳跃 - 任务实际执行 50μs,但
clock()分辨率是 10ms,连续几次读数都是 0 -
time(NULL)在整个循环里返回同一个整数值
如何排除编译器和 CPU 的干扰?
现代编译器会把无副作用的纯计算整个优化掉(比如 int x = a + b * c; 后没用到 x),CPU 也可能乱序执行或预测分支,导致测量失真。
关键动作:
- 确保被测代码有可观察副作用:把结果写入
volatile int sink或传给do_not_optimize_away()辅助函数 - 在计时区间外加
_mm_pause()(x86)或__builtin_ia32_pause()避免 CPU 预测干扰起始点 - 关闭 ASLR 和 CPU 频率调节(Linux 下
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor)
一个安全可用的最小模板长什么样?
以下代码能跑在 C++11+,不依赖第三方库,且抗基础优化:
#include <chrono>
#include <iostream>
<p>template <class Func, class... Args>
double benchmark(Func&& f, Args&&... args) {
volatile int sink = 0;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < 1000; ++i) {
sink ^= f(args...); // 强制每次执行并扰动 sink
asm volatile("" ::: "memory"); // 编译器屏障
}
auto end = std::chrono::high_resolution_clock::now();
auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
return ns / 1000.0; // 单次平均纳秒数
}</p><p>// 用法示例:
int compute(int a, int b) { return a <em> a + b </em> b; }
int main() {
std::cout << benchmark(compute, 123, 456) << " ns\n";
}</p>注意 sink 是 volatile,且用异或累积结果——既防止优化,又不引入分支或内存分配开销。真正压测时,循环次数、是否预热、是否绑核,都得按实际场景调。


















