摘要:建立一個(gè)基線測(cè)試作比較很重要。然而,相對(duì)于一個(gè)經(jīng)典的排序算法基線如快速排序,你可以說(shuō),處理萬(wàn)元素比去快。這一關(guān)聯(lián)由測(cè)試向量來(lái)維護(hù)。接著,測(cè)試的開(kāi)始時(shí)間被獲取到并以毫秒的形式用一個(gè)保存起來(lái)。運(yùn)行一個(gè)手動(dòng)測(cè)試。對(duì)每一個(gè)基線組固定測(cè)試。
介紹
對(duì)代碼進(jìn)行持續(xù)性開(kāi)發(fā)和有意義的基準(zhǔn)測(cè)試是一個(gè)復(fù)雜的任務(wù)。雖然測(cè)試工具本身(Intel? VTune? Amplifier, SmartBear AQTime, Valgrind)與應(yīng)用程序沒(méi)有相關(guān)性,但是它們?cè)谀承r(shí)候?qū)σ恍┬F(tuán)隊(duì),或者說(shuō)是一些繁瑣的工作來(lái)說(shuō)還是很重要的。這個(gè)Celero項(xiàng)目,主要是要建倉(cāng)一個(gè)小型的程序庫(kù),使它可以在加入 C++ 工程和對(duì)代碼進(jìn)行基準(zhǔn)測(cè)試時(shí)能夠非常容易地去重建,分享,并允許在獨(dú)立的運(yùn)行進(jìn)程、開(kāi)發(fā)者或者是工程間進(jìn)行比較。Celero 使用一個(gè)與 GoogleTest 相似的構(gòu)架,使得他的 API 很容易地使用,并融入一個(gè)工程中。當(dāng)你在開(kāi)發(fā)過(guò)程中進(jìn)行自動(dòng)測(cè)試時(shí),自動(dòng)化基準(zhǔn)將會(huì)扮演舉足輕重的作用。
背景通常,編寫(xiě)基準(zhǔn)的目的是為了測(cè)量一段代碼的性能。基準(zhǔn)有助于比較解決同一問(wèn)題的不同方案并選擇其中最合適的一個(gè)。其他時(shí)候,基準(zhǔn)能以一種很有意義的方式突出設(shè)計(jì)或算法改變后的性能影響。
通過(guò)測(cè)量代碼的性能,可以為性能消除那些你以為是正確方案的錯(cuò)誤。只有通過(guò)測(cè)量,你才能確定比如用一張查找表比計(jì)算一個(gè)值更快。這種傳聞(通常是重復(fù)的)可能導(dǎo)致糟糕的設(shè)計(jì)決策,最終生成效率更慢的代碼。
編寫(xiě)好的基準(zhǔn)的目的是為了消除所有噪音和開(kāi)銷(xiāo),并且只測(cè)量被測(cè)代碼。在測(cè)量中,噪音源包括時(shí)鐘分辨率噪音、操作系統(tǒng)后臺(tái)操作、測(cè)試設(shè)置/清除、框架開(kāi)銷(xiāo)以及其他不相干的系統(tǒng)行為。
理論上,我們想測(cè)量被測(cè)代碼的執(zhí)行時(shí)間“t”。實(shí)際上,我們測(cè)到的是“t”與所有噪音的和。
這些影響我們測(cè)量的“t”的不相干因素會(huì)隨時(shí)間變化而波動(dòng)。因此,我們想試圖將“t”隔離出來(lái)。實(shí)現(xiàn)這樣的方法是通過(guò)多次測(cè)量,但只保留最小的總時(shí)間。這個(gè)最小的總時(shí)間必然是受噪音干擾最小且最接近時(shí)間“t”的值。
一旦得到這個(gè)測(cè)量值,在進(jìn)行隔離就沒(méi)什么意義了。建立一個(gè)基線測(cè)試作比較很重要。基線通常應(yīng)該是一個(gè)基于你正要測(cè)量出一個(gè)解決方案的問(wèn)題的“經(jīng)典”或“純粹”的方案。一旦有了一個(gè)基線,你花時(shí)間去比較你的算法就有意義。簡(jiǎn)單地說(shuō),你中意的排序算法(fSort)不能在10毫秒內(nèi)自動(dòng)排序100萬(wàn)元素。然而,相對(duì)于一個(gè)經(jīng)典的排序算法基線如快速排序(qSort),你可以說(shuō),fSort處理100萬(wàn)元素比去Sort快50%。這是個(gè)很有意義且強(qiáng)大的測(cè)量。
Celero大量使用Visual C++和GCC4.7都支持的C++11特性。這對(duì)使代碼整潔、便攜大有幫助。為了使代碼更容易采用,用戶(hù)所需的所有定義都放在一個(gè)命名空間為celero的單一頭文件:Celero.h里。
Celero.h里包含將每個(gè)用戶(hù)基準(zhǔn)用例轉(zhuǎn)換為獨(dú)特的、具有與之相關(guān)測(cè)試固件的類(lèi)(如果有的話),然后登記測(cè)試用例到一個(gè)工廠。這些宏自動(dòng)將基線測(cè)試用例與相關(guān)的測(cè)試基準(zhǔn)關(guān)聯(lián)起來(lái),這樣,在運(yùn)行時(shí)基準(zhǔn)相關(guān)的數(shù)據(jù)就可以被算出。這一關(guān)聯(lián)由測(cè)試向量來(lái)維護(hù)。
測(cè)試向量利用PImpl慣語(yǔ)來(lái)隱藏實(shí)現(xiàn)并且保持包含Celero.h的開(kāi)銷(xiāo)降到最小。
Celero將結(jié)果輸出到命令行。因?yàn)轭伾怯杏玫模赡苡兄谥饔^因素/結(jié)果的可讀性),所以std::cout調(diào)用了自身之外的一些東西。Console.h定義了一個(gè)簡(jiǎn)單的顏色函數(shù),SetConsoleColor,它可以被celero::print命名空間中的函數(shù)用來(lái)格式化程序的輸出。
測(cè)量基準(zhǔn)的執(zhí)行時(shí)間位于TestFixturebase類(lèi)中,而且所有基準(zhǔn)的寫(xiě)法都是以此為基礎(chǔ)派生出來(lái)的。首先,測(cè)試夾具(譯注:test fixture 是檢測(cè)被測(cè)試系統(tǒng)時(shí)所需要的所有東西)的創(chuàng)建代碼被執(zhí)行。接著,測(cè)試的開(kāi)始時(shí)間被獲取到并以毫秒的形式用一個(gè)unsigned long保存起來(lái)。這么做是為了減少浮點(diǎn)指針錯(cuò)誤。再下一步,指定次數(shù)的操作(迭代)被執(zhí)行。結(jié)束時(shí),結(jié)束時(shí)間被抓取到,測(cè)試夾具銷(xiāo)毀,本次執(zhí)行的測(cè)量時(shí)間被返回,并且這個(gè)結(jié)果會(huì)被保存下來(lái)。
無(wú)論指定多少個(gè)樣本,這個(gè)循環(huán)就像這樣重復(fù)。如果樣本沒(méi)有指定(為零),那么測(cè)試將會(huì)重復(fù)運(yùn)行直到一秒鐘,或者至少采集了30個(gè)樣本。當(dāng)寫(xiě)到代碼的這個(gè)特定部分時(shí),顯然這里存在有一種“if-else”的關(guān)系。不管怎么說(shuō),大量的代碼都是如此重復(fù)著“if”與"else"的片段。這里可以使用一個(gè)老式的函數(shù),但是利用std::function來(lái)定義一個(gè) 匿名函數(shù)(lambda)再自然不過(guò),這樣就可以調(diào)用它并使所有的代碼整潔。(c++ 11真是一個(gè)奇妙的東西)最后,結(jié)果被打印到屏幕。
Celero 使用 CMake 去提供跨平臺(tái)構(gòu)件。由于它使用得是 C++ 11,因而需要請(qǐng)求一個(gè)現(xiàn)在流行的編譯器(Visual C++ 2012 or GCC 4.7+)。
一旦你的項(xiàng)目中加入了 Celero,你能夠創(chuàng)建專(zhuān)門(mén)的基準(zhǔn)項(xiàng)目和源文件。為了方便,一個(gè)頭文件和aCELERO_MAINmacro 能提供給 main() ,來(lái)幫助你的基準(zhǔn)項(xiàng)目自動(dòng)去執(zhí)行所有的基準(zhǔn)測(cè)試。
下面有一個(gè)簡(jiǎn)單的 Celero 基準(zhǔn)的例子:
#includeCELERO_MAIN; // 運(yùn)行一個(gè)自動(dòng)的基線。 // Celero 保證能提供足夠的采樣來(lái)得到一個(gè)合理的測(cè)量結(jié)果 BASELINE(CeleroBenchTest, Baseline, 0, 7100000) { celero::DoNotOptimizeAway(static_cast (sin(3.14159265))); } // 運(yùn)行一個(gè)自動(dòng)測(cè)試。 // Celero 保證能提供足夠的采樣來(lái)得到一個(gè)合理的測(cè)量結(jié)果 BENCHMARK(CeleroBenchTest, Complex1, 0, 7100000) { celero::DoNotOptimizeAway(static_cast (sin(fmod(rand(), 3.14159265)))); } // 運(yùn)行一個(gè)手動(dòng)測(cè)試。這是對(duì)一個(gè)樣本進(jìn)行每秒 7100000 次操作。 // Celero 保證能提供足夠的采樣來(lái)得到一個(gè)合理的測(cè)量結(jié)果。 BENCHMARK(CeleroBenchTest, Complex2, 1, 7100000) { celero::DoNotOptimizeAway(static_cast (sin(fmod(rand(), 3.14159265)))); } // 運(yùn)行一個(gè)手動(dòng)測(cè)試。這是對(duì) 60 個(gè)樣本進(jìn)行每秒 7100000 次操作。 // Celero 保證能提供足夠的采樣來(lái)得到一個(gè)合理的測(cè)量結(jié)果。 BENCHMARK(CeleroBenchTest, Complex3, 60, 7100000) { celero::DoNotOptimizeAway(static_cast (sin(fmod(rand(), 3.14159265)))); }
這段代碼中我們做的第一件事情,就是定義一個(gè)BASELINE測(cè)試用例。這個(gè)模版有四個(gè)參數(shù):
BASELINE(GroupName, BaselineName, Samples, Operations)
* GroupName- 基準(zhǔn)組的名字。它是用來(lái)將運(yùn)行與結(jié)果和它們相應(yīng)的基線測(cè)量收集到一起。
* BaselineName- 為了報(bào)表目的的基線的名字。
* Samples- 對(duì)測(cè)試代碼進(jìn)行給定次數(shù)的操作,對(duì)這些操作的總的循環(huán)運(yùn)行次數(shù)。
* Operations- 你希望對(duì)每個(gè)樣本運(yùn)行測(cè)試代碼的次數(shù)。
這里的樣本與操作是用來(lái)測(cè)量非常快的代碼的。例如,如果你知道基準(zhǔn)測(cè)試中的代碼運(yùn)行時(shí)間小于100毫秒,那么在進(jìn)行一次測(cè)量之前,這個(gè)操作次數(shù)將會(huì)指定代碼運(yùn)行"operations"次。而Samples則定義了要做多少次測(cè)量。
Celero允許指定零樣本也有助于此。零樣本將告訴Celero,基于完成指定次數(shù)操作所需要的時(shí)間,采集一些具有統(tǒng)計(jì)學(xué)意義數(shù)量的樣本。這些數(shù)字將會(huì)在運(yùn)行時(shí)給出。
celero::DoNotOptimizeAway模版是用來(lái)保證優(yōu)化編譯器不會(huì)消除你的函數(shù)或代碼。由于這個(gè)功能被用于所有的基準(zhǔn)樣本以及它們的基線,所以相比較起來(lái)其中的額外時(shí)間消耗可以忽略不計(jì)。
在基線被定義之后,接著被定義的是各種各樣的基準(zhǔn)。BENCHMARK宏的語(yǔ)法與普通宏的語(yǔ)法完全相同。
示例項(xiàng)目被設(shè)置為一旦成功編譯就自動(dòng)執(zhí)行基準(zhǔn)測(cè)試代碼。在我的PC上運(yùn)行這個(gè)基準(zhǔn)測(cè)試得到的是以下的輸出:
[ CELERO ] [==========] [ STAGE ] Baselining [==========] [ RUN ] CeleroBenchTest.Baseline -- Auto Run, 7100000 calls per run. [ AUTO ] CeleroBenchTest.Baseline -- 30 samples, 7100000 calls per run. [ DONE ] CeleroBenchTest.Baseline (0.517049 sec) [7100000 calls in 517049 usec] [0.072824 us/call] [13731773.971132 calls/sec] [==========] [ STAGE ] Benchmarking [==========] [ RUN ] CeleroBenchTest.Complex1 -- Auto Run, 7100000 calls per run. [ AUTO ] CeleroBenchTest.Complex1 -- 30 samples, 7100000 calls per run. [ DONE ] CeleroBenchTest.Complex1 (2.192290 sec) [7100000 calls in 2192290 usec] [0.308773 us/call] [3238622.627481 calls/sec] [ BASELINE ] CeleroBenchTest.Complex1 4.240004 [ RUN ] CeleroBenchTest.Complex2 -- 1 run, 7100000 calls per run. [ DONE ] CeleroBenchTest.Complex2 (2.199197 sec) [7100000 calls in 2199197 usec] [0.309746 us/call] [3228451.111929 calls/sec] [ BASELINE ] CeleroBenchTest.Complex2 4.253363 [ RUN ] CeleroBenchTest.Complex3 -- 60 samples, 7100000 calls per run. [ DONE ] CeleroBenchTest.Complex3 (2.192378 sec) [7100000 calls in 2192378 usec] [0.308786 us/call] [3238492.632201 calls/sec] [ BASELINE ] CeleroBenchTest.Complex3 4.240175 [==========] [ STAGE ] Completed. 4 tests complete. [==========]
首次運(yùn)行的測(cè)試將作為整個(gè)組測(cè)試的基線。這個(gè)基線顯示出它是一個(gè)“自動(dòng)測(cè)試”,暗示著由Celero來(lái)衡量并決策運(yùn)行測(cè)試代碼的次數(shù)。這個(gè)案例中,在我們的測(cè)試?yán)锼\(yùn)行7100000次代碼迭代總共30次。(每調(diào)用7100000次測(cè)量一次,這樣30次以后取最小的時(shí)間。)整個(gè)測(cè)量需要0.517049秒。基于這個(gè)結(jié)果,可以測(cè)量出每次對(duì)基準(zhǔn)代碼的調(diào)用需要0.072824毫秒。
在基線測(cè)試結(jié)束之后,將運(yùn)行每個(gè)多帶帶的測(cè)試。每個(gè)測(cè)試的運(yùn)行與測(cè)量方式都是相同的,不過(guò)有一個(gè)額外的度量報(bào)告:基線。將它運(yùn)行基準(zhǔn)測(cè)試代碼所需要的時(shí)間與基線進(jìn)行比較。這里的數(shù)據(jù)顯示,CeleroBenchTest.Complex1比基線運(yùn)行需要的時(shí)間多了4.240004倍。
GitHub 項(xiàng)目點(diǎn)擊 這里.
基準(zhǔn)應(yīng)該總是要在發(fā)行版本中運(yùn)行。但這絕對(duì)不是要求建立一個(gè)調(diào)試工程,也不是要改變?cè)镜慕Y(jié)果。編譯器(進(jìn)行優(yōu)化)將對(duì)你的代碼的執(zhí)行起到非常好的作用。
Celero 在 Doxygen 中存放了 API 文檔。
Celero 對(duì)每一個(gè)基線組固定測(cè)試。
當(dāng)監(jiān)聽(tīng)到第三個(gè)存儲(chǔ)槽時(shí),執(zhí)行代碼使基準(zhǔn)運(yùn)行得更快。這是多么有趣的事啊!
原文:Celero - A C++ Benchmark Authoring Library
轉(zhuǎn)載自:開(kāi)源中國(guó)社區(qū)--super0555, 竟悟, jimmyjmh
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/8686.html
摘要:推薦閱讀資源庫(kù)工具應(yīng)用程序精選列表中文版有哪些鮮為人知,但是很有意思的網(wǎng)站一份攻城獅筆記每天搜集上優(yōu)秀的項(xiàng)目一些有趣的民間故事超好用的谷歌瀏覽器油猴插件合集目錄資源文檔文章圖書(shū)會(huì)談教程更多庫(kù)工具管理數(shù)據(jù)部署桌面發(fā)展監(jiān)控應(yīng)用資源文檔介紹文檔教 推薦閱讀 MongoDB 資源、庫(kù)、工具、應(yīng)用程序精選列表中文版 有哪些鮮為人知,但是很有意思的網(wǎng)站? 一份攻城獅筆記 每天搜集 Github ...
摘要:安全生成安全的隨機(jī)數(shù),加密數(shù)據(jù),掃描漏洞的庫(kù)一個(gè)兼容標(biāo)準(zhǔn)的過(guò)濾器一個(gè)生成隨機(jī)數(shù)和字符串的庫(kù)使用生成隨機(jī)數(shù)的庫(kù)一個(gè)安全庫(kù)一個(gè)純安全通信庫(kù)一個(gè)簡(jiǎn)單的鍵值加密存儲(chǔ)庫(kù)一個(gè)結(jié)構(gòu)化的安全層一個(gè)試驗(yàn)的面向?qū)ο蟮陌b庫(kù)一個(gè)掃描文件安全的庫(kù) Security 安全 生成安全的隨機(jī)數(shù),加密數(shù)據(jù),掃描漏洞的庫(kù) HTML Purifier-一個(gè)兼容標(biāo)準(zhǔn)的HTML過(guò)濾器 RandomLib-一個(gè)生成隨機(jī)數(shù)和字...
摘要:安全生成安全的隨機(jī)數(shù),加密數(shù)據(jù),掃描漏洞的庫(kù)一個(gè)兼容標(biāo)準(zhǔn)的過(guò)濾器一個(gè)生成隨機(jī)數(shù)和字符串的庫(kù)使用生成隨機(jī)數(shù)的庫(kù)一個(gè)安全庫(kù)一個(gè)純安全通信庫(kù)一個(gè)簡(jiǎn)單的鍵值加密存儲(chǔ)庫(kù)一個(gè)結(jié)構(gòu)化的安全層一個(gè)試驗(yàn)的面向?qū)ο蟮陌b庫(kù)一個(gè)掃描文件安全的庫(kù) Security 安全 生成安全的隨機(jī)數(shù),加密數(shù)據(jù),掃描漏洞的庫(kù) HTML Purifier-一個(gè)兼容標(biāo)準(zhǔn)的HTML過(guò)濾器 RandomLib-一個(gè)生成隨機(jī)數(shù)和字...
摘要:誕生已經(jīng)有十年之久,但是真正起勢(shì)得益于去年開(kāi)源了大量的深度學(xué)習(xí)模塊和擴(kuò)展。來(lái)自一個(gè)日本的深度學(xué)習(xí)創(chuàng)業(yè)公司,今年月發(fā)布的一個(gè)框架。顧名思義,是的深度學(xué)習(xí)框架,也是較早的商用級(jí)別的深度學(xué)習(xí)開(kāi)源庫(kù)。 本周早些時(shí)候Google開(kāi)源了TensorFlow(GitHub),此舉在深度學(xué)習(xí)領(lǐng)域影響巨大,因?yàn)镚oogle在人工智能領(lǐng)域的研發(fā)成績(jī)斐然,有著雄厚的人才儲(chǔ)備,而且Google自己的Gmail和搜索...
閱讀 2770·2021-09-24 10:34
閱讀 1870·2021-09-22 10:02
閱讀 2258·2021-09-09 09:33
閱讀 1462·2021-08-13 15:02
閱讀 3273·2020-12-03 17:10
閱讀 1185·2019-08-30 15:44
閱讀 2151·2019-08-30 12:58
閱讀 3234·2019-08-26 13:40