您的位置:首页 > 编程语言 > C语言/C++

C++高精度实现计算程序运行时间

2010-08-29 15:49 591 查看
//C++高精度实现计算程序运行时间
#include<iostream>
#include<windows.h>
usingnamespace std;

void Test()//测试程序
{
for(int i=0; i<1000; i++)
{
for(int j=0; j<100; j++)
{
printf("%d,%d/n",i,j);
}
}
}

int main(void)
{
LARGE_INTEGER BegainTime ;
LARGE_INTEGER EndTime ;
LARGE_INTEGER Frequency ;
QueryPerformanceFrequency(&Frequency);
QueryPerformanceCounter(&BegainTime) ;

//要测试的代码放在这里
Test();

QueryPerformanceCounter(&EndTime);

//输出运行时间(单位:s)
cout << "运行时间(单位:s):" <<(double)( EndTime.QuadPart - BegainTime.QuadPart )/ Frequency.QuadPart <<endl;

system("pause") ;
return 0 ;
}

附vc计算高精度时间差

面线框里的代码便可实现计算精度达到微秒级的时间差:

------------------------------------------------------------------------------------

LARGE_INTEGER litmp;
LONGLONG QPart1,Qpart2;
double dfMinus,dfFreq,dfTime;

//获得计时器的时钟频率
QueryPerformanceFrequency(&litmp);
dfFreq = (double)litmp.QuadPart;
QueryPerformanceCounter(&litmp);
Qpart1 = litmp.QuadPart; //开始计时

Block1(); //工作模块函数等,根据自己需要添加。

QueryPerformanceCounter(&litmp);
Qpart2 = litmp.QuadPart; //终止计时
dfMinus = (double)(QPart2 - QPart1);//计算计数器值
dfTime = dfMinus / dfFreq;//获得对应时间,单位为秒你可以乘精确到毫秒级(us)

--------------------------------------------------------------------------------------

在一些计算机硬件系统中,包含有高精度运行计数器(high-resolution performance
counter),利用它可以获得高精度定时间隔,其精度与CPU的时钟频率有关。

1、首先调用QueryPerformanceFrequency函数取得高精度运行计数器的频率f。单位是每秒多少次(n/s),此数
一般很大。
2、在需要定时的代码的两端分别调用QueryPerformanceCounter以取得高精度运行计数器的数值n1,n2。两次数
值的差值通过f换算成时间间隔,t=(n2-n1)/f。

下面举一个例子来演示这种方法的使用及它的精确度。

在VC 6.0 下用MFC建立一个对话框工程,取名为HightTimer.在对话框面板中控件的布局如下图:

其中包含两个静态文本框,两个编辑框和两个按纽。上面和下面位置的编辑框的ID分别为IDC_E_TEST和IDC_E_ACT
UAL,通过MFC ClassWizard添加的成员变量也分别对应为DWORD m_dwTest和DWORD m_dwAct.
“退出”按纽的ID为IDOK,“开始测试”按纽ID为IDC_B_TEST,用MFC
ClassWizard添加此按纽的单击消息处理函数如下:

void CHightTimerDlg::OnBTest()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE); //取输入的测试时间值到与编辑框相关联的成员变量m_dwTest中

LARGE_INTEGER frequence;//LARGE_INTEGER是一个联合,其中LOWPART为低位,HIGHPART为高位,
//两者构成一个结构,而QuadPart是其中的位符号整数,为LongLong类型
if(!QueryPerformanceFrequency( &frequence)) //取高精度运行计数器的频率,若硬件不支持则返回FALSE
MessageBox("Your computer hardware doesn't support the high-resolution performance counter",
"Not Support", MB_ICONEXCLAMATION | MB_OK);

LARGE_INTEGER test, ret;
test.QuadPart = frequence.QuadPart * m_dwTest / 1000000;
//通过频率换算微秒数到对应的数量(与CPU时钟有关),秒=1000000微秒
//test 中存储着m_dwTest毫秒所需的次数
ret = MySleep( test ); //调用此函数开始延时,返回实际花销的数量

m_dwAct = (DWORD)(1000000 * ret.QuadPart / frequence.QuadPart ); //换算到微秒数

UpdateData(FALSE); //显示到对话框面板
}

其中上面调用的MySleep函数如下:

LARGE_INTEGER CHightTimerDlg::MySleep(LARGE_INTEGER Interval)
///////////////////////////////////////////////////////////////////////////////////////////////////
//////////
// 功能:执行实际的延时功能
// 参数:Interval 参数为需要执行的延时与时间有关的数量
// 返回值:返回此函数执行后实际所用的时间有关的数量
///////////////////////////////////////////////////////////////////////////////////////////////////
////////
{
LARGE_INTEGER privious, current, Elapse;

QueryPerformanceCounter( &privious );
current = privious;

while( current.QuadPart - privious.QuadPart < Interval.QuadPart )
QueryPerformanceCounter( ¤t );

Elapse.QuadPart = current.QuadPart - privious.QuadPart;

return Elapse;
}
注:别忘了在头文件中为此函数添加函数声明。

至此,可以编译和执行此工程了,当测试时间超过微秒时,准确度已经非常高了,此时机器执行本身延时函数代码的时间对需要延时的时间影响很小了。

上面的函数由于演示测试的需要,没有在函数级封装,下面给出的函数基本上可以以全局函数的形式照搬到别的
程序中。

BOOL MySleep(DWORD dwInterval)
///////////////////////////////////////////////////////////////////////////////////////////////////
//////////
// 功能:执行微秒级的延时功能
// 参数:Interval 参数为需要的延时数(单位:微秒)
// 返回值:若计算机硬件不支持此功能,返回FALSE,若函数执行成功,返回TRUE
///////////////////////////////////////////////////////////////////////////////////////////////////
////////
{
BOOL bNormal = TRUE;
LARGE_INTEGER frequence, privious, current, interval;

if(!QueryPerformanceFrequency( &frequence))
{
::MessageBox(NULL, "Your computer hardware doesn't support the high-resolution performance
counter",
"Not Support", MB_ICONEXCLAMATION | MB_OK); //或其它的提示信息
return FALSE;
}

interval.QuadPart = frequence.QuadPart * dwInterval / 1000000;

bNormal = bNormal && QueryPerformanceCounter( &privious );
current = privious;

while( current.QuadPart - privious.QuadPart < interval.QuadPart )
bNormal = bNormal && QueryPerformanceCounter( ¤t );

return bNormal;
}

需要指出的是,由于在此函数中的代码很多,机器在执行这些代码所花费的时间也很长,所以在需要几个微秒的
延时时,会影响精度。实际上,读者在熟悉这种方法后,只要使用QueryPerformanceFrequency和QueryPerforman
ceCounter这两个函数就能按实际需要写出自己的延时代码了。

给你个类吧,我在用呢

// Elapsed.h: interface for the CElapsed class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_ELAPSED_H__4A992E21_8B47_11D6_B1B2_FFFCE130B010__INCLUDED_)
#define AFX_ELAPSED_H__4A992E21_8B47_11D6_B1B2_FFFCE130B010__INCLUDED_

#if _MSC_VER > 1000
#pragmaonce
#endif// _MSC_VER > 1000

class CElapsed
{
private:
int Initialized;
__int64 Frequency;
__int64 BeginTime;

public:
BOOL Avaliable();
double End();
BOOL Begin();
CElapsed();
virtual ~CElapsed();
};

#endif// !defined(AFX_ELAPSED_H__4A992E21_8B47_11D6_B1B2_FFFCE130B010__INCLUDED_)

// Elapsed.cpp: implementation of the CElapsed class.
//
//////////////////////////////////////////////////////////////////////

#include"stdafx.h"
//#include "myimage.h"
#include"Elapsed.h"

#ifdef _DEBUG
#undef THIS_FILE
staticchar THIS_FILE[]=__FILE__;
#definenew DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CElapsed::CElapsed()
{
Initialized=QueryPerformanceFrequency((LARGE_INTEGER *)&Frequency);
}

CElapsed::~CElapsed()
{

}

BOOL CElapsed::Begin()
{
if(!Initialized)
return 0;
return QueryPerformanceCounter((LARGE_INTEGER *)&BeginTime);
}

double CElapsed::End()
{
if(!Initialized)
return 0;
__int64 endtime;
QueryPerformanceCounter((LARGE_INTEGER *)&endtime);

__int64 elapsed=endtime-BeginTime;

return (double)elapsed/(double)Frequency;
}
BOOL CElapsed::Avaliable()
{
return Initialized;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: