C++計時

來源:互聯網
上載者:User

標籤:

目前,存在著各種計時函數,一般的處理都是先調用計時函數,記下目前時間tstart,然後處理一段程式,再調用計時函數,記下處理後的時間tend,再tend和tstart做差,就可以得到程式的執行時間,但是各種計時函數的精度不一樣.下面對各種計時函數,做些簡單記錄.

  方法1,time()擷取當前的系統時間,返回的結果是一個time_t類型,其實就是一個大整數,其值表示從CUT(Coordinated Universal Time)時間1970年1月1日00:00:00(稱為UNIX系統的Epoch時間)到當前時刻的秒數.  標頭檔<time.h> 

void test1(){    time_t start,stop;    start = time(NULL);    foo();//dosomething    stop = time(NULL);    printf("Use Time:%ld\n",(stop-start));}

  方法2,clock()函數返回從“開啟這個程式進程”到“程式中調用clock()函數”時之間的CPU時鐘計時單元(clock tick)數,在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()函數以毫秒計的系統時間。該時間為從系統開啟算起所經過的時間,是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()這個函數返回高精確度效能計數器的值,它可以以微妙為單位計時.但是QueryPerformanceCounter()確切的精確計時的最小單位是與系統有關的,所以,必須要查詢系統以得到QueryPerformanceCounter()返回的嘀噠聲的頻率.QueryPerformanceFrequency()提供了這個頻率值,返回每秒嘀噠聲的個數.標頭檔<windows.h>

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)從作業系統啟動到現在所經過(elapsed)的毫秒數,它的傳回值是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位無符號整型數的格式,記錄了自CPU上電以來所經過的刻度數。由於目前的CPU主頻都非常高,因此這個組件可以達到納秒級的計時精度。這個精確性是上述幾種方法所無法比擬的.在Pentium以上的CPU中,提供了一條機器指令RDTSC(Read   Time   Stamp   Counter)來讀取這個時間戳記的數字,並將其儲存在EDX:EAX寄存器對中。由於EDX:EAX寄存器對恰好是Win32平台下C++語言儲存函數傳回值的寄存器,所以我們可以把這條指令看成是一個普通的函數調用,因為RDTSC不被C++的內嵌彙編器直接支援,所以我們要用_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環境下的計時函數,int gettimeofday ( struct timeval * tv , struct timezone * tz ),gettimeofday()會把目前的時間有tv所指的結構返回,當地時區的資訊則放到tz所指的結構中.

//timeval結構定義為:struct timeval{long tv_sec; /*秒*/long tv_usec; /*微秒*/};//timezone 結構定義為:struct timezone{int tz_minuteswest; /*和Greenwich 時間差了多少分鐘*/int tz_dsttime; /*日光節約時間的狀態*/};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環境下,用RDTSC指令計時.與方法6是一樣的.只不過在linux實現方式有點差異.

#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的頻率}

簡單的比較表格如下

序號 函數 類型 精度層級 時間
1 time C系統調用 <1s
2 clcok C系統調用 <10ms
3 timeGetTime Windows API <1ms
4 QueryPerformanceCounter Windows API <0.1ms
5 GetTickCount Windows API <1ms
6 RDTSC 指令 <0.1ms
7 gettimeofday  linux環境下C系統調用 <0.1ms


  總結,方法1,2,7,8可以在linux環境下執行,方法1,2,3,4,5,6可以在windows環境下執行.其中,timeGetTime()和GetTickCount()的傳回值類型為DWORD,當統計的毫妙數過大時,將會使結果歸0,影響統計結果.
        測試結果,windows環境下,主頻為1.6GHz,單位為秒.

1 Use Time:02 Use Time:0.3900003 Use Time:0.3880004 Use Time:0.3947045 Use Time:0.4070006 Use Time:0.398684

  linux環境下,主頻為2.67GHz,單位為秒

1 Use Time:12 Use Time:0.2900007 Use Time:0.2884768 Use Time:0.297843

      由於time()計時函數的精度比較低,多次運行程式時,將會得到不同的結果,時而為0,時而為1

foo()函數如下:

void foo(){    long i;    for (i=0;i<100000000;i++)    {        long a= 0;        a = a+1;    }}

C++計時

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.