プログラムの実行時間を正確に計算する方法-正確な取得時間(QueryPerformance Counter)

4976 ワード

LARGE_INTEGER tima,timb; 
QueryPerformanceCounter(&tima);
Windows Server 2003およびWindowsXPでQueryPerformance Counter関数を使用するプログラムは、適切に実行されない場合があります.
QueryPerformanceCounter実行時間を正確に計算するQueryPerformanceCounter実行時間を正確に計算する//このプログラムは、QueryPerformanceCounterを使用して実行時間//コードを正確に計算する方法を示しています
 
  • LARGE_INTEGER m_liPerfFreq={0};

  •  //1秒あたりのCPU数を取得 Performance Tick 
  •  QueryPerformanceFrequency(&m_liPerfFreq); 

  •  
  •  LARGE_INTEGER m_liPerfStart={0};

  •  QueryPerformanceCounter(&m_liPerfStart);
  •  

  •  for(int i=0; i< 100; i++)
  •   cout << i << endl;

  •  LARGE_INTEGER liPerfNow={0};

  •  // 計算CPUが現在まで実行する時間
  •  QueryPerformanceCounter(&liPerfNow);

  •  int time=( ((liPerfNow.QuadPart - m_liPerfStart.QuadPart) * 1000)/m_liPerfFreq.QuadPart);

  •  char buffer[100];

  •  sprintf(buffer,「実行時間」 %d millisecond ",time);

  •  cout<


  • QueryPerformanceCounter()この関数は、微妙な単位で計時できる高精度性能カウンタの値を返します.しかしQueryPerformanceCounter()の正確な正確な計時の最小単位はシステムに関係しているので、QueryPerformanceCounter()が返すブーブーという音の周波数を得るためにシステムを問い合わせる必要があります.QueryPerformanceFrequency()この周波数値が与えられ、1秒あたりのブータ音の個数が返される.正確な時間を算出するのは、1回目のQueryPerformanceCounter()呼び出しからの仮定で得られたLARGE_INTEGERがnStartCounterであり、一定時間経過後に再びこの関数を呼び出して終了し、nStopCounterが得られるとする.両者の差をQueryPerformanceFrequency()で割るの周波数は開始から終了までの秒数です.計時関数自体に時間がかかるため、わずかな時間のオーバーヘッドを減算します.しかし、一般的にはこのオーバーヘッドを無視します.式は以下の通りです.                             nStopCounter-nStartCounter  ElapsedTime=------------------------------------ - overhead  frequency  double time=(nStopCounter.QuadPart-nStartCounter.QuadPart)/frequency.QuadPart
    この2つの関数はVCが提供するWindows 95以降のバージョンでのみ使用できる正確な時間関数であり、コンピュータにハードウェアから正確なタイマーをサポートするように要求する.QueryPerformanceFrequency()関数とQueryPerformanceCounter()関数の原型は以下の通りである.
           BOOL  QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);
           BOOL  QueryPerformanceCounter(LARGE_INTEGER *lpCount);

    データ型ARGE_INTEGERは、1つの8バイト長の整数であってもよいし、2つの4バイト長の整数の連係構造であってもよい. その具体的な使い方は、コンパイラが64ビットをサポートしているかどうかによって決まります.このタイプの定義は次のとおりです.
           typedef union _LARGE_INTEGER
           {
               struct
               {
                  DWORD LowPart ;// 4     
                  LONG  HighPart;// 4     
               };
               LONGLONG QuadPart ;// 8     
               
            }LARGE_INTEGER ;

    タイミングを行う前にQueryPerformanceFrequency()関数を呼び出してマシン内部タイマのクロック周波数を取得し、 そして厳密なタイミングが必要なイベントが発生する前と発生した後にそれぞれQueryPerformance Counter()関数を呼び出し,2回のカウントの差とクロック周波数を用いてイベント経を算出する. 暦の正確な時間.次のコードは1 msの正確なタイミングを実現します.
     
  •        LARGE_INTEGER litmp; 

  •        LONGLONG QPart1,QPart2;
  •        double dfMinus, dfFreq, dfTim; 

  •        QueryPerformanceFrequency(&litmp);
  •        dfFreq = (double)litmp.QuadPart;// 取得カウンタのクロック周波数
  •        QueryPerformanceCounter(&litmp);
  •        QPart1 = litmp.QuadPart;// 初期値
  • を取得
           do
  •        {

  •           QueryPerformanceCounter(&litmp);
  •           QPart2 = litmp.QuadPart;//取得中止値
  •           dfMinus = (double)(QPart2-QPart1);
  •           dfTim = dfMinus / dfFreq;// 秒
  • 単位で対応する時間値が得られる.
           }while(dfTim<0.001);
    そのタイミング誤差は1マイクロ秒を超えず、精度はCPUなどの機器構成に関係する.以下のプログラムは関数Sleep(100)の正確な持続時間をテストするために使用される.
     
  •        LARGE_INTEGER litmp; 

  •        LONGLONG QPart1,QPart2;
  •        double dfMinus, dfFreq, dfTim; 

  •        QueryPerformanceFrequency(&litmp);
  •        dfFreq = (double)litmp.QuadPart;// 取得カウンタのクロック周波数
  •        QueryPerformanceCounter(&litmp);
  •        QPart1 = litmp.QuadPart;// 初期値
  • を取得
           Sleep(100);
  •        QueryPerformanceCounter(&litmp);

  •        QPart2 = litmp.QuadPart;//取得中止値
  •        dfMinus = (double)(QPart2-QPart1);

  •        dfTim = dfMinus / dfFreq;// 秒単位で対応する時間値を取得    
    Sleep()関数自体の誤差のため、上記のプログラムは実行するたびに微小な誤差が発生します.以下のコードは1マイクロ秒の正確なタイミングを実現します.
     
  •        LARGE_INTEGER litmp; 

  •        LONGLONG QPart1,QPart2;
  •        double dfMinus, dfFreq, dfTim; 

  •        QueryPerformanceFrequency(&litmp);
  •        dfFreq = (double)litmp.QuadPart;// 取得カウンタのクロック周波数
  •        QueryPerformanceCounter(&litmp);
  •        QPart1 = litmp.QuadPart;// 初期値
  • を取得
           do
  •        {

  •           QueryPerformanceCounter(&litmp);
  •           QPart2 = litmp.QuadPart;//取得中止値
  •           dfMinus = (double)(QPart2-QPart1);
  •           dfTim = dfMinus / dfFreq;// 秒
  • 単位で対応する時間値が得られる.
           }while(dfTim<0.000001);
    そのタイミング誤差は一般に0.5マイクロ秒を超えず,精度はCPUなどの機器配置に関係する.