【C/C++】計時函數比較

  目前,存在着各類計時函數,通常的處理都是先調用計時函數,記下當前時間tstart,而後處理一段程序,再調用計時函數,記下處理後的時間tend,再tend和tstart作差,就能夠獲得程序的執行時間,可是各類計時函數的精度不同.下面對各類計時函數,作些簡單記錄.html

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

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)windows

常量CLOCKS_PER_SEC,它用來表示一秒鐘會有多少個時鐘計時單元api

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()提供了這個頻率值,返回每秒嘀噠聲的個數.性能

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、0X31spa

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實現方式有點差別.code

#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);
}
#endif

void 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: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環境下,主頻爲2.67GHz,單位爲秒

1 Use Time:1
2 Use Time:0.290000
7 Use Time:0.288476
8 Use Time:0.297843

      因爲time()計時函數的精度比較低,屢次運行程序時,將會獲得不一樣的結果,時而爲0,時而爲1

foo()函數以下:

void foo()
{
    long i;
    for (i=0;i<100000000;i++)
    {
        long a= 0;
        a = a+1;
    }
}
相關文章
相關標籤/搜索