淺談c++性能測試工具之計(jì)算時(shí)間復(fù)雜度
google benchmark已經(jīng)為我們提供了類似的功能,而且使用相當(dāng)簡單。
具體的解釋在后面,我們先來看幾個(gè)例子,我們?nèi)藶橹圃鞄讉€(gè)時(shí)間復(fù)雜度分別為O(n), O(logn), O(n^n)的測試用例:
// 這里都是為了演示而寫成的代碼,沒有什么實(shí)際意義 static void bench_N(benchmark::State& state) { int n = 0; for ([[maybe_unused]] auto _ : state) { for (int i = 0; i < state.range(0); ++i) { benchmark::DoNotOptimize(n += 2); // 這個(gè)函數(shù)防止編譯器將表達(dá)式優(yōu)化,會(huì)略微降低一些性能 } } state.SetComplexityN(state.range(0)); } BENCHMARK(bench_N)->RangeMultiplier(10)->Range(10, 1000000)->Complexity(); static void bench_LogN(benchmark::State& state) { int n = 0; for ([[maybe_unused]] auto _ : state) { for (int i = 1; i < state.range(0); i *= 2) { benchmark::DoNotOptimize(n += 2); } } state.SetComplexityN(state.range(0)); } BENCHMARK(bench_LogN)->RangeMultiplier(10)->Range(10, 1000000)->Complexity(); static void bench_Square(benchmark::State& state) { int n = 0; auto len = state.range(0); for ([[maybe_unused]] auto _ : state) { for (int64_t i = 1; i < len*len; ++i) { benchmark::DoNotOptimize(n += 2); } } state.SetComplexityN(len); } BENCHMARK(bench_Square)->RangeMultiplier(10)->Range(10, 100000)->Complexity();
如何傳遞參數(shù)和生成批量測試我們在上一篇已經(jīng)介紹過了,這里不再重復(fù)。
需要關(guān)注的是新出現(xiàn)的state.SetComplexityN和Complexity。
首先是state.SetComplexityN,參數(shù)是一個(gè)64位整數(shù),用來表示算法總體需要處理的數(shù)據(jù)總量。benchmark會(huì)根據(jù)這個(gè)數(shù)值,再加上運(yùn)行耗時(shí)以及state的迭代次數(shù)計(jì)算出一個(gè)用于后面預(yù)估*均時(shí)間復(fù)雜度的值。
Complexity會(huì)根據(jù)同一組的多個(gè)測試用例計(jì)算出一個(gè)較接*的*均時(shí)間復(fù)雜度和一個(gè)均方根值,需要和state.SetComplexityN配合使用。
Complexity還有一個(gè)參數(shù),可以接受一個(gè)函數(shù)或是benchmark::BigO枚舉,它的作用是提示benchmark該測試用例的時(shí)間復(fù)雜度,默認(rèn)值為benchmark::oAuto,測試中會(huì)自動(dòng)幫我們計(jì)算出時(shí)間復(fù)雜度。對于較為復(fù)雜的算法,而我們又有預(yù)期的時(shí)間按復(fù)雜度,這時(shí)我們就可以將其傳給這個(gè)方法,比如對于第二個(gè)測試用例,我們還可以這樣寫:
static void bench_LogN(benchmark::State& state) { // 中間部分與前面一樣,略過 } BENCHMARK(bench_LogN)->RangeMultiplier(10)->Range(10, 1000000)->Complexity(benchmark::oLogN);
在選擇正確的提示后對測試結(jié)果幾乎沒有影響,除了偏差值可以降得更低,使結(jié)果更準(zhǔn)確。
Complexity在計(jì)算時(shí)間復(fù)雜度時(shí)會(huì)保留復(fù)雜度的系數(shù),因此,如果我們發(fā)現(xiàn)給出的提示的時(shí)間復(fù)雜度前的系數(shù)過大的話,就意味著我們的預(yù)估發(fā)生了較大的偏差,同時(shí)它還會(huì)計(jì)算出RMS值,同樣反應(yīng)了時(shí)間復(fù)雜度的偏差情況。
運(yùn)行我們的測試:
可以看到,自動(dòng)的時(shí)間復(fù)雜度計(jì)算基本是準(zhǔn)確的,可以在我們對算法進(jìn)行測試時(shí)提供一個(gè)有效的參考。
以上就是淺談c++性能測試工具之計(jì)算時(shí)間復(fù)雜度的詳細(xì)內(nèi)容,更多關(guān)于c++性能測試工具之計(jì)算時(shí)間復(fù)雜度的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語言中實(shí)現(xiàn)“17進(jìn)制”轉(zhuǎn)“10進(jìn)制”實(shí)例代碼
這篇文章主要介紹了C語言中實(shí)現(xiàn)“17進(jìn)制”轉(zhuǎn)“10進(jìn)制”實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-05-05C語言求Fibonacci斐波那契數(shù)列通項(xiàng)問題的解法總結(jié)
斐波那契數(shù)列相關(guān)問題是考研和ACM中常見的算法題目,這里特地為大家整理了C語言求Fibonacci斐波那契數(shù)列通項(xiàng)問題的解法總結(jié),需要的朋友可以參考下2016-06-06VisualStudio2019配置OpenCV4.5.0的方法示例
這篇文章主要介紹了VisualStudio2019配置OpenCV4.5.0的方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03delete[] p->elems和free(p->elems)區(qū)別介紹
delete[]和free()都是釋放內(nèi)存的函數(shù),但它們具有不同的使用方法和適用情況,這篇文章主要介紹了delete[] p->elems和free(p->elems)有什么區(qū)別,需要的朋友可以參考下2023-04-04C語言實(shí)現(xiàn)求解最小公倍數(shù)的算法示例
這篇文章主要為大家介紹了C語言如何實(shí)現(xiàn)求解任意兩個(gè)正整數(shù)的最小公倍數(shù),文中采用了窮舉法和定理法。感興趣的小伙伴快來跟隨小編一起學(xué)習(xí)學(xué)習(xí)吧2021-12-12