본문 바로가기

C/C++

스레드 수행 시간 측정 (보다 정밀한)

★ 쓰레드 수행 시간

 

+ 시간 측정을 위해 대부분 GetTickCount64 함수를 이용

  - 이 코드가 올바른 값을 획득하려면 코드 수행중 인터럽트가 수행되지 않았다는 가정 필요

  - 선점형 운영체제에서는 쓰레드가 언제 CPU에 의해 수행될지 알수 없음

  - 현재 코드를 수행 중 다른 작업 수행 가능

  - 따라서, 쓰레드가 소비한 시간 부정확

  - 실제 쓰레드가 부여받은 CPU 시간이 얼마나 되는지 알아내는 함수 필요

  - GetThreadTimes / GetProcessTimes 함수 제공

 


+ TSC (Time Stamp Counter) 이용

  -  비스타 이전에는 clock timer를 기반으로 10에서 15 밀리초 단위로 CPU 시간 계산

  -  비스타 부터 머신이 기동된 후부터 얼마만큼의 CPU 사이클이 수행되었는지를 저장하고 있는 64bit의 TSC 이용

  - 스레드가 스케줄러에 의해 정지되면 현재의 TSC 값과 스레드가 재시작되었던 시점에 획득된 TSC 값과의 차를 계산 후 쓰레드의 수행 시간에 더해줌 

  - QueryThreadCycleTime, QueryProcessCycleTime : 쓰레드와 프로세스에게 주어졌던 사이클 횟수

  - ReadTimeStampCounter 매크로를 사용하여 현재 TSC 값 획득 가능


 

+ 보다 정밀한 시간 측정

  - QueryPerformanceFrequency(LARGE_INTEGER* pliFrequency)

  - QueryPerformanceCounter(LARGE_INTEGER* pliCount);

  - 위 함수들은 윈도우 스케줄러가 해당 스레드를 선점하지 않을 경우에만 정확하게 시간 측정

  - 아래는 코드


클래스 :

class CStopwatch  
{
public:
 CStopwatch() {QueryPerformanceFrequency(&m_liPerfFreq); Start();}
 ~CStopwatch(){};

  void Start() { QueryPerformanceCounter (&m_liPerfStart);}

  __int64 Now() const {
   LARGE_INTEGER liPerfNow;
   QueryPerformanceCounter(&liPerfNow);
   return (((liPerfNow.QuadPart - m_liPerfStart.QuadPart) * 1000) 
    / m_liPerfFreq.QuadPart);
  }

  __int64 NowInMicro() const {
   LARGE_INTEGER liPerfNow;
   QueryPerformanceCounter(&liPerfNow);
   return (((liPerfNow.QuadPart - m_liPerfStart.QuadPart) * 100000)
    / m_liPerfFreq.QuadPart);
  }

private:
 LARGE_INTEGER m_liPerfFreq;
 LARGE_INTEGER m_liPerfStart;

}; 

 

사용 :

 CStopwatch stopwatch;

 //시간 측정할 코드 
 __int64 qwElapsedTime = stopwatch.Now(); 


 

 

<출처 : 제프리 리처의 Windows via C/C++>