加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

C语言精确计时方法

(2013-08-29 11:43:20)
标签:

c语言

精确计时

it

1. QueryPerformanceFrequency用法

 

精确获取时间:

QueryPerformanceFrequency() - 基本介绍

类型:Win32API

原型:BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);

作用:返回硬件支持的高精度计数器的频率。

返回值:非零,硬件支持高精度计数器;零,硬件不支持,读取失败。

QueryPerformanceFrequency() - 技术特点

WIN9X使用的高精度定时器:QueryPerformanceFrequency()QueryPerformanceCounter(),要求计算机从硬件上支持高精度定时器。需包含windows.h头文件。

函数的原形是:

BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);

BOOL QueryPerformanceCounter (LARGE_INTEGER *lpCount);

数据类型LARGEINTEGER既可以是一个作为8字节长的整数,也可以是作为两个4字节长的整数的联合结构,其具体用法根据编译器是否支持64位而定。该类型的定义如下:

typeef union _ LARGE_INTEGER

{

struct

{

DWORD LowPart;

LONG HighPart;

};

LONGLONG QuadPart;

} LARGE_INTEGER;

在定时前应该先调用QueryPerformanceFrequency()函数获得机器内部计时器的时钟频率。接着在需要严格计时的事件发生前和发生之后分别调用QueryPerformanceCounter(),利用两次获得的计数之差和时钟频率,就可以计算出事件经历的精确时间。

测试Sleep的精确时间:

#include 

#include 

void main()

{

     LARGE_INTEGER nFreq;

     LARGE_INTEGER nBeginTime;

     LARGE_INTEGER nEndTime;

     double time;

 

     QueryPerformanceFrequency(&nFreq);

     QueryPerformanceCounter(&nBeginTime); 

 

     Sleep(1000);

 

     QueryPerformanceCounter(&nEndTime);

     time=(double)(nEndTime.QuadPart-nBeginTime.QuadPart)/(double)nFreq.QuadPart;

 

     printf("%f\n",time);

     Sleep(1000);

system("Pause");

}

结果为

0.999982

1.000088

1.000200

等,所以Sleep的精度还是比较低的。

源地址:http://www.cppblog.com/deane/articles/113151.html

 

2. rdtsc 汇编

static inline unsigned __int64 GetCycleCount()
{
unsigned int timehi, timelo;

__asm
{
rdtsc
mov timehi, edx;
mov timelo, eax;
}

return ((unsigned __int64)timehi << 32) + (unsigned __int64)timelo;
}
rdtsc这个指令是得到CPU自启动以后的运行周期,
在586以上的CPU上有这个指令将放回的数值,
高位返回到edx,
低位放回到eax,
可以用做随机数的种子可以在一段指令的前后调用rdtsc,计算运行这段指令的时间,
不过这个指令在超线程和多核CPU上用来计算时间不是很准确了。
3. 测试实例(运行环境:VS2012,Win7,i3,2.53GHz)
#include "stdio.h"
#include "windows.h"
static inline unsigned __int64 GetCycleCount()
{
 unsigned int timehi, timelo;
 __asm
 {
  rdtsc
  mov timehi, edx;
  mov timelo, eax;
 }
 return ((unsigned __int64)timehi << 32) + (unsigned __int64)timelo;
}
int _tmain(int argc, _TCHAR* argv[])
{
 //PSO参数定义
 float v_in=(float)0.45;
 float x_in=(float)1.32;
 float pbest=(float)0.68;
 float gbest=(float)0.03;
 float w=(float)0.7;
 float c1=(float)2.0;
 float c2=(float)2.0;
 float r1=(float)0.35;
 float r2=(float)0.72;
 float v_out=(float)0.0;
 //计时程序参数定义
    LARGE_INTEGER nFreq;
    LARGE_INTEGER nBeginTime;
    LARGE_INTEGER nEndTime;
    double time;
 printf("CPU Times:\n");
 for(int i=0;i<10;i++)
 {
  QueryPerformanceFrequency(&nFreq);
  QueryPerformanceCounter(&nBeginTime);
  v_out=w*v_in+c1*r1*(pbest-x_in)+c2*r2*(gbest-x_in);
  QueryPerformanceCounter(&nEndTime);
  time=(double)1000000000.0*(nEndTime.QuadPart-nBeginTime.QuadPart)/(double)nFreq.QuadPart;
  printf("%f:\t%f\n",v_out,time);
 }
 printf("CPU Cycles:\n");
 for(int i=0;i<10;i++)
 {
  unsigned __int64 nBeginCycle = GetCycleCount();
  v_out=w*v_in+c1*r1*(pbest-x_in)+c2*r2*(gbest-x_in);
  unsigned __int64 nEndCycle = GetCycleCount();
  unsigned __int64 nCycle = nEndCycle - nBeginCycle;
  time=(double)nCycle/2.53;
  printf("%f:\t%f\n",v_out,time);
 }
 return 0;
}

Result:
CPU Times:
-1.990600:      405.210849
-1.990600:      810.421699
-1.990600:      405.210849
-1.990600:      405.210849
-1.990600:      405.210849
-1.990600:      405.210849
-1.990600:      405.210849
-1.990600:      405.210849
-1.990600:      405.210849
-1.990600:      810.421699
CPU Cycles:
-1.990600:      524.901186
-1.990600:      447.430830
-1.990600:      412.648221
-1.990600:      409.486166
-1.990600:      406.324111
-1.990600:      422.134387
-1.990600:      411.067194
-1.990600:      411.067194
-1.990600:      540.711462
-1.990600:      493.280632
请按任意键继续. . .

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有