Google benchmark使用手册及范例
構建集成
在robotic_arm的third_party已經集成了benchmark,只需在相關測試用例代碼的CmakeLists.txt添加如下內容:
target_link_libraries(xxx PRIVATE benchmark pthread)Demo樣例
存在以下模式樣例:
1. 使用BENCHMARK、BENCHMARK_MAIN宏
#include <benchmark/benchmark.h> #include <chrono> #include <thread>void BM_DemoSleep(benchmark::State& state) {for (auto _ : state){//待測試的代碼} } BENCHMARK(BM_DemoSleep); // 注冊要測試的函數對象BENCHMARK_MAIN(); // main函數,運行benchmark初始化和執行2. 直接使用Benchmark相應的接口
#include <benchmark/benchmark.h> #include <chrono> #include <thread>void BM_DemoSleep(benchmark::State& state) {for (auto _ : state){std::this_thread::sleep_for(std::chrono::nanoseconds(1000)); //待測試的代碼} }void BM_DemoSleep1(benchmark::State& state, int id) {std::cout << "id:"<< id << std::endl;for (auto _ : state){std::this_thread::sleep_for(std::chrono::nanoseconds(1000));} }int main(int argc, char** argv) {::benchmark::Initialize(&argc, argv); // 初始化Benchmarkif (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;// 使用函數指針注冊::benchmark::RegisterBenchmark("BM_DemoSleep", &BM_DemoSleep);// 使用Lamba函數注冊::benchmark::RegisterBenchmark("BM_DemoSleep1", [](benchmark::State& state){for (auto _ : state){std::this_thread::sleep_for(std::chrono::nanoseconds(1000));}});// 使用帶參數的函數指針注冊int id = 10;::benchmark::RegisterBenchmark("BM_DemoSleep2", &BM_DemoSleep1, id);::benchmark::RunSpecifiedBenchmarks(); // 運行::benchmark::Shutdown(); }3. 使用Fixture
class BMDemo : public benchmark::Fixture { public:void SetUp(const benchmark::State& state) {id_ = 2;}void TearDown(const ::benchmark::State& state) {id_ = 0;}int GetId() const {return id_;}; private:int id_{0}; };BENCHMARK_F(BMDemo, Test0)(benchmark::State& state) {for (auto _ : state) {std::this_thread::sleep_for(std::chrono::milliseconds(GetId())); // test code} } BENCHMARK_F(BMDemo, Test1)(benchmark::State& state) {for (auto _ : state) {std::this_thread::sleep_for(std::chrono::milliseconds(GetId())); // test code} }原理:BENCHMARK_F(BMDemo, Test0)(benchmark::State& state){},會創建一個BMDemo_Test0_Benchmark的類,繼承至BMDemo,然后實現BMDemo_Test0_Benchmark::BenchmarkCase(benchmark::State& state){}成員函數;在Fixture的Run方法中會一次調用SetUp->BenchmarkCase->TearDown
配置參數
1. Arg參數
| Benchmark* Arg(int64_t x); | 向Benchmark對象的std::vector<std::vector<int64_t> > args_添加一個元素(元素為vector{x}) |
| Benchmark* Range(int64_t start, int64_t limit); | Benchmark* Range(int64_t start, int64_t limit); |
| Benchmark* DenseRange(int64_t start, int64_t limit, int step = 1); | Benchmark* DenseRange(int64_t start, int64_t limit, int step = 1); |
| Benchmark* Args(const std::vector<int64_t>& args); | 向Benchmark對象的std::vector<std::vector<int64_t> > args_添加一個元素(元素為args) |
| Benchmark* ArgPair(int64_t x, int64_t y) | 向Benchmark對象的std::vector<std::vector<int64_t> > args_添加一個元素(元素為vector{x,y}) |
2. 測試多少次(iterations)
會有如下策略(簡單的將如果沒有明確設置iteration,會使用相應的計算方法(會使用到min_time),遞增迭代次數然后以最后一個確定的結果report):
我們可能逐漸增加基準的長度(迭代次數),直到我們確定結果是重要的。 一旦我們這樣做了,我們就會報告最后的結果并退出。 請注意,如果有重復,則迭代計數僅為第一次重復計算,其他重復僅使用該預先計算的迭代計數。
3. 重復多少次(Repetitions)
指的是整個函數對象調用多少次,默認值是1
::benchmark::RegisterBenchmark("BM_Arg", &BM_Arg)->Iterations(10)->Repetitions(3); // 迭代執行10次,也就是for(auto _ : state){}循環會迭代10次; 重復調用3次4. 顯示時間單位
Benchmark* Unit(TimeUnit unit);
設置顯示時間單位:
kNanosecond, kMicrosecond, kMillisecond, kSecond.
5. 多線程
| Benchmark* Threads(int t); | 設置多少個線程運行測試(線程函數中運行注冊的函數對象) |
| Benchmark* ThreadRange(int min_threads, int max_threads); | 類似args_, 以min_threads為起點,倍率為2,終點為 max_threads,向thread_counts_添加元素比如: Range(1, 16), Threads(1)->Threads(2)-> Threads(4)-> Threads(8)-> Threads(16),分別以1、2、4、8、16個線程進行測試 |
| Benchmark* DenseThreadRange(int min_threads, int max_threads, int stride = 1); | 類似args_, 以min_threads為起點,步長為1,終點為 max_threads,向thread_counts_添加元素,DenseThreadRange(1, 8, 3), 1、4、7、8個線程進行測試 |
6. 時間類型
void BM_Arg(benchmark::State& state) {for (auto _ : state) {auto start = std::chrono::high_resolution_clock::now();// Simulate some useful workload with a sleepstd::this_thread::sleep_for(sleep_duration);auto end = std::chrono::high_resolution_clock::now();auto elapsed_seconds =std::chrono::duration_cast<std::chrono::duration<double>>(end - start);state.SetIterationTime(elapsed_seconds.count());}}::benchmark::RegisterBenchmark("BM_Arg", &BM_Arg)->UseManualTime();7. 統計分析結果
會統計每次的結果,然后輸出分析結果:
mean: 平均值、median: 中值、stddev: 標準差、cv:標準差/平均值
自定義分析結果,比如最小值,最大值
接口:
示例:
::benchmark::RegisterBenchmark("BM_Arg", &BM_Arg)->Iterations(10)->Repetitions(10)->Unit(benchmark::kMillisecond)->ComputeStatistics("max", [](const std::vector<double>& v)->double{return *std::max_element(v.begin(), v.end());}, benchmark::kTime)->ComputeStatistics("min", [](const std::vector<double>& v)->double{return *std::min_element(v.begin(), v.end());}, benchmark::kTime);命令行
–benchmark_out_format=<console|json|csv>
定義輸出格式
–benchmark_out=
定義文件名
–benchmark_filter=
定義過濾規則(正則表達式)
–benchmark_repetitions=n
定義重復次數
–benchmark_report_aggregates_only={true|false}
上報內容是否只上報聚合內容(省略每次repetition的內容)
–benchmark_display_aggregates_only={true|false}
屏幕輸出內容是否只上報聚合內容(省略每次repetition的內容)
其他
模版方法和模版Fixture本文無介紹,相關使用方法可以參考google benchmark的github地址
總結
以上是生活随笔為你收集整理的Google benchmark使用手册及范例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BL5372 RTC linux驱动
- 下一篇: Benchmark和Baseline的含