詳解如何在C/C++中測量一個函數或功能的運行時間
最常用的clock()
最常用的測量方法是使用clock()
來記錄兩個 CPU 時間點clock_t
,然后做差。這個方法的好處在于非常簡單易寫,如下(第一行是為說明需要導入哪個庫):
#include <time.h> ..... clock_t begin = clock(); ...需要被測量的代碼 clock_t end = clock(); int duration = (end - begin)/CLOCKS_PER_SEC;
需要注意 3 點:
CLOCKS_PER_SEC
在 macOS 上是 1000000,也就是說(end - begin)
的單位是微秒,所以要除以CLOCKS_PER_SEC
。- 不同平臺的
clock_t
類型是不一樣的,有些平臺是整數型,有些是使用浮點型。如果是浮點型的話,CLOCKS_PER_SEC
或許可以不用寫,還是要看time.h
的相關內容。 - 這個方法中的“clock”一詞表示的是時鐘頻率,而不是時間。早期的計算機是固定頻率的(現在的一些計算器或者單片機其實也是固定頻率的),這個方法就是誕生于那個時間的。
這種方法最大的弊端就是它測量是 CPU 運行時間,準確的說是該進程使用 CPU 的時間。這就導致了對于非 CPU 密集型程序來說,這個結果可能不是那么精確。當然導致的最大的問題是并行計算程序得到的時間完全不對,而且不能簡單地使用核心數計算得到正確的時間。
因為這個方法是將多個 CPU 的運行時間加在一起了,串行計算的程序完全沒有問題,但是并行計算的話,CPU 使用率一般不會達到或接近核心數*100%
,因為計算機上還有其他任務也需要 CPU。比如說如果串行計算的程序使用率一般在 99% 左右,獲取時間為 30 秒,但是對于 6 核的設備上運行的并行計算程序的話,CPU 使用率達到 570% 就很不錯了,獲取的時間可能為 27 秒,而實際上只用了 5 秒。
這是我在使用 ISPC 編寫并行計算程序的時候發(fā)現的,所以我想尋找到新的方案,于是我發(fā)現了下一個方法。
timespec
timespec
是一個簡單的日歷時間或者時間流逝。通過使用日歷時間可以解決上一節(jié)中無法測量并行程序的實際運行時間的問題。但是“簡單”這點的表現為整數時間,也就是說最小的時間精度是秒,而不是上一種方法中的微秒,不過這對于復雜函數或程序的測試來說沒啥問題,畢竟 30 分鐘和 31 分鐘的性能差距不過 3.22%。
方法如下(第一行是為說明需要導入哪個庫):
#include <time.h> time_t begin = time(NULL); ...需要被測量的代碼 time_t end = time(NULL); int duration = (end - begin);
可以看到比上一種還要簡單。
但是對于一些小型的測試來說,這個方法又不太行,因為整數帶來的誤差太大了,比如說 0.6 秒是 1.8 秒性能的三倍,但是在整數上只為 2 倍甚至是 1 倍(為什么有這個“甚至”等會演示可以看到),所以還是需要一個更精確時間測量方法,這個方法不光要適應并行計算,還要有一定的精度。
clock_gettime()
clock_gettime()可以完美的符合要求,但是使用上有點復雜。
clock_gettime()是我從文檔的下面發(fā)現的。一開始我找到的是gettimeofday(),然后我去看了一下 IEEE 標準的文檔gettimeofday (opengroup.org),發(fā)現在“FUTURE DIRECTIONS(未來方向)”這一欄表示gettimeofday()可能未來會被廢棄;在“APPLICATION USAGE(應用使用)”這一欄表示應用應該使用clock_gettime()而不是gettimeofday。這必須得使用clock_gettime()了。
clock_gettime()
的復雜之處在于太精確了。先來看看使用方法(第一行是為說明需要導入哪個庫):
#include <time.h> struct timespec start; clock_gettime(CLOCK_REALTIME, &start); ...需要被測量的代碼 struct timespec end; clock_gettime(CLOCK_REALTIME, &end); double duration = (double)(end.tv_nsec-start.tv_nsec)/((double) 1e9) + (double)(end.tv_sec-start.tv_sec);
clock_gettime()的參數CLOCK_REALTIME表示系統(tǒng)層面的實時時間;這個地方還可以用CLOCK_MONOTONIC,這個值是從系統(tǒng)啟動開始一直運行的,一直連續(xù)的不跳躍的(除非手動改了),這個要比CLOCK_REALTIME精度小一些,所以更快一些。
可以看到計算運行時間的代碼,也就是時間差的表達式長了很多,是因為clock_gettime()獲取的時間分為兩部分:秒和納秒(在某論壇上有人指出在曾經的 Mac OS X 上這里是微秒,不確定,不過現在也是納秒了)。秒是int很簡單的,但是納秒用的是long int,這就涉及到轉換的問題了。所以就需要分別計算兩個部分,轉換合成。
實際演示(三種方法的對比)
這里展示一段并行計算程序在三種測量時間方法下的對比,各位可以看看差別(可以推測出測試設備是 6C6T 的 CPU 哦):
可以看到有時差別還是挺大的。
以上就是詳解如何在C/C++中測量一個函數或者功能的運行時間的詳細內容,更多關于在C/C++中測量函數運行時間的資料請關注腳本之家其它相關文章!
相關文章
DHCP:解析開發(fā)板上動態(tài)獲取ip的2種實現方法詳解
本篇文章是對開發(fā)板上動態(tài)獲取ip的2種實現方法進行了詳細的分析介紹,需要的朋友參考下2013-05-05通過C++獲取CPU占用率的代碼示例(windows、linux、macOS)
本文介紹了在Windows、Linux和macOS平臺下使用C++獲取CPU占用率的多種方法,包括系統(tǒng)整體CPU占用率和特定進程CPU占用率的計算公式和實現代碼示例,需要的朋友可以參考下2025-03-03