콘텐츠로 이동

지연 측정과 PresentMon

목차

PCBenchmarkX는 내부 처리 지연과 프레임 출력 지연을 별도로 측정합니다. 이러한 소프트웨어 메트릭은 마우스 클릭부터 화면 픽셀이 빛나기까지의 전체 경로를 설명하지 않습니다. 전체 측정 주기는 방법론에 설명되어 있습니다.

지속적인 스트림은 8-12 мс의 결정론적 간격으로 신호를 생성합니다. Windows가 허용하면 고정밀 대기 타이머를 생성하고, 그렇지 않으면 일반 대기 타이머를 사용합니다. 이벤트 대기는 커널을 점유할 연속 폴링 없이 이루어집니다. 이때 시스템 타이머의 전역 해상도는 변경되지 않습니다.

각 신호에 대해 예정된 시각, 생성기 깨우기, 실제 신호, 수신자 깨우기, 시뮬레이션, 명령 전송, GPU 타임스탬프 및 표시 이벤트가 기록됩니다. 공통 프레임 식별자가 모든 단계를 연결합니다.

예정 시각 → 생성기 깨우기 → 신호
↓
수신자 깨우기
↓
CPU → 명령 → GPU
↓
Present → 출력 이벤트

이 타임라인에서는 타이머 지연과 수신자 깨우기 지연이 각각 구분되어 보입니다. Core Latency의 시작은 실제 신호이므로, 이 메트릭에서 예정 시각부터 신호까지의 단계는 계산되지 않습니다.

결과에는 측정된 경로 latency_path의 단계별 분석이 포함됩니다 — Baseline과 Loaded에 대해 각각 별도로. 단계는 실제 신호부터 계산됩니다:

단계 측정 대상
signal_to_consumer_wake 신호부터 수신자 깨우기까지
cpu_processing CPU 처리: 시뮬레이션 및 프레임 데이터 준비
cpu_end_to_submit_start CPU 작업 종료부터 전송 준비 시작까지의 일시 정지
workload_submit_cpu_span 그래픽 API 명령의 준비 및 기록
submit_start_to_gpu_begin 준비 시작부터 GPU 작업 시작까지; 이것은 순수한 큐 지연이 아님
gpu_execution GPU 작업 자체의 실행, GPU 클럭 단위
presentation spans 표시: Present 래퍼 및 신호부터 그리고 GPU 작업 종료부터 ScreenTime까지의 간격

각 단계는 통계와 백분위수를 포함한 분포로 제공됩니다. 세그먼트는 두 중앙값을 빼는 것이 아니라 각 마커 쌍별로 개별 계산됩니다. 단계의 종료 마커가 없거나 신뢰할 수 없는 경우, 해당 분포는 비어 있는 상태로 유지됩니다 — 대체 값은 없습니다. 타이머 지연(예정 시각과 실제 신호의 차이)은 신호 이전의 별도 진단으로 기록되며 경로 합계 값에 포함되지 않습니다.

CPU 시간은 QueryPerformanceCounter를 통해 기록됩니다. GPU의 경우 엔진은 측정 대상 작업 주위에 두 개의 timestamp query를 배치하고, GetTimestampFrequency를 통해 큐 주파수를 얻은 후 틱 차이를 밀리초로 변환합니다:

GPU work, ms = (GPU_end − GPU_begin) × 1000 / GPU_frequency

Microsoft의 D3D12 timing 문서에 따르면, timestamp query는 작업이 파이프라인 끝까지 진행되는 것을 반영하며, GPU 및 CPU 카운터는 GetClockCalibration를 통해 연결됩니다.

GPU/QPC 보정 쌍을 사용하면 GPU 작업 완료를 신호와 동일한 시간 축에서 표현할 수 있습니다:

GPU_completion_QPC = calibration_QPC +
(GPU_end − calibration_GPU) × QPC_frequency / GPU_frequency
Core Latency, ms =
(GPU_completion_QPC − signal_QPC) × 1000 / QPC_frequency

이 추정의 정확도는 CPU와 GPU 시계가 얼마나 정확하게 대응되는지에 크게 좌우됩니다. 이는 여전히 마우스의 USB 경로, 매트릭스 스캔 시간 또는 픽셀 응답을 포함하지 않습니다. Microsoft는 고정밀 QPC 마커의 세부 사항을 별도로 설명합니다.

Baseline은 이 부하의 최소 구성에서 지연을 측정합니다. Loaded는 8,333333 мс로 보정된 GPU 부하, 즉 약 120 Гц의 연산 예산으로 작동합니다. 물리적 모니터는 다른 주파수를 가질 수 있습니다.

보정은 셰이더 내부의 복잡도를 1-4096 범위에서 변경합니다. 패스 수는 고정된 상태로 유지됩니다: 네 번의 포스트패스. 먼저 목표 시간 주변의 범위를 선택한 다음, 이를 정밀화하고 선택된 구성을 검증합니다. 빠른 비디오 카드에서 동일한 시간을 점유하려면 더 복잡한 작업이 필요합니다.

Performance에서는 작업량이 고정됩니다. Loaded Latency에서는 GPU 작업 시간이 서로 다른 비디오 카드에서 비슷하도록 부하가 보정됩니다. 측정 후 얻은 타임스탬프는 정규화되지 않습니다.

지연 테스트의 프레임 출력은 별도의 프레젠테이션 경로를 통해 이루어집니다: flip-discard 모드의 테두리 없는 창, 최대 프레임 지연(maximum frame latency) 1, 대기 가능한 DXGI 객체 및 시스템이 지원하는 경우 tearing. 이 경로는 화면 버퍼 외부에서 실행되며 Present를 호출하지 않는 고정 성능 부하와 분리되어 있습니다.

표시 이벤트에는 PresentMon 2.5.1 라이브러리가 사용됩니다. 이는 Windows의 그래픽 이벤트 분석 ETW 프로젝트로, 저자들이 설명한 것입니다. Procmon / Process Monitor는 이 측정 파이프라인에 사용되지 않습니다.

PCBenchmarkX는 자체 수집 세션을 시작하고, 자체 프로세스의 이벤트를 선택하며, 프레임을 소프트웨어 신호와 연결합니다. 이를 위해 별도의 서비스나 별도의 PresentMon 수동 실행은 필요하지 않습니다.

추가 간격이 저장됩니다:

  • 신호부터 Present까지;
  • Present부터 ScreenTime까지;
  • 신호부터 ScreenTime까지.

ScreenTime는 프레임 표시의 소프트웨어 이벤트입니다; 화면의 빛을 측정하기 위한 포토다이오드는 사용되지 않습니다. 표시 메트릭은 PC Score에 포함되지 않습니다; 무엇이 포함되는지는 점수 계산에 설명되어 있습니다. ETW 세션 시작은 관리자 권한으로 실행하거나 «Пользователи журнала производительности» 그룹의 구성원 자격이 필요할 수 있습니다. 세션을 시작하지 못한 경우 이 진단 블록은 없으며, 실패는 결과에 명시적으로 기록됩니다. 데이터 부재는 0 지연과 같지 않습니다.

PresentMon의 GPU 시간도 자체 D3D12 시간과 별도로 저장됩니다. PresentMon 개발자들은 HAGS에서 GPU 메트릭의 정확도 제한을 언급합니다. 따라서 엔진은 자체 GPU timestamps를 ETW의 추정치로 대체하지 않습니다.

PCBenchmarkX에서는 신호 생성기, 프레임 단계 매핑, CPU 시뮬레이션, D3D12 부하, Loaded 보정, 반복 블록 순서, 측정 수집, 통계 처리 및 점수 모델이 개발되었습니다. QPC와 D3D12는 Windows가 제공합니다. ETW를 통한 그래픽 이벤트 수집에는 오픈 소스 프로젝트 PresentMon이 사용됩니다.

기술 정보 및 외부 출처는 엔진 0.5.2에 대해 2026-09-20에 검증되었습니다.