Google 基准迭代是什么意思?
What is the meaning of Google Benchmark Iteration?
我正在使用 Google Benchmark 来测量某些代码的执行时间。比如我写了下面的代码来衡量它的执行时间性能
#include <benchmark/benchmark.h>
// Alternatively, can add libraries using linker options.
#ifdef _WIN32
#pragma comment ( lib, "Shlwapi.lib" )
#ifdef _DEBUG
#pragma comment ( lib, "benchmarkd.lib" )
#else
#pragma comment ( lib, "benchmark.lib" )
#endif
#endif
static void BenchmarkTestOne(benchmark::State& state) {
int Sum = 0;
while (state.KeepRunning())
{
for (size_t i = 0; i < 100000; i++)
{
Sum += i;
}
}
}
static void BenchmarkTestTwo(benchmark::State& state) {
int Sum = 0;
while (state.KeepRunning())
{
for (size_t i = 0; i < 10000000; i++)
{
Sum += i;
}
}
}
// Register the function as a benchmark
BENCHMARK(BenchmarkTestOne);
BENCHMARK(BenchmarkTestTwo);
// Run the benchmark
BENCHMARK_MAIN();
当上面的代码有运行时,它显示了以下结果:
Benchmark Time CPU Iterations
-----------------------------------------------------------
BenchmarkTestOne 271667 ns 272770 ns 2635
BenchmarkTestTwo 27130981 ns 27644231 ns 26
但是我没弄明白这里的Iterations是什么意思?还有为什么时间和 CPU 彼此不同?
Google Benchmark 尝试用相似的 时间 、and/or 对每个候选人进行基准测试,时间足够长以获得稳定的结果。
基准计算它实际进行了多少次迭代,以及确切的时间。慢得多的每次迭代基准测试将执行更少的迭代。
打印输出是(计算的)每次迭代时间,以及基准函数的(计数)迭代。
它实际上可能是对 state.KeepRunning()
的调用计数,但我不知道详细程度。
仅供参考,您的基准测试循环不会 return 任何结果或在循环后将其存储到 volatile
,因此编译器可以轻松优化循环。另请注意,带符号的溢出在 C 中是 UB,您的 int
肯定会溢出。
(或者 clang 仍然可以将那些求和循环优化为基于高斯 n * (n+1) / 2
的封闭形式公式,但避免溢出。)
禁用优化的基准测试没有用;别这样。
正如用户指南所写:
执行基准二进制文件时,每个基准函数都是 运行 串行。 运行 的迭代次数是通过 运行 几次基准测试并测量所用时间并确保最终结果在统计上稳定来动态确定的。因此,与较慢的基准函数相比,较快的基准函数将 运行 进行更多次迭代,因此报告了迭代次数。
所以迭代是在同一个极限时间内,基准函数可以迭代一次。迭代次数越大,程序越快。
我正在使用 Google Benchmark 来测量某些代码的执行时间。比如我写了下面的代码来衡量它的执行时间性能
#include <benchmark/benchmark.h>
// Alternatively, can add libraries using linker options.
#ifdef _WIN32
#pragma comment ( lib, "Shlwapi.lib" )
#ifdef _DEBUG
#pragma comment ( lib, "benchmarkd.lib" )
#else
#pragma comment ( lib, "benchmark.lib" )
#endif
#endif
static void BenchmarkTestOne(benchmark::State& state) {
int Sum = 0;
while (state.KeepRunning())
{
for (size_t i = 0; i < 100000; i++)
{
Sum += i;
}
}
}
static void BenchmarkTestTwo(benchmark::State& state) {
int Sum = 0;
while (state.KeepRunning())
{
for (size_t i = 0; i < 10000000; i++)
{
Sum += i;
}
}
}
// Register the function as a benchmark
BENCHMARK(BenchmarkTestOne);
BENCHMARK(BenchmarkTestTwo);
// Run the benchmark
BENCHMARK_MAIN();
当上面的代码有运行时,它显示了以下结果:
Benchmark Time CPU Iterations
-----------------------------------------------------------
BenchmarkTestOne 271667 ns 272770 ns 2635
BenchmarkTestTwo 27130981 ns 27644231 ns 26
但是我没弄明白这里的Iterations是什么意思?还有为什么时间和 CPU 彼此不同?
Google Benchmark 尝试用相似的 时间 、and/or 对每个候选人进行基准测试,时间足够长以获得稳定的结果。
基准计算它实际进行了多少次迭代,以及确切的时间。慢得多的每次迭代基准测试将执行更少的迭代。
打印输出是(计算的)每次迭代时间,以及基准函数的(计数)迭代。
它实际上可能是对 state.KeepRunning()
的调用计数,但我不知道详细程度。
仅供参考,您的基准测试循环不会 return 任何结果或在循环后将其存储到 volatile
,因此编译器可以轻松优化循环。另请注意,带符号的溢出在 C 中是 UB,您的 int
肯定会溢出。
(或者 clang 仍然可以将那些求和循环优化为基于高斯 n * (n+1) / 2
的封闭形式公式,但避免溢出。)
禁用优化的基准测试没有用;别这样。
正如用户指南所写: 执行基准二进制文件时,每个基准函数都是 运行 串行。 运行 的迭代次数是通过 运行 几次基准测试并测量所用时间并确保最终结果在统计上稳定来动态确定的。因此,与较慢的基准函数相比,较快的基准函数将 运行 进行更多次迭代,因此报告了迭代次数。
所以迭代是在同一个极限时间内,基准函数可以迭代一次。迭代次数越大,程序越快。