如何使用谷歌基准测试对自定义界面进行基准测试

How to benchmark custom interface using google benchmark

本文关键字:基准测试 自定义界面 谷歌 何使用      更新时间:2023-10-16

由于除了 github 自述文件之外,我找不到真正好的资源或文档,所以我会在这里询问社区。

假设我有一个名为Base的接口和多个派生类型。
我想对具有相同函数和传递给Foo的相同参数的所有派生类型Foo的虚函数进行基准测试。
对于每个派生类型,我想在单个基准测试中多次调用Foo,并使用从std::vector<std::size_t>传递的不同参数。

此外,我的一些派生类型的构造函数需要额外的参数,我应该如何处理它?

在我看来,最简单的事情是使用模板化基准并传递给:

const std::vector<std::size_t> v {1, 2, 4, 8, 16};
BENCHMARK_TEMPLATE(func, Derived1, v);
BENCHMARK_TEMPLATE(func, Derived2, v);
BENCHMARK_TEMPLATE(func, Derived3, v);
...

我不认为这是正确的方法,因为对于具有不同构造函数签名的每个派生类型,我需要具有与前一个几乎相同的不同基准函数。

对此进行基准测试的正确方法是什么?

**更新*: 我解决这个问题的方法如下:

std::unique_ptr<Base> GetObj(const std::size_t index)
{
switch(index)
{
case 0:
return std::make_unique<Derived1>(...);
case 1:
return std::make_unique<Derived2>(...);
...
}
}
void func(benchmark::State& state)
{
auto r = state.range();
auto object = GetObj(r);
for (auto _ : state)
{
...
}
}
BENCHMARK(func)->DenseRange(0,5);

但我不喜欢的是,基准测试的名称是模式func/0-5,我希望它是func/Derived1func/Derived2等等......任何想法如何实现这一点?

你的方法非常正确。如果要避免多个基准测试函数,请将基准测试的核心移动到单独的函数中,并从每个类型的函数中调用它。 像这样:

static void Benchmark(Base* b, benchmark::State& st) {
for (auto _ : state) {
b->DoTheThing()
}
}
void BM_Foo(benchmark::State& st) {
Foo f;
Benchmark(&f, st);
}
BENCHMARK(BM_Foo);

如果你想更复杂,你可以使用RegisterBenchmark功能更灵活地注册事物。像这样:

auto BM_base = [](benchmark::State& st, auto inputs, Base* b) { /* ... */ };
int main(int argc, char**argv) {
const std::vector<std::size_t> v = {1, 2, 4, 8, 16};
benchmark::RegisterBenchmark("foo", BM_base, v, new Foo());
benchmark::Initialize(&argc, argv);
return benchmark::RunSpecifiedBenchmarks();
}

顺便说一句,在注册基准时是否应该将 v 设置为Args?