google/benchmark: BENCHMARK_TEMPLATE 语法

google/benchmark: BENCHMARK_TEMPLATE syntax

我想 运行 在 floatdoublelong double 上 google/benchmark。

鉴于 BENCHMARK_TEMPLATE example,我尝试了以下操作:

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

template<typename Real>
BM_PowTemplated(benchmark::State& state) {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<Real> dis(1, 10);
    auto s = dis(gen);
    auto t = dis(gen);
    Real y;
    while (state.KeepRunning()) {
        benchmark::DoNotOptimize(y = std::pow(s, t));
    }
    std::ostream cnull(0);
    cnull << y;
}

BENCHMARK_TEMPLATE(BM_PowTemplated, float, double, long double);
BENCHMARK_MAIN();

我以为这会为 float、double 和 long double 创建三个基准测试,但它没有编译!

创建模板化 google 基准的正确语法是什么?关于 BENCHMARK_TEMPLATE 应该如何工作的我的心智模型是否正确?如果正确,我该如何修复此代码?

您对

BENCHMARK_TEMPLATE 使用方式有误
BENCHMARK_TEMPLATE(BM_PowTemplated, float, double, long double);

https://github.com/google/benchmark/ 的自述文件说

template <class Q> int BM_Sequential(benchmark::State& state) { .. }
BENCHMARK_TEMPLATE(BM_Sequential, WaitQueue<int>)->Range(1<<0, 1<<10);

Three macros are provided for adding benchmark templates.

#define BENCHMARK_TEMPLATE(func, ...) // Takes any number of parameters.

#define BENCHMARK_TEMPLATE1(func, arg1)
#define BENCHMARK_TEMPLATE2(func, arg1, arg2)

因此,BENCHMARK_TEMPLATE with arg1 用于具有一个模板参数的函数,with arg1 和 arg2 用于具有两个模板参数的函数。您的 BM_PowTemplated 只有一个参数,因此您不能将 BENCHMARK_TEMPLATE 与 3 个参数一起使用。

检查 google/benchmark 的 test/cxx03_test.cc 例如:https://github.com/google/benchmark/blob/b2e734087532897b7bb4c51a6b4f503060c9a20f/test/cxx03_test.cc

template <class T, class U>
void BM_template2(benchmark::State& state) {
    BM_empty(state);
}
BENCHMARK_TEMPLATE2(BM_template2, int, long);

template <class T>
void BM_template1(benchmark::State& state) {
    BM_empty(state);
}
BENCHMARK_TEMPLATE(BM_template1, long);
BENCHMARK_TEMPLATE1(BM_template1, int);

PS:宏定义: https://github.com/google/benchmark/blob/2d088a9f2d41acb77afc99d045f669e1a21b61ef/include/benchmark/benchmark_api.h#L684

我们可以看到宏的a(a, b)个参数在<>里面,它们被用作f< a,b >:

// template<int arg>
// void BM_Foo(int iters);
//
// BENCHMARK_TEMPLATE(BM_Foo, 1);
//
// will register BM_Foo<1> as a benchmark.
#define BENCHMARK_TEMPLATE1(n, a) \
  BENCHMARK_PRIVATE_DECLARE(n) =  \
      (::benchmark::internal::RegisterBenchmarkInternal( \
        new ::benchmark::internal::FunctionBenchmark(#n "<" #a ">", n<a>)))

#define BENCHMARK_TEMPLATE2(n, a, b)                     \
  BENCHMARK_PRIVATE_DECLARE(n) =                         \
      (::benchmark::internal::RegisterBenchmarkInternal( \
        new ::benchmark::internal::FunctionBenchmark(    \
            #n "<" #a "," #b ">", n<a, b>)))

#define BENCHMARK_TEMPLATE(n, ...)           \
  BENCHMARK_PRIVATE_DECLARE(n) =             \
      (::benchmark::internal::RegisterBenchmarkInternal( \
        new ::benchmark::internal::FunctionBenchmark( \
        #n "<" #__VA_ARGS__ ">", n<__VA_ARGS__>)))

因此,BENCHMARK_TEMPLATE 无法迭代多个变体并从一行定义函数的多个变体。