윈도우즈 컴퓨팅 프로그램 실행 시간

12638 단어
1. 이것은 윈도우즈에서 프로그램의 운행 시간을 계산하는 데 자주 사용하는 함수이다.
DWORD dwStart = GetTickCount();
Test(); // Your program.
DWORD dwEnd = GetTickCount();
DWORD dwTimes = dwEnd - dwStart;

(dwEnd-dwStart) 는 프로그램의 실행 시간입니다. 밀리초 단위로 이 함수는 55ms까지만 정확합니다. tick 1개는 55ms입니다.
2. timeGetTime()은 기본적으로 GetTickCount()와 같지만 정밀도는 더 높습니다.
DWORD dwStart = timeGetTime();
Test(); // Your program
DWORD dwEnd = timeGetTime();
DWORD dwTimes = dwEnd - dwStart;

(dwEnd-dwStart)는 프로그램의 실행 시간입니다. 밀리초 단위로 되돌아오는 값 단위는 ms이지만 전설의 정밀도는 10ms에 불과합니다.
3. clock () 함수로 시스템이 시작된 후 밀리초 단위의 시간을 얻은 다음 CLOCKS 를 나눈다PER_SEC, "초", 표준 c 함수로 바꿀 수 있습니다.clock_t clock ( void );
#include <time.h>
clock_t t = clock();
long sec = t / CLOCKS_PER_SEC;

그는 시계 주기를 기록하는 사람이라 실현이 정확하지 않을 것 같아서 실험 검증이 필요하다.
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
    time_t begin,end;
    begin = clock();
    //        
    end = clock();
    cout << "runtime:   " << double(end - begin) / CLOCKS_PER_SEC << endl;
    return 0;
}

4. 유닉스 시간과 관련된, 표준 라이브러리의 이것들은     1). timegm 함수는 struct tm 구조를timet구조, 시간대 정보 사용하지 않음;
time_t timegm(struct tm *tm);

     2).mktime 사용 시간대 정보
time_t mktime(struct tm *tm);

timelocal 함수는 GNU가 확장한posix 함수 mktime와 비슷하다
time_t timelocal (struct tm *tm);

3). gmtime 함수는 timet구조를structtm구조로 전환하고 시간대 정보를 사용하지 않습니다.
struct tm * gmtime(const time_t *clock);

4).localtime 사용 시간대 정보
struct tm * localtime(const time_t *clock);

5). time 획득 시간,stime 설정 시간
time_t t;
t = time(&t);

6). stime의 매개 변수는 GMT 시간으로 로컬 시간대에 따라 로컬 시간으로 설정해야 한다.
int stime(time_t *tp)

UTC=true는 서머타임을 나타냅니다.파일의 수정 시간 등 정보는 모두 GMT 시간에 저장하고 서로 다른 시스템은 수정 시간을 받은 후에localtime를 통해 로컬 시간으로 전환한다.시간대 설정은 setup으로 설정하는 것을 추천합니다.시간대 설정도/etc/sysconfig/clock의 설정을 바꾸고 ln-fs/usr/share/zoneinfo/xxx/xxx/etc/localtime를 다시 사용할 수 있습니다
time_t는 68년의 범위를 나타낼 수 있다. 즉, mktime는 1970-2038의 범위를 되돌릴 수 있는timet 시스템에 시간이 있는지 확인하세요t64, 더 큰 시간 범위를 나타낼 수 있습니다.
5. 윈도 안에 있는 것들은 다르다
Ctime MFC류, 마치 타임을h가 클래스를 봉하여 확장하지 않았습니다
CTime t = GetCurrentTime();

SYSTEMTIME 구조에는 밀리초 정보가 포함되어 있습니다.
typedef struct _SYSTEMTIME {
    WORD wYear;
    WORD wMonth;
    WORD wDayOfWeek;
    WORD wDay;
    WORD wHour;
    WORD wMinute;
    WORD wSecond;
    WORD wMilliseconds;
}SYSTEMTIME, *PSYSTEMTIME;

SYSTEMTIME t1;
GetSystemTime(&t1)
CTime curTime(t1);
WORD ms = t1.wMilliseconds;

SYSTEMTIME sysTm;
::GetLocalTime(&sysTm);

시간h중의strtime ()//윈도우즈에서만 사용
char t[11];
_strtime(t);
puts(t);

6. 다음은 어셈블리로 정확하게 시간을 재는 방법------------------------------------------------------------------------------------------------------어떻게 프로그램이나 코드가 실행되는 시간을 얻습니까?너는 전문적인 프로그램 테스트 도구가 있다고 말할 수 있지만, 확실히 말하지만, 너도 프로그램에 어셈블리 코드를 삽입해서 실현할 수 있다.Pentium의 명령 시스템에서 CPU 내부 64비트 카운터의 값을 얻을 수 있는 명령이 있습니다. 우리는 코드를 통해 두 번 이 카운터의 값을 가져와 프로그램이나 코드가 실행하는 시계 주기수를 얻을 수 있으며, 더 나아가 당신의 cpu의 주파수를 통해 시계 주기의 시간을 계산하여 프로그램이 실행하는 정확한 시간을 계산할 수 있습니다.우리는 TDSIC를 명령함으로써 cpu 내부 계수기의 값을 얻고 TDSIC의 반환 값은 EDX:EAX에 넣는다. 그 중에서 EDX에는 64개의 레지스터 중 32개의 값이 저장되고 EAX에는 32개의 값이 저장된다.다음은 구현된 코드를 살펴보겠습니다.
//                
#include<iostream>
using namespace std;

void GetClockNumber (long high, long low);
void GetRunTime();

int main()
{  
    long HighStart,LowStart,HighEnd,LowEnd;
    long numhigh,numlow;
    //         cpu       
    __asm      
    {
        RDTSC
        mov HighStart, edx
        mov LowStart, eax
    }
    for(int i= 0; i<100000; i++ )
    {
       for(int i= 0; i<100000; i++ )
       {
       }
    }
    //       cpu       ,     
    __asm
    {
        RDTSC
        mov HighEnd, edx
        Mov LowEnd, eax
        //          
        sub eax, LowStart
        cmp eax, 0    ;    32       ,               
        jg   L1
        neg   eax
        jmp   L2
      L1: mov numlow, eax
      L2: sbb edx, HighStart
        mov numhigh, edx
    }
    //             64       
    //   32   32   64      ,      32 
    __int64 timer =(numhigh<<32) + numlow;
     //             
     //   1.1Gcpu  ,          1.1      ,       cpu    1G   ^_^
    cout<< (double) (timer /1.1/1000000000) << endl;
    return 0;
}

이렇게 하면 간단한 어셈블리 명령을 통해 프로그램이나 코드의 대략적인 시간을 얻을 수 있지만 정확한 시간을 얻을 수 없다. 왜냐하면 중간의 순환을 없애도 프로그램은 실행 시간이 있기 때문이다. 왜냐하면 처음으로 계수기의 값을 얻은 후에 두 개의 어셈블리 명령이 있기 때문이다. mov HighStart, edx mov LowStart, eax 이 두 명령도 당연히 실행 시간이 있기 때문이다.물론 너는 이 두 지령의 운행 시간을 줄일 수 있다. (1.1G의 기기에서 3e-8s) 그러면 더욱 정확해질 것이다.만약 당신이 프로그램의 운행 시간을 정확하게 알고 싶다면, 전문적인 테스트 소프트웨어가 틀림없이 더 좋을 것이다. 그러나 일반적으로 전문적으로 요구하지 않는 프로그램을 얻을 필요는 없을 것 같다.그러나 DIY 하나를 만들 수 있는 것도 괜찮다. 있든 없든 적어도 VC++에 어셈블리 코드를 어떻게 삽입하고 32비트의 레지스터를 어떻게 사용하는지 배울 수 있다. 사실은 16비트의 레지스터와 같이 사용한다. 앞으로 64비트도 마찬가지일 것이다. 단지 위치가 다를 뿐이다.
//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에서 HightTimer라는 이름의 대화 상자 프로젝트를 MFC로 만듭니다.대화상자 패널에서 컨트롤의 배치는 다음과 같습니다. 정적 텍스트 상자 두 개, 편집 상자 두 개, 단추 두 개가 있습니다.위쪽과 아래쪽 편집 상자의 ID는 각각 IDC 입니다.E_TEST 및 IDCE_ACT UAL, MFC ClassWizard를 통해 추가된 구성원 변수도 각각 DWORD mdwTest 및 DWORD mdwAct.종료 버튼의 ID는 IDOK이고 테스트 시작은 버튼 ID로 IDCB_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);   //          
}
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와QueryPerformanceCounter 두 함수를 사용하면 실제 수요에 따라 자신의 시간 지연 코드를 쓸 수 있다. 
시간을 계산하는 클래스
//   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;  
}

좋은 웹페이지 즐겨찾기