You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Google Benchmark中实现每次函数调用冷缓存且不计入计时?

冷缓存场景下Google Benchmark的函数计时问题

我正在使用Google Benchmark对函数进行计时,但需要查看其在冷缓存下的性能表现。我知道该基准测试库会反复运行函数直到计时稳定,但希望这个稳定计时能基于冷缓存的场景。我的基准测试代码大致如下:

template <class ...Args>
void BM_MyFunc(benchmark::State& state, Args&&... args) {
    auto args_tuple = std::make_tuple(std::move(args)...);
    const int arg = std::get<0>(args_tuple);
    for (auto _ : state) {
        // flush cache by accessing a huge array
        for (int i = 0; i < N; i++) {
            huge_array[i] = rand();
        }
        my_func(arg);
    }
}

BENCHMARK_CAPTURE(BM_MyFunc,  my_func_with_42,  42);

问题在于将缓存刷新逻辑放在for (auto _ : state)循环内时,缓存刷新操作会被计入计时结果。如果将缓存刷新放在该循环外,则只会刷新一次缓存,基准测试库会将其视为异常情况并预热my_func,导致无法在冷缓存下测试。是否存在一种方式,能实现“每次函数调用前的准备操作”且不计入函数的计时结果?官方文档似乎未覆盖该特定场景。


解决方案:利用PauseTiming()和ResumeTiming()接口

Google Benchmark提供了暂停/恢复计时的API,刚好能满足“准备操作不计入计时”的需求。在缓存刷新前暂停计时,完成刷新后再恢复计时,这样只有目标函数my_func的执行时间会被统计。

修改后的代码如下:

template <class ...Args>
void BM_MyFunc(benchmark::State& state, Args&&... args) {
    auto args_tuple = std::make_tuple(std::move(args)...);
    const int arg = std::get<0>(args_tuple);
    for (auto _ : state) {
        // 暂停计时,准备操作不计入结果
        state.PauseTiming();
        // 刷新缓存
        for (int i = 0; i < N; i++) {
            huge_array[i] = rand();
        }
        // 恢复计时,开始统计目标函数
        state.ResumeTiming();
        
        my_func(arg);
    }
}

BENCHMARK_CAPTURE(BM_MyFunc,  my_func_with_42,  42);

补充说明

  • PauseTiming()会立刻停止当前计时周期,ResumeTiming()重新启动计时,两者之间的操作完全不会被计入基准测试的统计数据。
  • 这种方式既保证了每次调用my_func前都是冷缓存状态,又不会把缓存刷新的耗时算到目标函数的性能结果里。
  • 需确保huge_array的大小足够覆盖系统各级缓存(比如至少大于L3缓存容量),否则缓存刷新可能不彻底。

内容的提问来源于stack exchange,提问作者rcplusplus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 22:20:45