轉(zhuǎn)自:http://www.cnblogs.com/dwdxdy/p/3214905.html
目前,存在著各種計時函數(shù),一般的處理都是先調(diào)用計時函數(shù),記下當前時間tstart,然后處理一段程序,再調(diào)用計時函數(shù),記下處理后的時間tend,再tend和tstart做差,就可以得到程序的執(zhí)行時間,但是各種計時函數(shù)的精度不一樣.下面對各種計時函數(shù),做些簡單記錄.
方法1,time()獲取當前的系統(tǒng)時間,返回的結(jié)果是一個time_t類型,其實就是一個大整數(shù),其值表示從CUT(Coordinated Universal Time)時間1970年1月1日00:00:00(稱為UNIX系統(tǒng)的Epoch時間)到當前時刻的秒數(shù).
void test1(){ time_t start,stop; start = time(NULL); foo();//dosomething stop = time(NULL); 方法2,clock()函數(shù)返回從“開啟這個程序進程”到“程序中調(diào)用clock()函數(shù)”時之間的CPU時鐘計時單元(clock tick)數(shù),在MSDN中稱之為掛鐘時間(wal-clock)常量CLOCKS_PER_SEC,它用來表示一秒鐘會有多少個時鐘計時單元
void test2(){ double dur; clock_t start,end; start = clock(); foo();//dosomething end = clock(); dur = (double)(end - start); printf("Use Time:%f/n",(dur/CLOCKS_PER_SEC));}方法3,timeGetTime()函數(shù)以毫秒計的系統(tǒng)時間。該時間為從系統(tǒng)開啟算起所經(jīng)過的時間,是windows api
void test3(){ DWord t1,t2; t1 = timeGetTime(); foo();//dosomething t2 = timeGetTime(); printf("Use Time:%f/n",(t2-t1)*1.0/1000);}方法4,QueryPerformanceCounter()這個函數(shù)返回高精確度性能計數(shù)器的值,它可以以微妙為單位計時.但是QueryPerformanceCounter()確切的精確計時的最小單位是與系統(tǒng)有關(guān)的,所以,必須要查詢系統(tǒng)以得到QueryPerformanceCounter()返回的嘀噠聲的頻率.QueryPerformanceFrequency()提供了這個頻率值,返回每秒嘀噠聲的個數(shù).
void test4(){ LARGE_INTEGER t1,t2,tc; QueryPerformanceFrequency(&tc); QueryPerformanceCounter(&t1); foo();//dosomething QueryPerformanceCounter(&t2); printf("Use Time:%f/n",(t2.QuadPart - t1.QuadPart)*1.0/tc.QuadPart);}方法5,GetTickCount返回(retrieve)從操作系統(tǒng)啟動到現(xiàn)在所經(jīng)過(elapsed)的毫秒數(shù),它的返回值是DWORD
void test5(){ DWORD t1,t2; t1 = GetTickCount(); foo();//dosomething t2 = GetTickCount(); printf("Use Time:%f/n",(t2-t1)*1.0/1000);}方法6,RDTSC指令,在Intel Pentium以上級別的CPU中,有一個稱為“時間戳(Time Stamp)”的部件,它以64位無符號整型數(shù)的格式,記錄了自CPU上電以來所經(jīng)過的時鐘周期數(shù)。由于目前的CPU主頻都非常高,因此這個部件可以達到納秒級的計時精度。這個精確性是上述幾種方法所無法比擬的.在Pentium以上的CPU中,提供了一條機器指令RDTSC(Read Time Stamp Counter)來讀取這個時間戳的數(shù)字,并將其保存在EDX:EAX寄存器對中。由于EDX:EAX寄存器對恰好是Win32平臺下C++語言保存函數(shù)返回值的寄存器,所以我們可以把這條指令看成是一個普通的函數(shù)調(diào)用,因為RDTSC不被C++的內(nèi)嵌匯編器直接支持,所以我們要用_emit偽指令直接嵌入該指令的機器碼形式0X0F、0X31
inline unsigned __int64 GetCycleCount(){ __asm { _emit 0x0F; _emit 0x31; }}void test6(){ unsigned long t1,t2; t1 = (unsigned long)GetCycleCount(); foo();//dosomething t2 = (unsigned long)GetCycleCount(); printf("Use Time:%f/n",(t2 - t1)*1.0/FREQUENCY); //FREQUENCY指CPU的頻率}方法7,gettimeofday() linux環(huán)境下的計時函數(shù),int gettimeofday ( struct timeval * tv , struct timezone * tz ),gettimeofday()會把目前的時間有tv所指的結(jié)構(gòu)返回,當?shù)貢r區(qū)的信息則放到tz所指的結(jié)構(gòu)中.
//timeval結(jié)構(gòu)定義為:struct timeval{long tv_sec; /*秒*/long tv_usec; /*微秒*/};//timezone 結(jié)構(gòu)定義為:struct timezone{int tz_minuteswest; /*和Greenwich 時間差了多少分鐘*/int tz_dsttime; /*日光節(jié)約時間的狀態(tài)*/};void test7(){ struct timeval t1,t2; double timeuse; gettimeofday(&t1,NULL); foo(); gettimeofday(&t2,NULL); timeuse = t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec)/1000000.0; printf("Use Time:%f/n",timeuse);}方法8,linux環(huán)境下,用RDTSC指令計時.與方法6是一樣的.只不過在linux實現(xiàn)方式有點差異.
#if defined (__i386__)static __inline__ unsigned long long GetCycleCount(void){ unsigned long long int x; __asm__ volatile("rdtsc":"=A"(x)); return x;}#elif defined (__x86_64__)static __inline__ unsigned long long GetCycleCount(void){ unsigned hi,lo; __asm__ volatile("rdtsc":"=a"(lo),"=d"(hi)); return ((unsigned long long)lo)|(((unsigned long long)hi)<<32);}#endifvoid test8(){ unsigned long t1,t2; t1 = (unsigned long)GetCycleCount(); foo();//dosomething t2 = (unsigned long)GetCycleCount(); printf("Use Time:%f/n",(t2 - t1)*1.0/FREQUENCY); //FREQUENCY CPU的頻率}簡單的比較表格如下
序號 函數(shù) 類型 精度級別 時間 1 time C系統(tǒng)調(diào)用 低 <1s 2 clcok C系統(tǒng)調(diào)用 低 <10ms 3 timeGetTime Windows API 中 <1ms 4 QueryPerformanceCounter Windows API 高 <0.1ms 5 GetTickCount Windows API 中 <1ms 6 RDTSC 指令 高 <0.1ms 7 gettimeofday linux環(huán)境下C系統(tǒng)調(diào)用 高 <0.1ms
總結(jié),方法1,2,7,8可以在linux環(huán)境下執(zhí)行,方法1,2,3,4,5,6可以在windows環(huán)境下執(zhí)行.其中,timeGetTime()和GetTickCount()的返回值類型為DWORD,當統(tǒng)計的毫妙數(shù)過大時,將會使結(jié)果歸0,影響統(tǒng)計結(jié)果. 測試結(jié)果,windows環(huán)境下,主頻為1.6GHz,單位為秒.
1 Use Time:0 2 Use Time:0.390000 3 Use Time:0.388000 4 Use Time:0.394704 5 Use Time:0.407000 6 Use Time:0.398684 linux環(huán)境下,主頻為2.67GHz,單位為秒
1 Use Time:1 2 Use Time:0.290000 7 Use Time:0.288476 8 Use Time:0.297843 由于time()計時函數(shù)的精度比較低,多次運行程序時,將會得到不同的結(jié)果,時而為0,時而為1
foo()函數(shù)如下:
void foo(){ long i; for (i=0;i<100000000;i++) { long a= 0; a = a+1; }}
|
新聞熱點
疑難解答
圖片精選