C語言中常用計時方法總結

轉載 http://blog.csdn.net/fz_ywj/article/details/8109368

 C語言中常用計時方法總結

1. time()

頭文件:time.h

函數原型:time_t time(time_t * timer)

功能:返回以格林尼治時間(GMT)爲標準,從1970年1月1日00:00:00到現在的此時此刻所經過的秒數。

用time()函數結合其他函數(如:localtime、gmtime、asctime、ctime)可以獲得當前系統時間或是標準時間。

用difftime函數可以計算兩個time_t類型的時間的差值,可以用於計時。用difftime(t2,t1)要比t2-t1更準確,因爲C標準中並沒有規定time_t的單位一定是秒,而difftime會根據機器進行轉換,更可靠。

用法

  1. time_t start,end;  
  2. start =time(NULL);//or time(&start);  
  3. //…calculating…  
  4. end =time(NULL);  
  5. printf("time=%d\n",difftime(end,start));  
time_t start,end;
start =time(NULL);//or time(&start);
//…calculating…
end =time(NULL);
printf("time=%d\n",difftime(end,start));
總結:C標準庫中的函數,可移植性最好,性能也很穩定,但精度太低,只能精確到秒,對於一般的事件計時還算夠用,而對運算時間的計時就明顯不夠用了。

2. clock()

頭文件:time.h

函數原型:clock_t clock(void);

功能:該函數返回值是硬件滴答數,要換算成秒,需要除以CLK_TCK或者 CLK_TCKCLOCKS_PER_SEC。比如,在VC++6.0下,這兩個量的值都是1000。

用法

  1. clock_t start,end;  
  2. start = clock();  
  3. //…calculating…  
  4. end = clock();  
  5. printf("time=%f\n",(double)end-start)/CLK_TCK);  
clock_t start,end;
start = clock();
//…calculating…
end = clock();
printf("time=%f\n",(double)end-start)/CLK_TCK);
總結:可以精確到毫秒,適合一般場合的使用。

3. timeGetTime()

WIN32API

頭文件:Mmsystem.h  引用庫: Winmm.lib

函數原型:DWORD timeGetTime(VOID);

功能:返回系統時間,以毫秒爲單位。系統時間是從系統啓動到調用函數時所經過的毫秒數。注意,這個值是32位的,會在0到2^32之間循環,約49.71天。

用法

  1. DWORDstart,end;  
  2. start= timeGetTime();  
  3. //…calculating…  
  4. end= timeGetTime();  
  5. printf("time=%d\n",end-start);  
DWORDstart,end;
start= timeGetTime();
//…calculating…
end= timeGetTime();
printf("time=%d\n",end-start);
總結:該函數的時間精度是五毫秒或更大一些,這取決於機器的性能。可用timeBeginPeriod和timeEndPeriod函數提高timeGetTime函數的精度。如果使用了,連續調用timeGetTime函數,一系列返回值的差異由timeBeginPeriod和timeEndPeriod決定。

4. GetTickCount()

WIN32API

頭文件:windows.h

函數原型:DWORD WINAPI GetTickCount(void);

功能:返回自設備啓動後的毫秒數(不含系統暫停時間)。

用法

  1. DWORDstart,end;  
  2. start= GetTickCount();  
  3. //…calculating…  
  4. end= GetTickCount();  
  5. printf("time=%d\n",end-start);  
DWORDstart,end;
start= GetTickCount();
//…calculating…
end= GetTickCount();
printf("time=%d\n",end-start);
總結:精確到毫秒。對於一般的實時控制,使用GetTickCount()函數就可以滿足精度要求。

5. QueryPerformanceCounter()、QueryPerformanceFrequency()

WIN32API

頭文件:windows.h

函數原型:BOOLQueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);

          BOOLQueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);

功能:前者獲得的是CPU從開機以來執行的時鐘週期數。後者用於獲得你的機器一秒鐘執行多少次,就是你的時鐘週期。

補充:LARGE_INTEGER既可以是一個8字節長的整型數,也可以是兩個4字節長的整型數的聯合結構, 其具體用法根據編譯器是否支持64位而定:

  1. typedef union_LARGE_INTEGER  
  2. {  
  3.     struct  
  4.     {  
  5.         DWORD LowPart ;  
  6.         LONG HighPart;  
  7.     };  
  8.     LONGLONG QuadPart ;  
  9. }LARGE_INTEGER;  
typedef union_LARGE_INTEGER
{
    struct
    {
        DWORD LowPart ;
        LONG HighPart;
    };
    LONGLONG QuadPart ;
}LARGE_INTEGER;

用法

在進行定時之前,先調用QueryPerformanceFrequency()函數獲得機器內部定時器的時鐘頻率,然後在需要嚴格定時的事件發生之前和發生之後分別調用QueryPerformanceCounter()函數,利用兩次獲得的計數之差及時鐘頻率,計算出事件經歷的精確時間。

  1. LARGE_INTEGER  num;  
  2. longlong start,end,freq;  
  3. QueryPerformanceFrequency(&num);  
  4. freq=num.QuadPart;  
  5. QueryPerformanceCounter(&num);   
  6. start= num.QuadPart;   
  7. //…calculating…  
  8. QueryPerformanceCounter(&num);   
  9. end= num.QuadPart;    
  10. printf("time=%d\n",(end-start)*1000/freq);  
LARGE_INTEGER  num;
longlong start,end,freq;
QueryPerformanceFrequency(&num);
freq=num.QuadPart;
QueryPerformanceCounter(&num); 
start= num.QuadPart; 
//…calculating…
QueryPerformanceCounter(&num); 
end= num.QuadPart;  
printf("time=%d\n",(end-start)*1000/freq);
總結:這種方法的定時誤差不超過1微秒,精度與CPU等機器配置有關,一般認爲精度爲透微秒級。在Windows平臺下進行高精度計時的時候可以考慮這種方法。

6. gettimeofday()

Linux C函數。

頭文件:sys/time.h

函數原型:int gettimeofday(struct timeval *tv,struct timezone *tz);

說明:其參數tv是保存獲取時間結果的結構體,參數tz用於保存時區結果(若不使用則傳入NULL即可)。

timeval的定義爲:

  1. struct timeval {  
  2.   long tv_sec; // 秒數  
  3.   long tv_usec; //微秒數  
  4. }  
struct timeval {
  long tv_sec; // 秒數
  long tv_usec; //微秒數
}
可見該函數可用於在linux中獲得微秒精度的時間。

用法

  1. struct timeval start,end;  
  2. gettimeofday(&start, NULL );  
  3. //…calculating…  
  4. gettimeofday(&end, NULL );  
  5. long timeuse =1000000 * ( end.tv_sec - start.tv_sec ) + end.tv_usec - start.tv_usec;  
  6. printf("time=%f\n",timeuse /1000000.0);  
struct timeval start,end;
gettimeofday(&start, NULL );
//…calculating…
gettimeofday(&end, NULL );
long timeuse =1000000 * ( end.tv_sec - start.tv_sec ) + end.tv_usec - start.tv_usec;
printf("time=%f\n",timeuse /1000000.0);
總結:使用這種方式計時,精度可達微秒。經驗證,在arm+linux的環境下此函數仍可使用。推薦。

7. RDTSC - 讀取時間標籤計數器

X86架構CPU彙編指令。

操作碼:0F 31 指令:RDTSC

功能:將時間標籤計數器讀入 EDX:EAX寄存器中。

說明:在Pentium以上的CPU中,提供了一條機器指令RDTSC來讀取這個時間戳的數字,並將其保存在EDX:EAX寄存器對中。由於EDX:EAX寄存器對恰好是Win32平臺下C++語言保存函數返回值的寄存器,所以我們可以把這條指令看成是一個普通的函數調用:

  1. inline unsigned long longGetCycleCount()   
  2. {   
  3.     __asm RDTSC   
  4. }  
inline unsigned long longGetCycleCount() 
{ 
    __asm RDTSC 
}
如果編譯器不允許直接用RDTSC的話,可以用_emit僞指令直接嵌入該指令的機器碼形式0X0F、0X31:

  1. inline unsigned long long GetCycleCount()   
  2. {  
  3.     __asm _emit 0x0F   
  4.     __asm _emit 0x31  
  5. }   
inline unsigned long long GetCycleCount() 
{
    __asm _emit 0x0F 
    __asm _emit 0x31
} 
計算時還需要將得到的數字除以CPU的主頻(單位GHZ),就能得到納秒級的時間了。暫時我還沒找到好的獲得機器主頻的方法,Windows平臺下可以考慮用QueryPerformanceFrequency()函數,但這樣一來就沒辦法在Linux下使用此方法。後來我考慮配合sleep函數,獲取1秒中的機器週期數的方法來得到CPU主頻。如果哪位有更好的方法,還請多多請教。

  1. #ifdef WIN32  
  2. #include <windows.h>  
  3. #else  
  4. #include <sys/unistd.h>  
  5. #endif  
  6. inline unsigned long long GetNTime()  
  7. {  
  8.     __asm("RDTSC");  
  9. }  
  10.   
  11. static double hz=0.0;  
  12.   
  13. void init_timer()  
  14. {  
  15.     longlong t1=GetNTime();  
  16. #ifdef WIN32  
  17.     Sleep(1000);  
  18. #else  
  19.     sleep(1);  
  20. #endif  
  21.     longlong t=GetNTime()-t1;  
  22.     hz=(double)t/1000000000;  
  23.     printf("hz=%fGhz\n",hz);  
  24. }  
  25.   
  26. long long u_timer(long long *t,int mode)  
  27. {  
  28.     if(hz<0.001)  
  29.         init_timer();  
  30.     if(!mode)  
  31.     {  
  32.         *t=GetNTime();  
  33.         return0;  
  34.     }  
  35.   
  36.     longlong t1=GetNTime()-*t;  
  37.     t1/=hz;  
  38.     longlong ns=t1%1000;  
  39.     longlong us=(t1/1000)%1000;  
  40.     longlong ms=(t1/1000000)%1000;  
  41.     longlong s=t1/1000000000;  
  42.   
  43.     printf("time=");  
  44.     if(s!=0)  
  45.         printf("%llds",s);  
  46.     if(ms!=0)  
  47.         printf("%lldms",ms);  
  48.     if(us!=0)  
  49.         printf("%lldus",us);  
  50.     if(ns!=0)  
  51.         printf("%lldns",ns);  
  52.     printf("\n");  
  53.   
  54.     *t=GetNTime();  
  55.     returnt1;  
  56. }  
#ifdef WIN32
#include <windows.h>
#else
#include <sys/unistd.h>
#endif
inline unsigned long long GetNTime()
{
    __asm("RDTSC");
}

static double hz=0.0;

void init_timer()
{
    longlong t1=GetNTime();
#ifdef WIN32
    Sleep(1000);
#else
    sleep(1);
#endif
    longlong t=GetNTime()-t1;
    hz=(double)t/1000000000;
    printf("hz=%fGhz\n",hz);
}

long long u_timer(long long *t,int mode)
{
    if(hz<0.001)
        init_timer();
    if(!mode)
    {
        *t=GetNTime();
        return0;
    }

    longlong t1=GetNTime()-*t;
    t1/=hz;
    longlong ns=t1%1000;
    longlong us=(t1/1000)%1000;
    longlong ms=(t1/1000000)%1000;
    longlong s=t1/1000000000;

    printf("time=");
    if(s!=0)
        printf("%llds",s);
    if(ms!=0)
        printf("%lldms",ms);
    if(us!=0)
        printf("%lldus",us);
    if(ns!=0)
        printf("%lldns",ns);
    printf("\n");

    *t=GetNTime();
    returnt1;
}
總結:這種方法精確到納秒,但缺點是非常短時間的計時會不穩定。最近因爲項目需要,我也找了一下ARM+Linux平臺上可以用的計時方法,後來選擇了gettimeofday()。不知道ARM+Linux平臺上有沒有類似RDTSC的這種指令。

  • 本文已收錄於以下專欄:
BjarneCpp
lqxandroid2012

c語言中如何添加計時函數,統計程序執行的時間

這裏舉一個例子,行優先和列優先遍歷二維數組的程序執行時間比較,這裏需要調用 time.h 編譯環境爲vs2013#define M 10000000#define N 10short a[M][...

C語言中的計時方法:time

在Linux中用C語言計時可以用很多方法。  1. 可用使用C語言庫自帶的clock()進行計時。如:  #include   #include   using namespa...
  • DC_Neo
  • DC_Neo
  • 2012年09月14日 12:50
  • 1786

一個普通程序員的內心獨白....躺槍!躺槍!

我,一個普普通通程序員,沒有過人的天賦,沒有超乎尋常的好運,該如何逆襲走上人生巔峯?

Delphi7高級應用開發隨書源碼

  • 2003年04月30日 00:00
  • 676KB
  • 下載

C語言計時器的使用

1.如果是想使用秒級別的技術,可用使用C語言庫time.h>自帶的clock()進行計時。如:   #include iostream>  #include time.h>   u...

C語言中常用計時方法總結

C語言中常用計時方法總結1. time()頭文件:time.h函數原型:time_t time(time_t * timer)功能:返回以格林尼治時間(GMT)爲標準,從1970年1月1...

程序員跨越式成長指南

完成第一次跨越,你會成爲具有一技之長的開發者,月薪可能翻上幾番; 完成第二次跨越,你將成爲擁有局部優勢或行業優勢的專業人士,獲得個人內在價值的有效提升和外在收入的大幅躍遷……

C語言給函數計時

C/C++中的計時函數是clock(),而與其相關的數據類型是clock_t。在MSDN中,查得對clock函數定義如下:clock_t clock( void );這個函數返回從“開啓這個程序進程”...
  • leohxj
  • leohxj
  • 2010年06月29日 20:22
  • 7624

C語言中對程序運行計時

使用time()函數。它在頭文件time.h中具體使用方法如下:time_t a,b;//time_t是表示時間的結構體,你可以在time.h中找到它的原型。a=time(NULL);//...

C語言時間差計算函數clock() 與 time ()用法分析

在很多情況下,爲了評判某個算法,函數的優劣,特別是比較同一個功能的兩個函數的效率高低時,我們經常通過計算耗費時間作爲判斷標準。C語言中有兩個相關的函數用來計算時間差,分別是:time_t time(...

c語言中關於時間的函數

本文從介紹基礎概念入手,探討了在C/C++中對日期和時間操作所用到的數據結構和函數,並對計時、時間的獲取、時間的計算和顯示格式等方面進行了闡述。本文還通過大量的實例向你展示了time.h頭文件中聲明的...

C語言time.h中clock()函數的使用

C語言中求程序執行的時間可以使用clock()函數,_CRTIMP clock_t __cdecl __MINGW_NOTHROW clock (void);(可以把它直接視爲clock_t cloc...

C語言再學習 -- 時間函數

在軟件設計中經常會用到關於時間的處理,用來計算語句、函數的執行時間,這時就需要精確到毫秒甚至是微妙的時間。我們首先來介紹一下,時間單位:時間單位還有:毫秒(ms)、微秒 (μs)、納秒(ns)、皮...

C語言中常用"計時"方法總結

C語言中常用計時方法總結 1. time() 頭文件:time.h 函數原型:time_t time(time_t * timer) 功能:返回以格林尼治時間(GMT)爲標準,從1970年1月...

c ms/毫秒級 計時 及time.h 其它函數詳解

C/C++中的日期和時間 摘要: 本文從介紹基礎概念入手,探討了在C/C++中對日期和時間操作所用到的數據結構和函數,並對計時、時間的獲取、時間的計算和顯示格式等方面進行了闡述。本文還通過大量的實例向...

C\C++中計時、延時函數

C\C++標準庫中提供了兩種計時函數clock()和time()。其用法如下: (1)clock()函數用法void timeConsume(){ double start,stop,...

C/C++ 各種計時函數總結

本文對Windows平臺下常用的計時函數進行總結,包括精度爲秒、毫秒、微秒三種精度的5 種方法。分爲在標準C/C++下的二種time()及clock(),標準C/C++所以使用的time()及cloc...

Windows 各種計時函數總結

本文對Windows平臺下常用的計時函數進行總結,包括精度爲秒、毫秒、微秒三種精度的5種方法。分爲在標準C/C++下的二種time()及clock(),標準C/C++所以使用的time()及clock...

C語言寫的一個鐘錶(很炫哦)

下面是源代碼: #include#include#include#include#define PI 3.1415926#define x 320#define y 240int main(){ in...

C語言寫的一個電子時鐘

C語言的電子時鐘

C語言控制檯的數字時鐘

轉自:http://hi.baidu.com/csxwczj/item/68cd6e0f056da6eaf55ba67f/*TC2.0編譯*/#include #include #inclu...

C語言編寫時鐘程序

使用C語言編寫的時鐘程序,TC下通過,VC需要有graphics包,這個包可以去easyx下載,下載地址爲:http://www.easyx.cn/downloads/,下載下來安裝就可以了。以下...
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章