Analizowanie wykresów płomieniowych profilowania GPU w usłudze Azure Kubernetes Service (AKS) (wersja zapoznawcza)

Wykresy płomieniowe profilowania GPU pokazują, które funkcje zużywają najwięcej pamięci GPU. W tym artykule wyjaśniono, jak interpretować wykresy płomieni generowane przez narzędzia profilowania procesora GPU dla Azure Kubernetes Service (AKS).

Important

Funkcje usługi AKS w wersji zapoznawczej są dostępne na zasadzie samoobsługi i wymagają zapisania się. Wersje zapoznawcze są udostępniane w wersji "as is" i "jako dostępne" i są wykluczone z umów dotyczących poziomu usług i ograniczonej gwarancji. Wersje zapoznawcze usługi AKS są częściowo objęte pomocą techniczną dla klientów, świadczoną w miarę możliwości. W związku z tym te funkcje nie są przeznaczone do użytku produkcyjnego. Aby uzyskać więcej informacji, zobacz następujące artykuły pomocy technicznej:

Przed rozpoczęciem skonfiguruj profilowanie procesora GPU i upewnij się, że dane profilowania są dostępne w piroskopie i narzędziu Grafana.

Uwaga / Notatka

Pierwsze uruchomienie profilowania może nie pokazywać każdego symbolu, w tym symboli z operacji uruchamiania, takich jak ładowanie modelu, podczas gdy profiler analizuje obciążenie i rozpoznaje symbole. Uruchom ponownie obciążenie po początkowej analizie, aby przechwycić te symbole w kolejnych profilach.

Omówienie wykresów płomieni

Wykres płomienia wizualizuje profilowane stosy wywołań. Każdy pasek reprezentuje funkcję, a paski ułożone warstwowo pokazują łańcuch wywołań, czyli to, która funkcja wywołała inną funkcję. Szerokość każdego paska oznacza wielkość mierzonego zasobu, takiego jak czas procesora CPU lub przydzielona pamięć GPU, przepływającego przez tę funkcję.

Kluczowa zasada: im szerszy pasek, tym większa część mierzonego zasobu przepływa przez tę funkcję.

Następujące przykładowe wykresy płomieni są przechwytywane z obciążenia wnioskowania vLLM.

Zrzut ekranu przedstawiający początkowy zwinięty widok wykresu płomieniowego w Grafanie dla obciążenia vLLM, pokazujący ułożone warstwowo słupki reprezentujące stosy wywołań alokacji pamięci GPU.

Tip

Użyj opcji Rozwiń wszystkie grupy na panelu grafu płomieni Grafana, aby wyświetlić pełny stos wywołań bez zwijania. Użyj pola Wyszukiwania , aby znaleźć określone funkcje lub słowa kluczowe. Aby zapobiec ponownemu zwijaniu panelu, wstrzymaj automatyczne odświeżanie pulpitu nawigacyjnego, ustawiając interwał odświeżania na Wyłączone w prawym górnym rogu pulpitu nawigacyjnego narzędzia Grafana podczas inspekcji rozwiniętego wykresu płomienia.

Zrzut ekranu przedstawiający wykres płomieniowy w Grafanie dla obciążenia vLLM po wybraniu pozycji Rozwiń wszystkie grupy, pokazujący pełny stos wywołań z ramkami poszczególnych funkcji dla alokacji pamięci GPU.

Tip

Użyj bloku fokusu , aby skoncentrować się na określonej ścieżce alokacji.

Odczytywanie symboli

Etykiety grafu płomienia są zgodne z następującymi konwencjami:

Format symbolu Meaning
Foo > bar class Foo: method def bar()
Foo > __init__ Konstruktor klasy Foo
bar (sam) Autonomiczna def bar() funkcja
<interpreter trampoline> Obciążenie CPython. Możesz zignorować ten symbol.
<raw-address>, na przykład 0x7f151 Natywny kod C lub CUDA bez dostępnego symbolu Python.

Oto kilka przykładów:

  • GPUModelRunner / _allocate_kv_cache_tensors: Jest to metoda w klasie. Przeczytaj ten symbol jako class GPUModelRunner: def _allocate_kv_cache_tensors(self).
  • LlamaMLP / __init__: konstruktor wywoływany podczas tworzenia LlamaMLP(...) obiektu.
  • _compile_fx_inner: autonomiczna funkcja na poziomie modułu, która nie znajduje się w klasie.

Poznaj alokację własną a całkowitą

Użyj wartości Self i Total , aby określić, gdzie jest używany zasób:

  • Łącznie to zużycie zasobów przez funkcję oraz wszystkie funkcje przez nią wywoływane. Funkcja może mieć dużą sumę, ale nie przydzielić jej nic, ponieważ jest częścią łańcucha wywołań.
  • Self to zasoby zużywane bezpośrednio przez funkcję, z wyłączeniem jej funkcji podrzędnych. Wysoka wartość własna oznacza, że to w tej funkcji zasób jest zużywany.

Na przykład, jeśli GPUModelRunner._allocate_kv_cache_tensors ma 55,1 GB własnej alokacji, jest to funkcja, która wywołuje torch.empty(), aby utworzyć tensory pamięci podręcznej klucz–wartość (KV).

Użyj następujących technik nawigacji:

  • Zacznij od węzłów liścia, które są słupkami z niczym powyżej nich. Cała ich szerokość oznacza własny przydział.
  • Pomiń szerokie słupki z zerową alokacją własną podczas wyszukiwania źródła alokacji. Te funkcje organizują wywołania do innych funkcji.
  • Zbadaj szerokie paski z wysoką alokacją własną jako potencjalne cele optymalizacji.

Znajdź największego konsumenta zasobów

Aby zidentyfikować hotspoty, wykonaj następujące czynności:

  1. Spójrz na najszersze słupki w górnej części wykresu. Te funkcje liścia przydzielają pamięć. Im szerszy pasek, tym więcej pamięci zużywa.

  2. Sprawdź alokację własną w porównaniu z całkowitą alokacją. Szeroki pasek u dołu z self: 0 jest częścią łańcucha wywołań. Podążaj za nim w górę, aż znajdziesz pasek z wysoką alokacją własną.

  3. Przeczytaj stos wywołań od dołu do góry, aby dowiedzieć się, dlaczego funkcja została wywołana. Poniższy przykład kończy się funkcją, która wykonuje alokację:

    <raw-address>, for example, 0x7f151       -> native code entry
    <interpreter trampoline>                 -> CPython dispatch
    <module>                                 -> script top level
    EngineCoreProc.run_engine_core           -> vLLM engine startup
    EngineCore.__init__                      -> engine initialization
    EngineCore._initialize_kv_caches         -> KV cache setup
    Worker.initialize_from_config            -> worker setup
    GPUModelRunner.initialize_kv_cache       -> model runner
    GPUModelRunner._allocate_kv_cache_tensors -> actual allocation
    

Skorzystaj z poniższej tabeli jako z szybkiego odniesienia:

Goal Czego szukać
Znajdź, co przydziela najwięcej pamięci Najszer­szy pasek liścia na górze stosu
Znajdowanie elementów odpowiedzialnych za największą ilość pamięci Najszer­szy słupek na dole stosu
Identyfikowanie celów optymalizacji Paski z szerokim samoprzydziałem
Identyfikowanie funkcji, które można pominąć Szerokie słupki z zerową alokacją własną

Następne kroki