首页 > 解决方案 > 为什么 cpu 时间在基准测试中的波动通常比实时大?

问题描述

在使用Google Benchmark框架检查我的基准测试的输出时,我观察到在许多情况下测量的 cpu 时间的标准偏差明显大于测量的实时标准偏差。

这是为什么?还是由于测量误差导致的结果?我对此感到非常惊讶,因为我预计 cpu 时间更具可重复性。

这是对我系统的一般观察。尽管如此,我还是提供了一个简单的例子:

#include <benchmark/benchmark.h>
#include <cmath>

static void BM_SineEvaluation(benchmark::State& state)
{
    for (auto _ : state)
    {
        double y = 1.0;
        for (size_t i = 0; i < 100; ++i)
        {
            y *= std::sin(y) * std::sin(y) + std::cos(y) * std::cos(y);
            y+= std::sin(std::cos(y));
        }
        benchmark::DoNotOptimize(y);
    }
}

BENCHMARK(BM_SineEvaluation);

该示例甚至不包含堆分配。编译器没有优化任何 sin/cos 函数。这就是所有的代码。时间测量完全在 Google Benchmark 库中完成,该库可在 github 上公开获得。但到目前为止我还没有研究过实现。

当使用命令行参数 --benchmark_repetitions=50 --benchmark_report_aggregates_only=true 运行程序时,我得到如下输出:

----------------------------------------------------------------
Benchmark                         Time           CPU Iterations
----------------------------------------------------------------
BM_SineEvaluation_mean        11268 ns      11270 ns      64000
BM_SineEvaluation_median      11265 ns      11230 ns      64000
BM_SineEvaluation_stddev         11 ns         90 ns      64000

我在带有 Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24218.1 for x86 (Visual Studio 2015) 和 /O2 的非常旧的 Intel Core i7 920 (Bloomfield) 上使用 Google Benchmark v1.4.1。


编辑:我在 Intel i5-4300U CPU 和 gcc-8.1.1 上对 Fedora-28 做了进一步的测量(它足够聪明,可以用 -O2 调用 sincos),并发现了一个对比的行为:

----------------------------------------------------------------
Benchmark                         Time           CPU Iterations
----------------------------------------------------------------
BM_SineEvaluation_mean        54642 ns      54556 ns      12350
BM_SineEvaluation_median      54305 ns      54229 ns      12350
BM_SineEvaluation_stddev        946 ns        888 ns      12350 

当省略 -O2 时(更接近 MSVC,因为它有单独的 sin/cos 调用),我仍然得到相同的定性结果:实时的标准偏差也大于 cpu 时间的标准偏差。

我不太确定从中得出什么结论。这是否意味着 Windows 上的时间测量不那么精确?

标签: c++performancegoogle-benchmark

解决方案


推荐阅读