Как передать аргументы в программу Google Benchmark
У меня есть C++ Google Benchmark Programm. Он использует Google BENCHMARK_MAIN()
метод. Теперь я вызываю и выполняю скомпилированную программу со скриптом Go. Есть ли способ передать аргументы в мою тестовую программу? (Я знаю общий способ работы с основным методом, но я не уверен, как это сделать в Googles, потому что он реализован в benchmark_api.h
и я не могу просто изменить это.)
Обновить:
До сих пор я скопировал тело макро в мой файл benchmark.cpp и добавил строку. Это не очень хорошее решение, потому что возможные изменения от Google на этом Макро (например, изменение имени или добавленной строки кода) не повлияют на мою копию. Это работает наконец.
int main (int argc, char** argv)
{
MyNamespace::conf = {argv[1]};
::benchmark::Initialize (&argc, argv);
::benchmark::RunSpecifiedBenchmarks ();
}
3 ответа
Взломать весь BENCHMARK_MAIN
Функция - это, конечно, один из способов сделать это, но ИМО - это действительно громоздко и ужасно. Поэтому я просто предложу другой подход:
// define your chunksize and iteration count combinations here (for i and j)
static void CustomArguments(benchmark::internal::Benchmark* b) {
for (int i = 0; i <= 10; ++i)
for (int j = 0; j <= 50; ++j)
b->Args({i, j});
}
// the string (name of the used function is passed later)
static void TestBenchmark(benchmark::State& state, std::string func_name) {
// cout for testing purposes
std::cout << state.range(0) /* = i */ << " " << state.range(1) /* = j */
<< " " << func_name << std::endl;
for (auto _ : state) {
// do whatever with i and j and func_name
}
}
// This macro is used to pass the string "function_name1/2/3"
// as a parameter to TestBenchmark
BENCHMARK_CAPTURE(TestBenchmark, benchmark_name1, "function_name1")
->Apply(CustomArguments);
BENCHMARK_CAPTURE(TestBenchmark, benchmark_name2, "function_name2")
->Apply(CustomArguments);
BENCHMARK_CAPTURE(TestBenchmark, benchmark_name3, "function_name3")
->Apply(CustomArguments);
BENCHMARK_MAIN()
А затем в вашем скрипте go вы вызываете эталон с помощью фильтра регулярных выражений:./prog_name --benchmark_filter=InsertRegexFilterHere
Так, например:./prog_name --benchmark_filter=TestBenchmark/benchmark_name2/5/35
Приведенный выше пример вызовет эталонный тест и передаст "имя_функции2", 5 и 35 (это значения для вашего размера фрагмента и количества итераций), и поэтому результат будет примерно таким:
------------------------------------------------------------------------------
Benchmark Time CPU Iterations
------------------------------------------------------------------------------
TestBenchmark/benchmark_name2/5/35 2 ns 2 ns 308047644
Я хотел бы расширить ответ Майка ван Дайка, добавив, что библиотека также поддерживает следующее:
static void BM_SetInsert(benchmark::State& state) {
std::set<int> data;
for (auto _ : state) {
state.PauseTiming();
data = ConstructRandomSet(state.range(0));
state.ResumeTiming();
for (int j = 0; j < state.range(1); ++j)
data.insert(RandomNumber());
}
}
BENCHMARK(BM_SetInsert)
->Args({1<<10, 128})
->Args({2<<10, 128})
->Args({4<<10, 128})
->Args({8<<10, 128})
->Args({1<<10, 512})
->Args({2<<10, 512})
->Args({4<<10, 512})
->Args({8<<10, 512});
В вашем тесте
state.range(0)
и
state.range(1)
теперь относится к первому и второму аргументу соответственно. См. Больше @ https://github.com/google/benchmark#passing-arguments
Как описано в https://github.com/google/benchmark/blob/main/docs/user_guide.md#using-registerbenchmarkname-fn-args, тесты можно регистрировать в интерактивном режиме следующим образом:
auto BM_test = [](benchmark::State& st, auto Inputs) { /* ... */ };
int main(int argc, char** argv) {
for (auto& test_input : { /* ... */ })
benchmark::RegisterBenchmark(test_input.name(), BM_test, test_input);
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
benchmark::Shutdown();
}
Следует отметить, что обычно он прерывается, если видит неизвестные аргументы. Это не относится кbenchmark::Initialize
. Эта функция удаляет всеbenchmark
конкретные варианты, такие как--benchmark_filter
,--benchmark_out
... from и оставляет неизвестные параметры и позиционные аргументы нетронутыми (также изменяется).
Это означает, что можно позвонить
benchmark::Initialize(&argc, argv);
а затем получить аргументы, специфичные для программы, из очищенногоargc
иargv
.