欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C语言中常用计时方法总结

程序员文章站 2024-02-26 21:18:16
...

转载 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的这种指令。

  • 本文已收录于以下专栏:
C语言中常用计时方法总结
C语言中常用计时方法总结

c语言中如何添加计时函数,统计程序执行的时间

这里举一个例子,行优先和列优先遍历二维数组的程序执行时间比较,这里需要调用 time.h 编译环境为vs2013#define M 10000000#define N 10short a[M][...

C语言中的计时方法:time

在Linux中用C语言计时可以用很多方法。  1. 可用使用C语言库自带的clock()进行计时。如:  #include   #include   using namespa...
  • C语言中常用计时方法总结
  • DC_Neo
  • 2012年09月14日 12:50
  • 1786
C语言中常用计时方法总结C语言中常用计时方法总结

一个普通程序员的内心独白....躺枪!躺枪!

我,一个普普通通程序员,没有过人的天赋,没有超乎寻常的好运,该如何逆袭走上人生巅峰?
C语言中常用计时方法总结

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语言给函数计时

C/C++中的计时函数是clock(),而与其相关的数据类型是clock_t。在MSDN中,查得对clock函数定义如下:clock_t clock( void );这个函数返回从“开启这个程序进程”...
  • C语言中常用计时方法总结
  • 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语言中常用计时方法总结
  • onezeros
  • 2009年09月16日 18:32
  • 20714

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/,下载下来安装就可以了。以下...

 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的这种指令。

相关标签: C语言计时函数