Przejdź do głównej zawartości

Pomiar opóźnień i PresentMon

Na tej stronie

PCBenchmarkX osobno mierzy wewnętrzne opóźnienie przetwarzania i opóźnienie prezentacji klatki. Te programowe metryki nie opisują całej drogi od kliknięcia myszą do świecenia piksela na ekranie. Pełny cykl pomiarowy opisano w metodyce.

Stały strumień generuje sygnały w deterministycznych odstępach 8-12 ms. Jeśli Windows na to pozwala, tworzy oczekujący timer o wysokiej precyzji; w przeciwnym razie używa zwykłego oczekującego timera. Oczekiwanie na zdarzenie obywa się bez ciągłego odpytywania, które zajmowałoby rdzeń. Globalna rozdzielczość timera systemowego przy tym się nie zmienia.

Dla każdego sygnału logowane są: zaplanowany termin, wybudzenie generatora, faktyczny sygnał, wybudzenie odbiorcy, symulacja, wysłanie poleceń, znaczniki czasu GPU i zdarzenia prezentacji. Wspólny identyfikator klatki wiąże wszystkie etapy.

Termin planowy → wybudzenie generatora → sygnał
↓
wybudzenie odbiorcy
↓
CPU → polecenia → GPU
↓
Present → zdarzenie prezentacji

W tych taśmach osobno widać zarówno spóźnienie timera, jak i opóźnienie wybudzenia odbiorcy. Początek Core Latency to faktyczny sygnał, dlatego krok od terminu planowego do sygnału nie jest w tej metryce liczony.

Wynik zawiera rozbicie zmierzonej drogi latency_path na etapy — osobno dla Baseline i Loaded. Etapy liczone są od faktycznego sygnału:

Etap Co mierzy
signal_to_consumer_wake od sygnału do wybudzenia odbiorcy
cpu_processing przetwarzanie CPU: symulację i przygotowanie danych klatki
cpu_end_to_submit_start pauzę od końca pracy CPU do początku przygotowania wysyłki
workload_submit_cpu_span przygotowanie i zapis poleceń API graficznego
submit_start_to_gpu_begin od początku przygotowania do początku pracy GPU; to nie jest czyste opóźnienie kolejki
gpu_execution samo wykonanie pracy GPU, w taktach GPU
presentation spans prezentację: otoczkę Present oraz odstępy od sygnału i od końca pracy GPU do ScreenTime

Każdy etap podawany jest jako rozkład ze statystykami i percentylami. Segmenty liczone są dla każdej pary znaczników osobno, a nie przez odejmowanie dwóch median. Jeśli końcowy znacznik etapu jest nieobecny lub niewiarygodny, jego rozkład pozostaje pusty — nie ma podstawionych wartości. Spóźnienie timera (rozbieżność terminu planowego i faktycznego sygnału) zapisywane jest jako osobna diagnostyka przed sygnałem i nie wchodzi do sumarycznych wartości drogi.

Czas CPU zapisywany jest przez QueryPerformanceCounter. Dla GPU silnik umieszcza dwa timestamp query wokół mierzonej pracy, pobiera częstotliwość kolejki przez GetTimestampFrequency i przelicza różnicę taktów na milisekundy:

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

Zgodnie z dokumentacją Microsoft dotyczącą D3D12 timing, timestamp query odzwierciedla przejście pracy do końca potoku, a liczniki GPU i CPU są wiązane przez GetClockCalibration.

Para kalibracyjna GPU/QPC pozwala wyrazić zakończenie pracy GPU na tej samej osi czasu co sygnał:

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

Dokładność tego oszacowania w dużej mierze zależy od tego, jak precyzyjnie zestawiono zegary CPU i GPU. Mimo to nie obejmuje ona drogi USB myszy, czasu skanowania matrycy ani reakcji piksela. Microsoft osobno opisuje niuanse wysokoprecyzyjnych znaczników QPC.

Baseline mierzy opóźnienie w minimalnej konfiguracji tego obciążenia. Loaded działa z obciążeniem GPU skalibrowanym na 8,333333 ms, czyli na budżet obliczeniowy około 120 Hz. Fizyczny monitor może mieć inną częstotliwość.

Kalibracja zmienia złożoność wewnątrz shadera w zakresie 1-4096. Liczba przebiegów pozostaje stała: cztery przebiegi końcowe. Najpierw dobierany jest zakres wokół docelowego czasu, następnie jest on doprecyzowywany, a wybrana konfiguracja jest sprawdzana. Aby zająć ten sam czas na szybkiej karcie graficznej, potrzebna jest bardziej złożona praca.

W Performance objętość pracy jest stała. W Loaded Latency obciążenie jest kalibrowane, aby czas pracy GPU był zbliżony na różnych kartach graficznych. Uzyskane znaczniki czasu po pomiarze nie są normalizowane.

Prezentacja klatek testu opóźnienia odbywa się przez osobną ścieżkę prezentacji: okno bezramkowe w trybie flip-discard, maksymalne opóźnienie klatki (maximum frame latency) 1, oczekiwany obiekt DXGI i tearing, jeśli system go obsługuje. Ta ścieżka jest oddzielona od stałego obciążenia wydajności, które wykonuje się poza buforem ekranu i nie wywołuje Present.

Dla zdarzeń prezentacji używana jest biblioteka PresentMon 2.5.1. To projekt ETW do analizy zdarzeń graficznych w Windows, opisany przez jego autorów. Procmon / Process Monitor nie jest stosowany w tym potoku pomiarowym.

PCBenchmarkX uruchamia własną sesję zbierania, wybiera zdarzenia swojego procesu i wiąże klatki z programowymi sygnałami. Nie wymaga to osobnej usługi ani ręcznego uruchamiania osobnego PresentMon.

Zapisywane są dodatkowe odstępy:

  • od sygnału do Present;
  • od Present do ScreenTime;
  • od sygnału do ScreenTime.

ScreenTime to programowe zdarzenie prezentacji klatki; fotodioda do pomiaru światła z ekranu nie jest używana. Metryki prezentacji nie wchodzą do PC Score; co do niego wchodzi, opisano w obliczaniu punktów. Uruchomienie sesji ETW może wymagać uruchomienia jako administrator lub członkostwa w grupie „Użytkownicy dziennika wydajności”. Jeśli nie udało się uruchomić sesji, bloku tej diagnostyki nie będzie, a błąd jest zapisywany w wyniku jawnie. Brak danych nie równa się zerowemu opóźnieniu.

Czas GPU PresentMon jest również przechowywany osobno od własnego czasu D3D12. Twórcy PresentMon zauważają ograniczenia dokładności metryk GPU przy HAGS. Dlatego silnik nie zastępuje własnych GPU timestamps oszacowaniem z ETW.

W PCBenchmarkX opracowano generator sygnałów, dopasowanie etapów klatki, symulację CPU, obciążenia D3D12, kalibrację Loaded, kolejność powtarzających się bloków, zbieranie pomiarów, przetwarzanie statystyczne i model punktów. QPC i D3D12 dostarcza Windows. Do zbierania zdarzeń graficznych przez ETW używany jest otwarty projekt PresentMon.

Informacje techniczne i źródła zewnętrzne zweryfikowano 2026-09-20 dla silnika 0.5.2.