//C++高精度實現計算程序運行時間
#include <iostream>
#include <windows.h>
using namespace 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;//獲得對應時間,單位為秒 你可以乘1000000精確到毫秒級(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為低32位,HIGHPART為高32位,
//兩者構成一個結構,而QuadPart是其中的64位符號整數,為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時鍾有關),1秒=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;
}
注:別忘了在頭文件中為此函數添加函數聲明。
至此,可以編譯和執行此工程了,當測試時間超過3微秒時,准確度已經非常高了,此時機器執行本身延時函數代碼的時間對需要延時的時間影響很小了。
上面的函數由於演示測試的需要,沒有在函數級封裝,下面給出的函數基本上可以以全局函數的形式照搬到別的
程序中。
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
#pragma once
#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
static char THIS_FILE[]=__FILE__;
#define new 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;
}