C_and_CPP 板


LINE

有时候会需要比较各种不同实作法的效能。 以前我都是自己使用 gettimeofday,然後自己写测试资料和输出, 不过重复了几次之後就厌烦了,就上网找 library。 到最後我挑了 google 的 benchmark library,跟大家分享一下心得。 https://github.com/google/benchmark 这 library 可以方便的统计执行时间,同时可以支援参数化的测试, 甚至是 template 参数。而且使用起来跟 unit test 很类似,所以容易上手。 我以 binary search 为例子,简单介绍一下如何使用。 我有两个 function : binary_search 和 biased_search 。 都是 binary search ,只是 biased_search 不挑中点来比较而是挑 1/4 处。 测试方法很简单,对於长度为 2^10, 2^12, ..., 2^20 的整数阵列, 测试前先生成一组随机整数放到阵列中并加以排序。 测试的时候是在此有序阵列中搜寻一个随机数字。 最後统计平均的执行时间。 现在介绍如何使用此 library 来作 benchmark 。 首先要宣告一个 class ,且该 class 继承 benchmark::Fixture。 然後把所有的测试资料都宣告成此 class 的 member 。 接着把测试资料的生成程式码写在 SetUp 函数里,这函数会在每组测试之前被呼叫。 举例来说,宣告一个 class SearchBenchmark : public benchmark::Fixture, 此 class 有一个 test 阵列,我想在每组测试之前先取得要测试的阵列长度, 产生指定数量的随机整数,放到此阵列中并排序,那 SetUp 可以写成 void SetUp(const ::benchmark::State& state) { generator.seed(); for (int32_t i = 0; i < state.range_x(); ++i) test[i] = distribution(generator); std::sort(test, test + state.range_x()); } 来生成测试资料。 其中 state.range_x() 代表是测试参数,也就是阵列的长度。 因为在 SetUp 中 reset 乱数产生器的 seed ,所以每组同阵列长度的 测试都会使用一样的资料和随机查询。 而测试的时候,则是使用 BENCHMARK_DEFINE_F 的 macro 来告诉 library 所要测试 的部分。以测试 binary_search 的效能为例: BENCHMARK_DEFINE_F(SearchBenchmark, BinarySearch)(benchmark::State& state) { while (state.KeepRunning()) { int32_t r = distribution(generator); benchmark::DoNotOptimize(binary_search(test, state.range_x(), r)); } } 在 loop 之中需要先 check state.KeepRunning() ,如果 benchmark 还在继续 那就呼叫 binary_search 。而 state.range_x() 代表测试的参数,也就是阵 列的长度。 BENCHMARK_DEFINE_F 的第一个参数是 fixture 的 class 名字,第二个参数是 这个测试的名字。 呼叫 DoNotOptimize 是为了避免 compiler 把结果最佳化掉而导致 binary_search 没有被呼叫。 而测试参数的给定是透过 BENCHMARK_REGISTER_F 的 macro 。 以 BinarySearch 测试为例: BENCHMARK_REGISTER_F(SearchBenchmark, BinarySearch) ->RangeMultiplier(4)->Range(1 << 10, 1 << 20); 会产生 6 组测试,参数分别是 2^10, 2^12, 2^14, 2^16, 2^18, 2^20 。 每一个测试会被执行大约数秒 (使用者可调整)。 测试结束时会统计实际所花的时间和 iterations 的数量。 我设定每组测试跑至少五秒,撷取部份的结果如下: Benchmark Time CPU Iterations ------------------------------------------------------------------------- SearchBenchmark/Random/1024k 64 ns 64 ns 109865274 SearchBenchmark/BinarySearch/256k 305 ns 304 ns 22751716 SearchBenchmark/BinarySearch/1024k 517 ns 516 ns 13595401 SearchBenchmark/BiasedSearch/256k 231 ns 231 ns 29824178 SearchBenchmark/BiasedSearch/1024k 348 ns 347 ns 19306835 SearchBenchmark/STLSearch/256k 298 ns 298 ns 23643489 SearchBenchmark/STLSearch/1024k 506 ns 505 ns 13852965 SearchBenchmark/BSearch/256k 348 ns 347 ns 20436083 SearchBenchmark/BSearch/1024k 584 ns 582 ns 11745972 其中 Random: 生成随机数的时间 BinarySearch: 正常的二分搜寻 BiasedSearch: 挑 1/4 处来比较的二分搜寻 STLSearch: std::lower_bound BSearch: C library 里面的 bsearch 。 (BinarySearch 和 BiasedSearch 是跟 std::lower_bound 一样, 如果要搜寻的元素不在阵列中,就会回传第一个不比搜寻元素小的位置) 而 Time 和 CPU 分别平均每次函式呼叫所用的时间,所以越小表示速度越快。 以结果来看, 一般的 binary search 和 biased search 在长度小於 256k 时 速度是没有差别的。 但是当长度大於 256k 之後,挑 1/4 处来比较是会比挑中点稍微快一点的。 这现象已经被发现很久了,据说原因是 CPU 的 branch prediction 的机制, 如果每次都挑中点来比较,搜寻的元素又是随机的,那每次比较的结果都很难预测。 如果挑 1/4 处, 那比较的结果就是 biased 的,所以比较好预测。 但是效能的差别大概只会有 3~5 % 。 只是我也不知道要怎麽验证这个说法就是了,希望以後 library 可以提供 performance counter 的资讯。 当然这是因为整数之间比较非常的快, misprediction rate 才变得重要。 如果元素之间比较很慢,又或是阵列很大导致 cache miss penalty 很大, 那 misprediction rate 就不重要了。 --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 24.23.200.172
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1468784920.A.41D.html
1F:推 longlongint: 感谢分享。用 profiling tool 就可以拿到效能分析资 07/18 04:45
2F:→ longlongint: 料,但是我还没学会怎麽用,提供关键字给你参考。 07/18 04:45
3F:→ FRAXIS: profiling toll 可以拿到 performance counter 资讯 07/18 05:36
4F:→ FRAXIS: 但是 benchmark library 的好处是提供简便的方式根据参数 07/18 05:37
5F:→ FRAXIS: 生成想要的测试 07/18 05:38
6F:推 damody: 赞 07/18 08:17
7F:推 Ommm5566: 07/18 11:32
8F:推 Caesar08: 推 07/18 13:10
9F:推 ilikekotomi: 感谢分享 07/18 20:27
10F:→ longlongint: 了解 省工夫是重点 07/18 22:26
11F:推 lunastorm: https://www.youtube.com/watch?v=nXaxk27zwlk 07/19 07:58
12F:推 lunastorm: 可以看这个CppCon2015的talk, 讲得蛮仔细~ 07/19 07:59
13F:推 Sidney0503: 推楼上那个 07/19 09:18
14F:推 Sidney0503: 那个影片好好笑XDDDDDD 07/19 10:54
15F:→ FRAXIS: CppCon 看起来不错 还有什麽跟 optimization 相关的 talk? 07/19 21:19







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:Gossiping站内搜寻

TOP