zoukankan      html  css  js  c++  java
  • 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 ",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 ",(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 ",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 ",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;  

    用法

    在进行定时之前,先调用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 ",(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. }  
    可见该函数可用于在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 ",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. }  
    如果编译器不允许直接用RDTSC的话,可以用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31:
    1. inline unsigned long long GetCycleCount()   
    2. {  
    3.     __asm _emit 0x0F   
    4.     __asm _emit 0x31  
    5. }   
    计算时还需要将得到的数字除以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 ",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(" ");  
    53.   
    54.     *t=GetNTime();  
    55.     returnt1;  
    56. }  
    总结:这种方法精确到纳秒,但缺点是非常短时间的计时会不稳定。最近因为项目需要,我也找了一下ARM+Linux平台上可以用的计时方法,后来选择了gettimeofday()。不知道ARM+Linux平台上有没有类似RDTSC的这种指令。
  • 相关阅读:
    005. gitlab安装
    004. github使用
    003. git标签
    TS标红和报错解决(优化项)
    catalog连接数据库与sde权限问题
    博客新生企划
    HDU 7105 Power Sum
    HDU 7131 Nun Heh Heh Aaaaaaaaaaa
    BZOJ 1691 挑剔的美食家
    洛谷 4254 Blue Mary 开公司
  • 原文地址:https://www.cnblogs.com/x_wukong/p/5079425.html
Copyright © 2011-2022 走看看