고해상도 타임스탬프 획득

Windows는 고해상도 타임스탬프를 획득하거나 시간 간격을 측정하는 데 사용할 수 있는 API를 제공합니다. 네이티브 코드의 기본 API는 QPC(QueryPerformanceCounter)입니다. 디바이스 드라이버의 경우 커널 모드 API는 KeQueryPerformanceCounter입니다. 관리 코드의 경우 System.Diagnostics.Stopwatch 클래스는 정확한 시간 기준으로 QPC 를 사용합니다.

QPC 는 외부 시간 참조와 독립적이며 동기화되지 않습니다. 고해상도 시간 측정에 사용하기 위해 UTC(협정 세계시)와 같은 외부 시간 참조에 동기화할 수 있는 타임스탬프를 검색하려면 GetSystemTimePreciseAsFileTime을 사용합니다.

타임스탬프는 컴퓨터 및 네트워크 성능 측정의 필수적인 부분입니다. 이러한 성능 측정 작업에는 응답 시간, 처리량 및 대기 시간의 계산과 프로파일링 코드 실행이 포함됩니다. 이러한 각 작업에는 시작 및 종료 이벤트에 의해 정의된 시간 간격 동안 발생하는 활동의 측정과 외부 시간 참조와 독립적일 수 있는 종료 이벤트가 포함됩니다.

QPC 는 일반적으로 타임스탬프 이벤트를 사용하고 동일한 시스템 또는 가상 머신에서 발생하는 작은 시간 간격을 측정하는 데 사용하는 가장 좋은 방법입니다. 각 컴퓨터가 NTP(네트워크 시간 프로토콜)와 같은 시간 동기화 체계에 참여하는 경우 여러 컴퓨터에서 이벤트를 타임스탬프하려는 경우 GetSystemTimePreciseAsFileTime 을 사용하는 것이 좋습니다. QPC 는 프로세서의 TSC(타임스탬프 카운터)를 직접 읽는 것과 같은 다른 시간 측정 접근 방식에서 발생할 수 있는 어려움을 방지하는 데 도움이 됩니다.

Windows 버전의 QPC 지원

QPC 는 Windows 2000 및 Windows XP에서 도입되었으며 하드웨어 플랫폼 및 프로세서의 향상된 기능을 활용하기 위해 발전했습니다. 여기서는 이러한 Windows 버전에서 실행되는 소프트웨어를 유지 관리하는 데 도움이 되는 다양한 Windows 버전의 QPC 특성에 대해 설명합니다.

Windows XP 및 Windows 2000

QPC 는 Windows XP 및 Windows 2000에서 사용할 수 있으며 대부분의 시스템에서 잘 작동합니다. 그러나 일부 하드웨어 시스템의 BIOS는 하드웨어 CPU 특성(고정되지 않는 TSC)을 올바르게 나타내지 않았으며 일부 다중 코어 또는 다중 프로세서 시스템은 코어 간에 동기화할 수 없는 TSC가 있는 프로세서를 사용했습니다. 이러한 버전의 Windows를 실행하는 결함이 있는 펌웨어가 있는 시스템은 TSC를 QPC 의 기준으로 사용하는 경우 다른 코어에서 동일한 QPC 읽기를 제공하지 않을 수 있습니다.

Windows Vista 및 Windows Server 2008

Windows Vista 및 Windows Server 2008과 함께 제공되는 모든 컴퓨터는 QPC의 기준으로 플랫폼 카운터(HPET(High Precision Event Timer) 또는 ACPI POWER Management 타이머(PM 타이머)를 사용했습니다. 이러한 플랫폼 타이머는 TSC보다 액세스 대기 시간이 높으며 여러 프로세서 간에 공유됩니다. 이렇게 하면 여러 프로세서에서 동시에 호출되는 경우 QPC 의 확장성이 제한됩니다.

Windows 7 및 Windows Server 2008 R2

대부분의 Windows 7 및 Windows Server 2008 R2 컴퓨터에는 일정한 속도 TSC가 있는 프로세서가 있으며 이러한 카운터를 QPC의 기준으로 사용합니다. TSC는 매우 짧은 대기 시간 및 오버헤드(프로세서 유형에 따라 10대 또는 100s 컴퓨터 주기 순서)로 액세스할 수 있는 고해상도 프로세서별 하드웨어 카운터입니다. Windows 7 및 Windows Server 2008 R2는 운영 체제(또는 하이퍼바이저)가 시스템 초기화 중에 모든 프로세서에서 개별 TSC를 긴밀하게 동기화할 수 있는 단일 클록 도메인 시스템에서 QPC 의 기초로 TSC를 사용합니다. 이러한 시스템에서 성능 카운터를 읽는 비용은 플랫폼 카운터를 사용하는 시스템에 비해 훨씬 낮습니다. 또한 동시 호출에 대한 추가 오버헤드가 없으며 사용자 모드 쿼리는 종종 시스템 호출을 우회하여 오버헤드를 더욱 줄입니다. TSC가 시간 유지에 적합하지 않은 시스템에서 Windows는 QPC의 기준으로 플랫폼 카운터(HPET 타이머 또는 ACPI PM 타이머)를 자동으로 선택합니다.

Windows 8, Windows 8.1, Windows Server 2012 및 Windows Server 2012 R2

Windows 8, Windows 8.1, Windows Server 2012 및 Windows Server 2012 R2는 성능 카운터의 기준으로 TSC를 사용합니다. TSC 동기화 알고리즘은 프로세서가 많은 대형 시스템을 더 잘 수용할 수 있도록 크게 개선되었습니다. 또한 운영 체제에서 정확한 벽시계 타임스탬프를 획득할 수 있는 새로운 정확한 시간 API에 대한 지원이 추가되었습니다. 자세한 내용은 GetSystemTimePreciseAsFileTime을 참조하세요. arm 프로세서를 사용하는 Windows RT 및 Windows 11 및 Windows 10 디바이스에서 성능 카운터는 플랫폼이 너무 장착된 경우 Arm 일반 타이머에서 제공하는 독점 플랫폼 카운터 또는 시스템 카운터를 기반으로 합니다.

타임스탬프를 획득하기 위한 지침

Windows는 안정적이고 효율적인 성능 카운터를 제공하는 데 계속 투자할 것입니다. 해상도가 1 마이크로초 이상인 타임스탬프가 필요하고 타임스탬프를 외부 시간 참조에 동기화할 필요가 없는 경우 QueryPerformanceCounter, KeQueryPerformanceCounter 또는 KeQueryInterruptTimePrecise를 선택합니다. 해상도가 1 마이크로초 이상인 UTC 동기화 타임스탬프가 필요한 경우 GetSystemTimePreciseAsFileTime 또는 KeQuerySystemTimePrecise를 선택합니다.

예를 들어 하드웨어 타이머 정보에 설명된 이유로 TSC 레지스터를 QPC 기준으로 사용할 수 없는 비교적 적은 수의 플랫폼에서 고해상도 타임스탬프를 획득하는 것은 해상도가 낮은 타임스탬프를 획득하는 것보다 훨씬 더 비쌀 수 있습니다. 10~16밀리초의 해상도로 충분하면 GetTickCount64, QueryInterruptTime, QueryUnbiasedInterruptTime, KeQueryInterruptTime 또는 KeQueryUnbiasedInterruptTime 을 사용하여 외부 시간 참조에 동기화되지 않은 타임스탬프를 가져올 수 있습니다. UTC 동기화 타임스탬프의 경우 GetSystemTimeAsFileTime 또는 KeQuerySystemTime을 사용합니다. 더 높은 해상도가 필요한 경우 QueryInterruptTimePrecise, QueryUnbiasedInterruptTimePrecise 또는 KeQueryInterruptTimePrecise 를 사용하여 타임스탬프를 대신 가져올 수 있습니다.

일반적으로 성능 카운터 결과는 여러 스레드 또는 프로세스에서 측정되는 경우에도 다중 코어 및 다중 프로세서 시스템의 모든 프로세서에서 일관됩니다. 이 규칙에 대한 몇 가지 예외는 다음과 같습니다.

  • 특정 프로세서에서 실행되는 Windows Vista 이전 운영 체제는 다음 이유 중 하나로 인해 이러한 일관성을 위반할 수 있습니다.

    • 하드웨어 프로세서에는 고정되지 않는 TSC가 있으며 BIOS는 이 조건을 올바르게 나타내지 않습니다.
    • 사용된 TSC 동기화 알고리즘은 프로세서 수가 많은 시스템에 적합하지 않았습니다.
  • 서로 다른 스레드에서 얻은 성능 카운터 결과를 비교할 때 ± 1틱에 따라 다른 값이 모호한 순서를 갖는 것을 고려합니다. 타임스탬프를 동일한 스레드에서 가져온 경우 이 ± 1틱 불확실성은 적용되지 않습니다. 이 컨텍스트에서 틱이라는 용어는 1÷( QueryPerformanceFrequency에서 얻은 성능 카운터의 빈도)와 같은 기간을 나타냅니다.

하드웨어에서 동기화되지 않는 다중 클록 도메인이 있는 대규모 서버 시스템에서 성능 카운터를 사용하는 경우 Windows는 TSC를 타이밍 목적으로 사용할 수 없다고 판단하고 QPC의 기준으로 플랫폼 카운터를 선택합니다. 이 시나리오는 여전히 신뢰할 수 있는 타임스탬프를 생성하지만 액세스 대기 시간과 확장성은 부정적인 영향을 받습니다. 따라서 앞의 사용 지침에서 설명한 대로 이러한 해결이 필요한 경우 1 마이크로초 또는 더 나은 해상도를 제공하는 API만 사용합니다. TSC는 모든 프로세서 클록 도메인의 하드웨어 동기화를 포함하는 다중 클록 도메인 시스템의 QPC 에 대한 기초로 사용되며, 이를 통해 효과적으로 단일 클록 도메인 시스템으로 작동합니다.

성능 카운터의 빈도는 시스템 부팅 시 고정되며 모든 프로세서에서 일관되므로 애플리케이션이 초기화되면 QueryPerformanceFrequency 의 빈도만 쿼리한 다음 결과를 캐시하면 됩니다.

가상화

성능 카운터는 올바르게 구현된 하이퍼바이저에서 실행되는 모든 게스트 가상 머신에서 안정적으로 작동해야 합니다. 그러나 하이퍼바이저 버전 1.0 인터페이스를 준수하고 참조 시간 인식 기능을 노출하는 하이퍼바이저는 오버헤드를 크게 줄일 수 있습니다. 하이퍼바이저 인터페이스 및 인식에 대한 자세한 내용은 하이퍼바이저 사양을 참조하세요.

직접 TSC 사용

일부 버전의 Windows, 가상 머신의 실시간 마이그레이션 및 고정 또는 긴밀하게 동기화된 TSC가 없는 하드웨어 시스템에서 신뢰할 수 있는 결과를 얻을 수 없으므로 RDTSC 또는 RDTSCP 프로세서 명령을 사용하여 TSC를 직접 쿼리하는 것이 좋습니다. 대신 QPC 를 사용하여 제공하는 추상화, 일관성 및 이식성을 활용하는 것이 좋습니다.

타임스탬프를 가져오는 예제

이 섹션의 다양한 코드 예제에서는 타임스탬프를 획득하는 방법을 보여 줍니다.

네이티브 코드에서 QPC 사용

이 예제에서는 C 및 C++ 네이티브 코드에서 QPC 를 사용하는 방법을 보여줍니다.

LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds;
LARGE_INTEGER Frequency;

QueryPerformanceFrequency(&Frequency); 
QueryPerformanceCounter(&StartingTime);

// Activity to be timed

QueryPerformanceCounter(&EndingTime);
ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;


//
// We now have the elapsed number of ticks, along with the
// number of ticks-per-second. We use these values
// to convert to the number of elapsed microseconds.
// To guard against loss-of-precision, we convert
// to microseconds *before* dividing by ticks-per-second.
//

ElapsedMicroseconds.QuadPart *= 1000000;
ElapsedMicroseconds.QuadPart /= Frequency.QuadPart;

관리 코드에서 고해상도 타임스탬프를 획득

이 예제에서는 관리 코드 System.Diagnostics.Stopwatch 클래스를 사용하는 방법을 보여 줍니다.

using System.Diagnostics;

long StartingTime = Stopwatch.GetTimestamp();

// Activity to be timed

long EndingTime  = Stopwatch.GetTimestamp();
long ElapsedTime = EndingTime - StartingTime;

double ElapsedSeconds = ElapsedTime * (1.0 / Stopwatch.Frequency);

System.Diagnostics.Stopwatch 클래스는 시간 간격 측정을 수행하는 몇 가지 편리한 메서드도 제공합니다.

커널 모드에서 QPC 사용

Windows 커널은 성능 카운터와 성능 빈도를 모두 얻을 수 있는 KeQueryPerformanceCounter 를 통해 성능 카운터에 대한 커널 모드 액세스를 제공합니다. KeQueryPerformanceCounter 는 커널 모드에서만 사용할 수 있으며 디바이스 드라이버 및 기타 커널 모드 구성 요소의 작성기에 제공됩니다.

이 예제에서는 C 및 C++ 커널 모드에서 KeQueryPerformanceCounter 를 사용하는 방법을 보여줍니다.

LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds;
LARGE_INTEGER Frequency;

StartingTime = KeQueryPerformanceCounter(&Frequency);

// Activity to be timed

EndingTime = KeQueryPerformanceCounter(NULL);
ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;
ElapsedMicroseconds.QuadPart *= 1000000;
ElapsedMicroseconds.QuadPart /= Frequency.QuadPart;

QPC 및 TSC에 대한 일반 FAQ

다음은 일반적으로 QPC 및 TSC에 대한 질문과 대답입니다.

QueryPerformanceCounter()가 Win32 GetTickCount() 또는 GetTickCount64() 함수와 동일한가요?

아니요. GetTickCountGetTickCount64QPC와 관련이 없습니다. GetTickCountGetTickCount64 는 시스템이 시작된 이후의 시간(밀리초)을 반환합니다.

QPC를 사용하거나 RDTSC/RDTSCP 지침을 직접 호출해야 하나요?

정확성 및 이식성 문제를 방지하려면 TSC 레지스터 또는 RDTSC 또는 RDTSCP 프로세서 지침을 사용하는 대신 QPC 사용하는 것이 좋습니다.

QPC와 외부 시간 Epoch의 관계는 무엇인가요? UTC와 같은 외부 Epoch에 동기화할 수 있나요?

QPC 는 UTC와 같은 외부 시간 참조에 동기화할 수 없는 하드웨어 카운터를 기반으로 합니다. 외부 UTC 참조에 동기화할 수 있는 정확한 시간 스탬프의 경우 GetSystemTimePreciseAsFileTime을 사용합니다.

QPC는 일광 절약 시간, 윤초, 표준 시간대 또는 관리자가 변경한 시스템 시간 변경의 영향을 받나요?

아니요. QPC 는 시스템 시간 및 UTC와 완전히 독립적입니다.

QPC 정확도는 전원 관리 또는 Turbo Boost 기술로 인한 프로세서 주파수 변경의 영향을 받나요?

아니요. 프로세서에 고정 TSC가 있는 경우 QPC 는 이러한 종류의 변경 내용의 영향을 받지 않습니다. 프로세서에 고정 TSC가 없는 경우 QPC는 프로세서 주파수 변경 또는 Turbo Boost 기술의 영향을 받지 않는 플랫폼 하드웨어 타이머에 되돌리기.

QPC는 하이퍼 스레딩이 있는 다중 프로세서 시스템, 다중 코어 시스템 및 시스템에서 안정적으로 작동하나요?

예.

QPC가 내 컴퓨터에서 작동하는지 확인하고 유효성을 검사할 어떻게 할까요? 있나요?

이러한 검사를 수행할 필요가 없습니다.

고정 TSC가 없는 프로세서는 무엇입니까? 시스템에 고정되지 않는 TSC가 있는 경우 어떻게 검사 수 있나요?

이 검사 직접 수행할 필요가 없습니다. Windows 운영 체제는 시스템 초기화 시 여러 검사를 수행하여 TSC가 QPC의 기준으로 적합한지 확인합니다. 그러나 참조 목적으로 다음 중 하나를 사용하여 프로세서에 고정 TSC가 있는지 여부를 확인할 수 있습니다.

  • Windows Sysinternals의 Coreinfo.exe 유틸리티
  • TSC 특성과 관련된 CPUID 명령에서 반환되는 값 확인
  • 프로세서 제조업체의 설명서

다음은 Windows Sysinternals Coreinfo.exe 유틸리티(www.sysinternals.com)에서 제공하는 TSC-INVARIANT 정보를 보여 줍니다. 별표는 "True"를 의미합니다.

> Coreinfo.exe 

Coreinfo v3.2 - Dump information on system CPU and memory topology
Copyright (C) 2008-2012 Mark Russinovich
Sysinternals - www.sysinternals.com

 <unrelated text removed>

RDTSCP          * Supports RDTSCP instruction
TSC             * Supports RDTSC instruction
TSC-DEADLINE    - Local APIC supports one-shot deadline timer
TSC-INVARIANT   * TSC runs at constant rate

QPC는 Windows RT 하드웨어 플랫폼에서 안정적으로 작동하나요?

예.

QPC는 얼마나 자주 롤오버하나요?

가장 최근의 시스템 부팅으로부터 100년 이내이며, 사용된 기본 하드웨어 타이머를 기반으로 하는 시간이 길어질 수 있습니다. 대부분의 애플리케이션에서 롤오버는 문제가 되지 않습니다.

QPC 호출의 계산 비용은 어떻게 됩니까?

QPC의 계산 호출 비용은 주로 기본 하드웨어 플랫폼에 의해 결정됩니다. TSC 레지스터가 QPC의 기초로 사용되는 경우 계산 비용은 주로 프로세서가 RDTSC 명령을 처리하는 데 걸리는 시간을 기준으로 결정됩니다. 이 시간은 사용된 프로세서에 따라 10개의 CPU 주기에서 수백 개의 CPU 주기까지 다양합니다. TSC를 사용할 수 없는 경우 시스템은 다른 하드웨어 시간 기준을 선택합니다. 이러한 시간 기반은 마더보드(예: PCI 사우스 브리지 또는 PCH)에 있기 때문에 호출당 계산 비용은 TSC보다 높으며 프로세서 속도 및 기타 하드웨어 요인에 따라 0.8 ~ 1.0 마이크로초 부근에 자주 있습니다. 이 비용은 마더보드의 하드웨어 디바이스에 액세스하는 데 필요한 시간에 따라 결정됩니다.

QPC에 커널 전환(시스템 호출)이 필요한가요?

시스템에서 TSC 레지스터를 QPC의 기준으로 사용할 수 있는 경우 커널 전환이 필요하지 않습니다. 시스템에서 HPET 또는 PM 타이머와 같은 다른 시간 기반을 사용해야 하는 경우 시스템 호출이 필요합니다.

성능 카운터 단조(감소하지 않음)인가요?

예. QPC는 뒤로 이동하지 않습니다.

성능 카운터를 사용하여 이벤트를 정시에 정렬할 수 있나요?

예. 그러나 서로 다른 스레드에서 가져온 성능 카운터 결과를 비교할 때 ± 1 틱으로 다른 값은 동일한 타임스탬프를 가진 것처럼 모호한 순서를 갖습니다.

성능 카운터는 얼마나 정확합니까?

대답은 다양한 요인에 따라 달라집니다. 자세한 내용은 하위 수준 하드웨어 클록 특성을 참조하세요.

QPC 및 TSC를 사용한 프로그래밍에 대한 FAQ

다음은 QPC 및 TSC를 사용한 프로그래밍에 대한 질문과 대답입니다.

QPC 출력을 밀리초로 변환해야 합니다. double 또는 float로 변환하여 정밀도 손실을 방지하려면 어떻게 해야 하나요?

정수 성능 카운터에서 계산을 수행할 때 유의해야 할 몇 가지 사항이 있습니다.

  • 정수 나누기에서 나머지를 잃게 됩니다. 이로 인해 경우에 따라 전체 자릿수가 손실될 수 있습니다.
  • 64비트 정수와 부동 소수점(double) 사이를 변환하면 부동 소수점 매니타가 가능한 모든 정수 값을 나타낼 수 없기 때문에 전체 자릿수가 손실될 수 있습니다.
  • 64비트 정수의 곱하면 정수 오버플로가 발생할 수 있습니다.

일반적인 원칙으로, 이러한 계산 및 변환을 가능한 한 지연하여 발생하는 오류가 복합화되지 않도록 합니다.

FILETIME에 추가할 수 있도록 QPC를 100나노초 틱으로 변환하려면 어떻게 해야 하나요?

파일 시간은 1601년 1월 1일 오전 12:00(UTC) 이후 경과된 100나노초 간격의 수를 나타내는 64비트 값입니다. 파일 시간은 GetSystemTimeAsFileTimeGetSystemTimePreciseAsFileTime과 같이 하루 중 시간을 반환하는 Win32 API 호출에서 사용됩니다. 반면 QueryPerformanceCounter 는 시간을 1/( QueryPerformanceFrequency에서 가져온 성능 카운터의 빈도)의 단위로 나타내는 값을 반환합니다. 둘 사이의 변환에는 QPC 간격과 100나노초 간격의 비율을 계산해야 합니다. 값이 작을 수 있으므로 정밀도를 잃지 않도록 주의하세요(0.0000001/0.000000340).

QPC에서 반환되는 타임스탬프가 부인 정수인 이유는 무엇인가요?

QPC 타임스탬프와 관련된 계산에는 빼기 작업이 포함될 수 있습니다. 서명된 값을 사용하여 음수 값을 생성할 수 있는 계산을 처리할 수 있습니다.

관리 코드에서 고해상도 타임스탬프를 얻으려면 어떻게 해야 하나요?

System.Diagnostics.Stopwatch 클래스에서 Stopwatch.GetTimeStamp 메서드를 호출합니다. Stopwatch.GetTimeStamp를 사용하는 방법에 대한 예제는 관리 코드에서 고해상도 타임스탬프 획득을 참조하세요.

QueryPerformanceFrequency는 어떤 상황에서 FALSE를 반환하거나 QueryPerformanceCounter는 0을 반환하나요?

Windows XP 이상을 실행하는 시스템에서는 이 문제가 발생하지 않습니다.

QPC를 사용하려면 스레드 선호도를 단일 코어로 설정해야 하나요?

아니요. 자세한 내용은 타임스탬프를 획득하기 위한 지침을 참조하세요. 이 시나리오는 필요하지도 바람직하지도 않습니다. 이 시나리오를 수행하면 처리를 하나의 코어로 제한하거나 여러 스레드가 QueryPerformanceCounter를 호출할 때 선호도를 동일한 코어로 설정하는 경우 단일 코어에 병목 상태를 만들어 애플리케이션의 성능에 부정적인 영향을 줄 수 있습니다.

하위 수준 하드웨어 클록 특성

이 섹션에서는 하위 수준의 하드웨어 클록 특성을 보여 줍니다.

절대 클록 및 차이 클록

절대 클록은 정확한 하루 중 시간 판독값을 제공합니다. 일반적으로 UTC(협정 세계시)를 기반으로 하므로 정확도는 부분적으로 외부 시간 참조에 얼마나 잘 동기화되는지에 따라 달라집니다. 차이 클록은 시간 간격을 측정하며 일반적으로 외부 시간 epoch를 기반으로 하지 않습니다. QPC 는 차이 클록이며 외부 시간 epoch 또는 참조와 동기화되지 않습니다. 시간 간격 측정에 QPC 를 사용하는 경우 일반적으로 절대 클록에서 파생된 타임스탬프를 사용하는 것보다 정확도가 향상됩니다. 절대 클록의 시간을 동기화하는 프로세스는 단기 시간 간격 측정의 불확실성을 증가시키는 위상 및 빈도 변화를 도입할 수 있기 때문입니다.

해상도, 정밀도, 정확도 및 안정성

QPC 는 하드웨어 카운터를 기본으로 사용합니다. 하드웨어 타이머는 틱 생성기, 틱 수를 계산하는 카운터 및 카운터 값을 검색하는 수단의 세 부분으로 구성됩니다. 이러한 세 가지 구성 요소의 특성은 QPC의 해상도, 정밀도, 정확도 및 안정성을 결정합니다.

하드웨어 생성기가 일정한 속도로 틱을 제공하는 경우 이러한 틱을 계산하기만 하면 시간 간격을 측정할 수 있습니다. 틱이 생성되는 속도를 빈도라고 하며 Hertz(Hz)로 표현됩니다. 주파수의 상호는 마침표 또는 틱 간격이라고 하며 적절한 SI(International System of Units) 시간 단위(예: 초, 밀리초, 마이크로초 또는 나노초)로 표현됩니다.

시간 간격

타이머의 해상도는 마침표와 같습니다. 해상도는 두 타임스탬프를 구분하는 기능을 결정하고 측정할 수 있는 가장 작은 시간 간격에 하한을 배치합니다. 이를 틱 해상도라고도 합니다.

디지털 시간 측정은 시간이 지속적으로 진행되는 동안 디지털 카운터가 개별 단계에서 진행되므로 ± 1 틱의 측정 불확실성을 도입합니다. 이 불확실성을 양자화 오류라고 합니다. 일반적인 시간 간격 측정의 경우 수량화 오류가 측정되는 시간 간격보다 훨씬 작기 때문에 이 효과는 무시될 수 있습니다.

디지털 시간 측정

그러나 측정되는 기간이 작고 타이머의 해상도에 근접하는 경우 이 정량화 오류를 고려해야 합니다. 발생한 오류의 크기는 한 클록 기간의 크기입니다.

다음 두 다이어그램은 1시간 단위의 해상도가 있는 타이머를 사용하여 ± 1틱 불확실성의 영향을 보여 줍니다.

틱 불확실성

QueryPerformanceFrequencyQPC의 빈도를 반환하고 마침표와 해상도는 이 값의 상호와 같습니다. QueryPerformanceFrequency가 반환하는 성능 카운터 빈도는 시스템 초기화 중에 결정되며 시스템이 실행되는 동안 변경되지 않습니다.

참고

QueryPerformanceFrequency가 하드웨어 틱 생성기의 실제 빈도를 반환하지 않는 경우가 많습니다. 예를 들어 일부 이전 버전의 Windows에서 QueryPerformanceFrequency는 TSC 빈도를 1024로 나눈 값을 반환합니다. 하이퍼바이저 버전 1.0 인터페이스를 구현하는 하이퍼바이저에서(또는 항상 일부 최신 버전의 Windows에서) 실행되는 경우 성능 카운터 빈도는 10MHz로 고정됩니다. 따라서 QueryPerformanceFrequency 가 하드웨어 빈도에서 파생된 값을 반환한다고 가정하지 마세요.

 

QueryPerformanceCounter 는 성능 카운터를 읽고 컴퓨터가 대기, 최대 절전 모드 또는 연결된 대기 상태와 같은 절전 모드 상태인 시간을 포함하여 Windows 운영 체제가 시작된 이후 발생한 총 틱 수를 반환합니다.

다음 예제에서는 틱 간격 및 해상도를 계산하는 방법과 틱 수를 시간 값으로 변환하는 방법을 보여 줍니다.

예제 1

QueryPerformanceFrequency 는 특정 컴퓨터에서 3,125,000 값을 반환합니다. 이 컴퓨터에서 QPC 측정의 틱 간격 및 해상도는 무엇인가요? 틱 간격 또는 마침표는 3,125,000의 상호이며 0.000000320(320나노초)입니다. 따라서 각 틱은 320나노초의 전달을 나타냅니다. 320나노초보다 작은 시간 간격은 이 컴퓨터에서 측정할 수 없습니다.

틱 간격 = 1/(성능 빈도)

틱 간격 = 1/3,125,000 = 320 ns

예제 2

앞의 예제와 동일한 컴퓨터에서 QPC 에 대한 두 번의 연속 호출에서 반환된 값의 차이는 5입니다. 두 호출 사이에 얼마나 많은 시간이 경과되었나요? 5틱에 320나노초를 곱하면 1.6 마이크로초가 생성됩니다.

ElapsedTime = 틱 * 틱 간격

ElapsedTime = 5 * 320 ns = 1.6 μs

소프트웨어에서 틱 카운터에 액세스(읽기)하는 데 시간이 걸리며, 이 액세스 시간은 시간 측정의 정밀도를 줄일 수 있습니다. 이는 최소 간격 시간(측정할 수 있는 가장 작은 시간 간격)이 해상도와 액세스 시간이 더 크기 때문입니다.

Precision = MAX [ Resolution, AccessTime]

예를 들어 100나노초 해상도와 800나노초 액세스 시간이 있는 가상 하드웨어 타이머를 생각해 보세요. 플랫폼 타이머가 QPC의 기초로 TSC 레지스터 대신 사용된 경우일 수 있습니다. 따라서 이 계산에 표시된 것처럼 정밀도는 100나노초가 아닌 800나노초가 될 것입니다.

전체 자릿수 = MAX [800 ns,100 ns] = 800 ns

이 두 그림은 이 효과를 묘사합니다.

qpc 액세스 시간

액세스 시간이 해상도보다 큰 경우 추측하여 정밀도를 개선하지 마세요. 즉, 타임스탬프를 호출의 시작 또는 끝에서 정확하게 수행한다고 가정하는 것은 오류입니다.

반면 QPC 액세스 시간은 20나노초이고 하드웨어 클록 해상도는 100나노초인 다음 예제를 고려해 보세요. TSC 레지스터가 QPC의 기준으로 사용된 경우일 수 있습니다. 여기서 정밀도는 클록 해상도로 제한됩니다.

qpc 전체 자릿수

실제로 카운터를 읽는 데 필요한 시간이 해상도보다 크거나 작은 시간 원본을 찾을 수 있습니다. 두 경우 모두 정밀도는 둘 중 더 큽다.

이 표에서는 다양한 클록의 대략적인 해상도, 액세스 시간 및 정밀도에 대한 정보를 제공합니다. 일부 값은 다른 프로세서, 하드웨어 플랫폼 및 프로세서 속도에 따라 달라집니다.

클록 원본 명목 클록 빈도 클록 해상도 액세스 시간(일반) 전체 자릿수
PC RTC 64Hz 15.625밀리초 해당 없음 해당 없음
3GHz 프로세서 클록이 있는 TSC를 사용하여 성능 카운터 쿼리 3MHz 333나노초 30나노초 333나노초
3GHz 주기 시간이 있는 시스템의 RDTSC 컴퓨터 명령 3GHz 피코세콘 333개 30나노초 30나노초

 

QPC는 하드웨어 카운터를 사용하기 때문에 하드웨어 카운터의 몇 가지 기본 특성을 이해하면 QPC의 기능 및 제한 사항에 대해 이해할 수 있습니다.

가장 일반적으로 사용되는 하드웨어 틱 생성기는 크리스탈 진동기입니다. 크리스탈은 뛰어난 안정성과 정확도로 저렴한 주파수 참조를 제공하는 압전 특성을 나타내는 작은 쿼츠 또는 기타 세라믹 재료입니다. 이 빈도는 클록에 의해 계산되는 틱을 생성하는 데 사용됩니다.

타이머의 정확도는 true 또는 표준 값의 적합도를 나타냅니다. 이는 주로 지정된 주파수에서 틱을 제공하는 크리스탈 진동기의 기능에 따라 달라집니다. 진동 빈도가 너무 높으면 클록이 '빠르게 실행'되며 측정된 간격이 실제로보다 더 오래 표시됩니다. 빈도가 너무 낮으면 클록이 '느리게 실행'되며 측정된 간격이 실제로보다 짧게 표시됩니다.

짧은 기간(예: 응답 시간 측정, 네트워크 대기 시간 측정 등)에 대한 일반적인 시간 간격 측정의 경우 하드웨어 진동기의 정확도는 일반적으로 충분합니다. 그러나 일부 측정의 경우 특히 장시간 간격 또는 다른 컴퓨터에서 수행된 측정값을 비교하려는 경우 진동기 주파수 정확도가 중요해집니다. 이 섹션의 나머지 부분에서는 진동기 정확도의 효과를 살펴봅니다.

결정의 진동 빈도는 제조 공정 중에 설정되며 제조업체가 지정한 빈도와 최대 주파수 오프셋이라고 하는 '백만 개당 부품'(ppm)으로 표현된 제조 허용 오차를 더하거나 뺀 값으로 지정합니다. 지정된 주파수가 1,000,000Hz이고 최대 주파수 오프셋이 ± 10ppm인 크리스탈은 실제 주파수가 999,990Hz에서 1,000,010Hz 사이인 경우 사양 제한 내에 있습니다.

초당 마이크로초로 백만 단위의 구 부분을 대체하여 시간 간격 측정에 이 빈도 오프셋 오류를 적용할 수 있습니다. + 10ppm 오프셋이 있는 오실레이터는 초당 10 마이크로초의 오류가 발생합니다. 따라서 1초 간격을 측정할 때 빠르게 실행되고 1초 간격을 0.9999990초로 측정합니다.

편리한 참조는 100ppm의 빈도 오류로 인해 24시간 후 8.64초의 오류가 발생한다는 것입니다. 이 표에서는 더 긴 시간 간격 동안 누적된 오류로 인한 측정 불확실성을 표시합니다.

시간 간격 기간 +/- 10PPM 주파수 허용 오차로 인한 누적 오류로 인한 측정 불확실성
1 마이크로초 ± 10 피코세콘드 (10-12)
1밀리초 ± 10나노초(10-9)
1초 ± 10 마이크로초
1시간 ± 60 마이크로초
1일 ± 0.86초
1주 ± 6.08초

 

앞의 표에서는 짧은 시간 간격 동안 빈도 오프셋 오류를 무시할 수 있음을 보여 줍니다. 그러나 긴 시간 간격의 경우 빈도 오프셋이 작더라도 측정 불확실성이 상당할 수 있습니다.

개인용 컴퓨터 및 서버에서 사용되는 크리스탈 진동기는 일반적으로 100만 개당 ± 30~50개 부품의 주파수 허용 오차로 제조되며, 크리스탈은 500ppm까지 꺼질 수 있습니다. 빈도 오프셋 허용 오차가 훨씬 더 엄격한 결정을 사용할 수 있지만 비용이 더 많이 들기 때문에 대부분의 컴퓨터에서 사용되지 않습니다.

이 빈도 오프셋 오류의 부작용을 줄이려면 최신 버전의 Windows, 특히 Windows 8 여러 하드웨어 타이머를 사용하여 빈도 오프셋을 감지하고 가능한 한 보정합니다. 이 보정 프로세스는 Windows가 시작될 때 수행됩니다.

다음 예제에서 알 수 있듯이 하드웨어 클록의 주파수 오프셋 오류는 달성 가능한 정확도에 영향을 미치며 클록의 해상도는 덜 중요할 수 있습니다.

빈도 오프셋 오류는 달성 가능한 정확도에 영향을 줍니다.

예제 1

해상도가 1 마이크로초이고 최대 주파수 오프셋 오차가 ±50ppm인 1MHz 진동기를 사용하여 시간 간격 측정을 수행한다고 가정합니다. 이제 오프셋이 정확히 +50 ppm이라고 가정해 보겠습니다. 즉, 실제 주파수는 1,000,050Hz입니다. 시간 간격을 24시간으로 측정한 경우 측정은 4.3초가 너무 짧습니다(23:59:55.7000000 측정과 실제 24:00:00.000000).

하루 중 초 = 86400

빈도 오프셋 오류 = 50 ppm = 0.00005

86,400초 * 0.00005 = 4.3초

예제 2

프로세서 TSC 클록이 결정 진동기에 의해 제어되고 3GHz의 주파수를 지정했다고 가정합니다. 즉, 해상도는 1/3,000,000,000 또는 약 333 picoseconds입니다. 프로세서 클록을 제어하는 데 사용되는 결정의 주파수 허용 오차는 ±50ppm이고 실제로는 +50 ppm이라고 가정합니다. 인상적인 해상도에도 불구하고 24시간의 시간 간격 측정은 여전히 4.3초가 너무 짧습니다. (23:59:55.70000000000은 실제 24:00:00:00.0000000000000에 비해 측정됨).

하루 중 초 = 86400

빈도 오프셋 오류 = 50 ppm = 0.00005

86,400초 * 0.00005 = 4.3초

이는 고해상도 TSC 클록이 반드시 낮은 해상도 클록보다 더 정확한 측정값을 제공하는 것은 아니라는 것을 보여줍니다.

예제 3

서로 다른 두 컴퓨터를 사용하여 동일한 24시간 간격을 측정하는 것이 좋습니다. 두 컴퓨터에는 최대 주파수 오프셋이 ± 50ppm인 진동기가 있습니다. 이 두 시스템에서 동일한 시간 간격의 측정은 얼마나 멀리 떨어져 있을까요? 이전 예제와 마찬가지로 ± 50ppm은 24시간 후 최대 ± 4.3초의 오류를 생성합니다. 한 시스템이 4.3초 빠르게 실행되고 다른 시스템이 4.3초 느리게 실행되는 경우 24시간 후의 최대 오류는 8.6초가 될 수 있습니다.

하루 중 초 = 86400

빈도 오프셋 오류 = ±50 ppm = ±0.00005

±(86,400초 * 0.00005) = ±4.3초

두 시스템 간의 최대 오프셋 = 8.6초

요약하자면, 긴 시간 간격을 측정하고 서로 다른 시스템 간의 측정값을 비교할 때 빈도 오프셋 오류가 점점 더 중요해집니다.

타이머의 안정성은 예를 들어 온도 변경의 결과와 같이 시간에 따라 틱 빈도가 변경되는지 여부를 설명합니다. 컴퓨터에서 틱 생성기로 사용되는 석영 결정은 온도의 기능으로 주파수의 작은 변화를 나타냅니다. 열 드리프트로 인한 오류는 일반적으로 일반 온도 범위의 빈도 오프셋 오류에 비해 작습니다. 그러나 큰 온도 변동이 적용되는 휴대용 장비 또는 장비용 소프트웨어 설계자는 이 효과를 고려해야 할 수 있습니다.

하드웨어 타이머 정보

TSC 레지스터(x86 및 x64)

모든 최신 Intel 및 AMD 프로세서에는 일반적으로 프로세서 클록과 같은 높은 속도로 증가하는 64비트 레지스터인 TSC 레지스터가 포함되어 있습니다. 이 카운터의 값은 RDTSC 또는 RDTSCP 컴퓨터 지침을 통해 읽을 수 있으며 프로세서에 따라 수십 또는 수백 개의 컴퓨터 주기 순서로 매우 낮은 액세스 시간과 계산 비용을 제공합니다.

TSC 레지스터는 이상적인 타임스탬프를 사용하는 메커니즘처럼 보이지만 시간 보관을 위해 안정적으로 작동할 수 없는 상황은 다음과 같습니다.

  • 모든 프로세서에 사용 가능한 TSC 레지스터가 있는 것은 아니므로 소프트웨어에서 TSC 레지스터를 사용하면 이식성 문제가 직접 발생합니다. (이 경우 Windows는 이식성 문제를 방지하는 QPC 에 대한 대체 시간 원본을 선택합니다.)
  • 일부 프로세서는 TSC 클록의 빈도를 변경하거나 TSC 레지스터의 발전을 중지할 수 있으므로 TSC가 이러한 프로세서의 타이밍 목적에 적합하지 않습니다. 이러한 프로세서에는 고정되지 않는 TSC 레지스터가 있다고 합니다. (Windows는 자동으로 이를 감지하고 QPC에 대한 대체 시간 원본을 선택합니다.)
  • 가상화 호스트에 사용 가능한 TSC가 있더라도 대상 가상화 호스트에 하드웨어 지원 TSC 크기 조정이 없거나 활용되지 않는 경우 실행 중인 가상 머신의 실시간 마이그레이션으로 인해 게스트가 볼 수 있는 TSC 빈도가 변경될 수 있습니다. (게스트에 대해 이러한 유형의 실시간 마이그레이션이 가능한 경우 하이퍼바이저가 CPUID의 고정 TSC 기능 비트를 지웁니다.)
  • 다중 프로세서 또는 다중 코어 시스템에서 일부 프로세서와 시스템은 각 코어의 클록을 동일한 값으로 동기화할 수 없습니다. (Windows는 자동으로 이를 감지하고 QPC에 대한 대체 시간 원본을 선택합니다.)
  • 일부 대형 다중 프로세서 시스템에서는 프로세서에 고정 TSC가 있더라도 프로세서 클록을 동일한 값으로 동기화하지 못할 수 있습니다. (Windows는 자동으로 이를 감지하고 QPC에 대한 대체 시간 원본을 선택합니다.)
  • 일부 프로세서는 순서대로 명령을 실행합니다. 이렇게 하면 RDTSC 명령이 프로그램에 지정된 것과 다른 시간에 실행될 수 있으므로 RDTSC 를 사용하여 명령 시퀀스를 시간 지정하는 경우 잘못된 주기 수가 발생할 수 있습니다. RDTSCP 명령은 이 문제에 대한 응답으로 일부 프로세서에 도입되었습니다.

다른 타이머와 마찬가지로 TSC는 정확한 주파수를 미리 알 수 없고 빈도 오프셋 오류가 있는 결정 진동기를 기반으로 합니다. 따라서 사용하기 전에 다른 타이밍 참조를 사용하여 보정해야 합니다.

시스템 초기화 중에 Windows는 TSC가 타이밍 목적에 적합한지 확인하고 필요한 빈도 보정 및 코어 동기화를 수행합니다.

PM 클록(x86 및 x64)

PM 클록이라고도 하는 ACPI 타이머는 프로세서 속도와 독립적으로 신뢰할 수 있는 타임스탬프를 제공하기 위해 시스템 아키텍처에 추가되었습니다. 이 타이머의 단일 목표이므로 단일 클록 주기에 타임스탬프를 제공하지만 다른 기능은 제공하지 않습니다.

HPET 타이머(x86 및 x64)

HPET(High Precision Event Timer)는 멀티미디어 및 기타 시간에 민감한 애플리케이션의 타이밍 요구 사항을 충족하기 위해 Intel과 Microsoft가 공동으로 개발했습니다. 프로세서별 리소스인 TSC와 달리 HPET는 플랫폼 전체의 공유 리소스이지만 시스템에는 여러 HPET가 있을 수 있습니다. HPET 지원은 Windows Vista 이후 Windows에서 지원되었으며, Windows 7 및 Windows 8 하드웨어 로고 인증에는 하드웨어 플랫폼에서 HPET 지원이 필요합니다.

제네릭 타이머 시스템 카운터(Arm)

Arm 기반 플랫폼에는 Intel 또는 AMD 기반 플랫폼에 있으므로 TSC, HPET 또는 PM 클록이 없습니다. 대신 Arm 프로세서는 시스템 카운터 레지스터(예: CNTVCT_EL0)를 포함하는 제네릭 타이머(제네릭 간격 타이머 또는 GIT라고도 함)를 제공합니다. 일반 타이머 시스템 카운터는 고정 주파수 플랫폼 전체 시간 원본입니다. 시작 시 0부터 시작하여 높은 속도로 증가합니다. Armv8.6 이상에서는 정확히 1GHz로 정의되지만 초기 부팅 펌웨어에서 설정한 클록 주파수 레지스터를 읽어 결정해야 합니다. 자세한 내용은 "A-프로필 아키텍처에 대한 Arm 아키텍처 참조 설명서"(DDI 0487)의 "AArch64 상태의 일반 타이머" 장을 참조하세요.

주기 카운터(Arm)

Arm 기반 플랫폼은 성능 모니터 주기 카운터 레지스터(예: PMCCNTR_EL0)를 제공합니다. 이 카운터는 프로세서 클록 주기를 계산합니다. 고정되지 않으며 해당 단위는 실시간과 상관 관계가 없을 수 있습니다. 이 레지스터를 사용하여 타임스탬프를 가져오는 것은 권장되지 않습니다.