Windows VC 에서 정확 한 시간 을 얻 는 방법
성능 에 주목 하 는 프로그램 개발 자 에 게 좋 은 시간 측정 부품 은 유익 한 친구 이자 훌륭 한 스승 이다.타 이 머 는 프로그램 구성 요소 로 서 프로그래머 의 정확 한 제어 프로 세 스 를 도 울 수 있 을 뿐만 아니 라 강력 한 디 버 깅 무기 이기 도 하 다. 경험 이 있 는 프로그래머 에 게 프로그램의 성능 병목 을 빨리 확인 하거나 서로 다른 알고리즘 에 대해 설득력 있 는 성능 비 교 를 할 수 있다. 윈도 플랫폼 에서 자주 사용 하 는 타 이 머 는 두 가지 가 있 는데 하 나 는 timeGetTime 멀티미디어 타 이 머 로 밀리초 단위 의 타 이 머 를 제공 할 수 있다.그러나 이 정 도 는 많은 응용 장소 에 있어 서 는 너무 거칠다.다른 하 나 는 Query PerformanceCount 카운터 로 시스템 에 따라 초 단위 의 계 수 를 제공 할 수 있 습 니 다.실시 간 도형 처리, 멀티미디어 데이터 흐름 처리, 또는 실시 간 시스템 구조의 프로그래머 에 게 Query PerformanceCount / Query PerformanceFrequency 를 잘 사용 하 는 것 은 기본 적 인 기능 이다.본 고 에서 소개 하고 자 하 는 것 은 Pentium CPU 내부 타임 스탬프 를 직접 이용 하여 시간 을 재 는 고정 밀 타임 수단 이다.다음 토론 은 주로 이라는 책 덕분에 15 페이지 - 17 페이지 에 관심 이 있 는 독자 들 이 이 책 을 직접 참고 할 수 있다.RDTSC 지령 에 대한 상세 한 논 의 는 인텔 제품 매 뉴 얼 을 참고 할 수 있다.본문 은 단지 벽돌 을 던 지 는 용도 로 만 쓰 인 다.Intel Pentium 이상 등급 의 CPU 에는 '타임 스탬프 (Time Stamp)' 라 고 불 리 는 위 젯 이 있 는데, 이 위 젯 은 CPU 가 전 기 를 거 친 이래 시계 주 기 를 기록 하 는 부호 없 는 정수 64 자리 형식 이다.현재 CPU 의 주파수 가 매우 높 기 때문에 이 부품 은 나 초 단위 의 시간 측정 정밀도 에 도달 할 수 있다.이 정확성 은 상술 한 두 가지 방법 으로 비교 할 수 없 는 것 이다.Pentium 이상 의 CPU 에 서 는 이 타임 스탬프 의 숫자 를 읽 고 EDX: EAX 레지스터 쌍 에 저장 하 는 기계 명령 RDTSC (Read Time Stamp Counter) 를 제공 합 니 다.EDX: EAX 레지스터 는 Win 32 플랫폼 에서 C + 언어 저장 함수 반환 값 의 레지스터 이기 때문에 우 리 는 이 명령 을 일반적인 함수 호출 이 라 고 볼 수 있 습 니 다.이렇게:
inline unsigned __int64 GetCycleCount()
{
__asm RDTSC
}
그러나 안 됩 니 다. RDTSC 는 C + + 의 내장 어 셈 블 리 에 의 해 직접 지원 되 지 않 기 때문에 우 리 는 을 사용 해 야 합 니 다.emit 의사 명령 은 이 명령 을 직접 삽입 하 는 기계 코드 형식 0x0F, 0x 31 입 니 다. 다음 과 같 습 니 다.
inline unsigned __int64 GetCycleCount()
{
__asm _emit 0x0F
__asm _emit 0x31
}
이후 카운터 가 필요 한 경우 일반적인 Win 32 API 를 사용 하 는 것 처럼 GetCycleCount 함 수 를 두 번 호출 하여 두 반환 값 의 차 이 를 비교 할 수 있 습 니 다. 이렇게:
unsigned long t;
t = (unsigned long)GetCycleCount();
//Do Something time-intensive ...
t -= (unsigned long)GetCycleCount();
'윈도 그래 픽 프로 그래 밍' 15 페이지 에 클래스 를 만 들 었 습 니 다. 이 계산 기 를 봉인 하 십시오.관심 있 는 독 자 는 그 종류의 코드 를 참고 할 수 있다.저 자 는 보다 정확 한 시간 을 맞 추기 위해 RDTSC 명령 을 수행 하 는 시간 을 GetCycleCount 함 수 를 두 번 연속 호출 하여 계산 하고 저장 하 였 으 며, 이후 시간 계산 이 끝 날 때마다 실제 얻 은 계수 에서 이 짧 은 시간 을 빼 서 더욱 정확 한 시간 계산 숫자 를 얻 었 다.그러나 개인 적 으로 이 점 의 개선 은 의미 가 크 지 않다 고 생각한다.내 기계 에서 실측 하면 이 명령 은 대략 몇 십 에서 100 여 주 기 를 썼 다. Celeron 800 MHz 의 기계 에서 이것 은 10 분 의 1 초 에 불과 하 다.대부분의 응용 에 있어 서 이 시간 은 무시 할 수 있다.나 초 수량 급 까지 정확 해 야 하 는 응용 에 있어 서 이 보상 도 너무 거칠다.
저 는 에서 이러한 소스 코드 를 복사 하여 여러분 께 보 여 드 렸 습 니 다. 다음은 RDTSC 명령 을 사용 한 CPU 시계 순환 스톱워치 류 입 니 다.
// Timer.h
#pragma once
inline unsigned __int64 GetCycleCount(void)
{
_asm _emit 0x0F
_asm _emit 0x31
}
class KTimer
{
unsigned __int64 m_startcycle;
public:
unsigned __int64 m_overhead;
KTimer(void)
{
m_overhead = 0;
Start();
m_overhead = Stop();
}
void Start(void)
{
m_startcycle = GetCycleCount();
}
unsigned __int64 Stop(void)
{
return GetCycleCount()-m_startcycle-m_overhead;
}
};
이 방법의 장점 은 1. 높 은 정밀도 이다.나 초급 에 직접 도달 할 수 있 는 시간 정밀도 (1GHz CPU 에서 시계 주 기 는 1 나 초) 는 다른 시간 측정 방법 으로 는 따라 잡기 어렵다.2. 원가 가 낮다.timeGetTime 함 수 는 멀티미디어 라 이브 러 리 winmm. lib 를 연결 해 야 합 니 다. Query Performance * 함 수 는 MSDN 의 설명 에 따라 하드웨어 의 지원 (지원 되 지 않 는 기 계 를 본 적 이 없 지만) 과 KERNEL 라 이브 러 리 의 지원 이 필요 하기 때문에 둘 다 Windows 플랫폼 에서 만 사용 할 수 있 습 니 다 (DOS 플랫폼 에서 의 고정 밀 시간 계산 문 제 는 을 참고 하 십시오.타이머 8253 제어 에 대한 상세 한 설명 이 들 어 있 습 니 다.그러나 RDTSC 명령 은 CPU 명령 으로 i386 플랫폼 에서 Pentium 이상 의 기 계 는 모두 지원 되 고 플랫폼 의 제한 도 없다 (i386 버 전 UNIX 와 Linux 에서 이 방법 이 똑 같이 적용 되 지만 조건 시험 이 없다 고 믿는다). 그리고 함수 호출 비용 이 가장 적다.
(여기 서 제 가 말씀 드 리 고 싶 은 것 은 이렇게 보면 크로스 플랫폼 도 운영 체제 플랫폼 이 라 고 할 수 있 고 하드웨어 플랫폼 을 뛰 어 넘 을 수 없습니다. 즉, Intel Pentium 이상 의 기계 만 사용 할 수 있 습 니 다)
3. CPU 주파수 와 직접 대응 하 는 속도 관 계 를 가진다.하나의 계 수 는 1 / (CPU 주파수 Hz 수) 초 에 해당 하 며, 이렇게 하면 CPU 의 주파 수 를 알 면 바로 시간 을 계산 할 수 있다.이것 은 Query PerformanceCount 와 달리 후 자 는 Query PerformanceFrequency 를 통 해 현재 계수기 의 초당 계수 횟수 를 얻어 야만 시간 으로 환산 할 수 있다.이 방법의 단점 은 다음 과 같다. 1. 기 존의 C / C + + 컴 파 일 러 는 대부분 RDTSC 명령 을 직접 지원 하지 않 기 때문에 기계 코드 를 직접 끼 워 넣 는 방식 으로 프로 그래 밍 해 야 하기 때문에 비교적 번거롭다.2. 데이터 디 더 링 이 심 합 니 다.사실은 모든 계량 수단 에 있어 정밀도 와 안정성 은 영원히 모순 이다.낮은 정밀도 의 timeGetTime 으로 시간 을 재 면 기본적으로 매번 시간 을 재 는 결 과 는 같다.RDTSC 명령 은 매번 결과 가 다 르 고 수백 내지 수천 의 차이 가 있다.이것 은 이런 방법의 고정 밀 자체 고유의 모순 이다.
(여기 서 데이터 디 더 링 은 확실히 큰 문제 입 니 다. 저 는 이런 상황 을 만난 적 이 있 습 니 다. 예 를 들 어 a 와 b 두 가지 알고리즘 을 테스트 한 적 이 있 습 니 다. 데이터 디 더 링 으로 인해 때로는 a 가 b 보다 시간 이 적 고 때로는 b 가 a 보다 시간 이 적 습 니 다. 저 는 두 가지 테스트 방법 을 생각해 보 았 습 니 다.
(1) 테스트 횟수 를 늘린다. 예 를 들 어 a 와 b 두 가지 알고리즘 을 각각 10 번 씩 테스트 하고 a 가 b 보다 적은 횟수 와 b 가 a 보다 적은 횟수 중 어느 것 이 많은 지 를 보고 어느 알고리즘 의 효율 이 높 은 지 판정한다.
(2) 테스트 데 이 터 량 을 늘 리 고 테스트 데 이 터 량 을 늘 리 면 알고리즘 효율 의 차이 가 나타 날 것 이 라 고 생각 합 니 다) 이 방법 에 대해 시간 을 재 는 최대 길 이 는 다음 과 같은 공식 으로 간단하게 계산 할 수 있 습 니 다. CPU 에서 전 기 를 넣 은 이래 의 초 수 = RDTSC 가 읽 은 주기 수 / CPU 메 인 주파수 속도 (Hz) 64 비트 부호 없 는 정수 가 표현 할 수 있 는 최대 숫자 는 1.8 입 니 다.×10 ^ 19, 제 셀 러 론 800 에서 약 700 년 을 잴 수 있 습 니 다.어쨌든 우 리 는 넘 치 는 문제 에 관심 을 가 질 필요 가 없다.
다음은 몇 가지 작은 예 로 세 가지 시간 계산 방법의 용법 과 정 도 를 간략하게 비교 하 였 다.
#include <stdio.h>
#include "KTimer.h"
main()
{
unsigned t;
KTimer timer;
timer.Start();
Sleep(1000);
t = timer.Stop();
printf("Lasting Time: %d/n",t);
}
//Timer2.cpp timeGetTime
// <mmsys.h>, Windows
// <windows.h> :)
// :CL timer2.cpp /link winmm.lib
#include <windows.h>
#include <stdio.h>
main()
{
DWORD t1, t2;
t1 = timeGetTime();
Sleep(1000);
t2 = timeGetTime();
printf("Begin Time: %u/n", t1);
printf("End Time: %u/n", t2);
printf("Lasting Time: %u/n",(t2-t1));
}
//Timer3.cpp QueryPerformanceCounter
// :CL timer3.cpp /link KERNEl32.lib
#include <windows.h>
#include <stdio.h>
main()
{
LARGE_INTEGER t1, t2, tc;
QueryPerformanceFrequency(&tc);
printf("Frequency: %u/n", tc.QuadPart);
QueryPerformanceCounter(&t1);
Sleep(1000);
QueryPerformanceCounter(&t2);
printf("Begin Time: %u/n", t1.QuadPart);
printf("End Time: %u/n", t2.QuadPart);
printf("Lasting Time: %u/n",( t2.QuadPart- t1.QuadPart));
// ( ),
double dTotalTime = (double)(t2.QuadPart-t1.QuadPart) / (double)tc.QuadPart; //
printf(" : %f/n", dTotalTime);
}
/ / 이상 세 예제 프로그램 은 모두 1 초 동안 휴면 을 테스트 하 는 데 걸 리 는 시간 file: / / 테스트 / 테스트 환경: Celeron 800 MHz / 256 M SDRAM / / Windows 2000 Professional SP2 / / Microsoft Visual C + 6.0 SP5 / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / 다음은 Timer 1 의 운행 결과 입 니 다.높 은 정밀도 의 RDTSC 명령 Lasting Time: 804586872 이하 Timer 2 의 실행 결과 입 니 다. 가장 거 친 timeGetTime API Begin Time: 20254254 End Time: 20255255 Lasting Time: 1001 이하 Timer 3 의 실행 결과 입 니 다.Query PerformanceCount API Frequency: 3579545 Begin Time: 3804729124 End Time: 3808298836 Lasting Time: 3569712 옛사람 들 은 유추 할 수 있다 고 말 했다.도형 프로 그래 밍 을 소개 하 는 책 에서 이렇게 유용 한 실시 간 처리 지식 을 얻 게 되 어 나 는 매우 기쁘다.아름다움 이 있 으 면 감히 자신 을 돌 볼 수 없 으 니, 여러분 도 나 처럼 이 가 볍 고 효과 적 인 타 이 머 를 좋아 하 시 기 를 바 랍 니 다.
인터넷 에 서 는 일종 의 설 이 있다.
double dTotalTime=(double)(t2.QuadPart-t1.QuadPart)/(double)tc.QuadPart
문제 가 있 을 수 있 습 니 다. 예 를 들 어 현재 많은 메인보드 에 CPU 주파수 자동 조정 기능 이 있 는데 주로 에너지 절약 입 니 다. 특히 노트북 에서 이렇게 제거 하면 정확성 을 보장 할 수 없습니다.나 는 이런 견해 가 정확 한 지 아 닌 지 를 모두 가 연구 하도록 제공 할 것 이다.
위의 글 은 주로 에서 발췌 한 것 이다. 사실은 위 에서 언급 한 세 가지 방법 을 제외 하고 위 에서 정확 한 방법 이 없다. 바로 GetTickCount 함 수 를 사용 하 는 것 이다. 이런 방법 은 밀리초 급 의 시간 을 얻 을 수 있 고 구체 적 인 용법 은 다음 과 같다.
DWORD startTime = GetTickCount();
// do something
DWORD totalTime = GetTickCount() - startTime;
참고 문헌:
& lt; CPU 타임 스탬프 로 고정 밀 타임 진행 & gt; 저자: zhangyanqd
《 윈도 그래 픽 프로 그래 밍 》, (미) Feng Yuan 지음.
《 VC 에서 밀리초 급 을 얻 는 시간 》,http://www.cppblog.com/humanchao/archive/2008/04/22/43322.html
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.