Analysera flame graphs för GPU-profilering på Azure Kubernetes Service (AKS) (förhandsversion)

Flamdiagram för GPU-profilering visar vilka funktioner som använder mest GPU-minne. Den här artikeln beskriver hur du tolkar flamdiagram som genereras av GPU-profileringsverktygen för Azure Kubernetes Service (AKS).

Important

AKS-förhandsversionsfunktioner är tillgängliga via självbetjäning och frivillig registrering. Förhandsversioner tillhandahålls "i befintligt skick" och "i mån av tillgång," och de är undantagna från servicenivåavtal och begränsad garanti. AKS-förhandsversioner stöds delvis av kundsupport efter bästa förmåga. Därför är dessa funktioner inte avsedda för produktionsanvändning. Mer information finns i följande supportartiklar:

Innan du börjar konfigurerar du GPU-profilering och bekräftar att profileringsdata är tillgängliga i Pyroscope och Grafana.

Note

Den första profileringskörningen kanske inte visar alla symboler, inklusive symboler från startåtgärder som modellinläsning, medan profileraren analyserar arbetsbelastningen och löser symboler. Kör arbetsbelastningen igen efter den första analysen för att samla in dessa symboler i efterföljande profiler.

Förstå flamdiagram

Ett flamdiagram visualiserar profilerade anropsstackar. Varje stapel representerar en funktion, och de staplade staplarna visar anropskedjan eller vilken funktion som kallas en annan funktion. Bredden på varje stapel representerar mängden av den uppmätta resursen, till exempel CPU-tid eller allokerat GPU-minne, som flödar genom den funktionen.

Grundregel: Ju bredare en stapel är, desto mer av den uppmätta resursen flödar genom den funktionen.

Följande exempel på flamdiagram har tagits från en inferensarbetsbelastning i vLLM.

Skärmbild av den första komprimerade flamdiagramvyn i Grafana för en vLLM-arbetsbelastning som visar staplade staplar som representerar GPU-minnesallokeringsanropsstackar.

Tip

Använd Expandera alla grupper i panelen för flame graph i Grafana för att se hela anropsstacken utan att den fälls ihop. Använd sökrutan för att hitta specifika funktioner eller nyckelord. Om du vill förhindra att panelen kollapsar igen pausar du den automatiska uppdateringen av instrumentpanelen genom att ställa in uppdateringsintervallet på Av i det övre högra hörnet på Grafana-instrumentpanelen medan du inspekterar det expanderade flamdiagrammet.

Skärmbild av flamdiagrammet i Grafana för en vLLM-arbetsbelastning när du har valt Expandera alla grupper, som visar den fullständiga anropsstacken med enskilda funktionsramar för GPU-minnesallokeringar.

Tip

Använd Fokusblock för att fokusera på en specifik allokeringssökväg.

Läs symbolerna

Flamdiagrametiketter följer dessa konventioner:

Symbolformat Meaning
Foo > bar class Foo: method def bar()
Foo > __init__ Konstruktor av klass Foo
bar (ensam) Fristående def bar() funktion
<interpreter trampoline> CPython-omkostnad. Du kan ignorera den här symbolen.
<raw-address>, till exempel 0x7f151 Inbyggd C- eller CUDA-kod utan Python symbol tillgänglig.

Exempel inkluderar:

  • GPUModelRunner / _allocate_kv_cache_tensors: En metod för en klass. Läs den här symbolen som class GPUModelRunner: def _allocate_kv_cache_tensors(self).
  • LlamaMLP / __init__: En konstruktor som anropas när ett LlamaMLP(...) objekt skapas.
  • _compile_fx_inner: En fristående funktion på modulnivå som inte finns i en klass.

Förstå egen kontra total allokering

Använd värdena Self och Total för att avgöra var resursen används:

  • Total är den resurs som används av en funktion och allt den anropar. En funktion kan ha en stor summa men allokera ingenting i sig eftersom den är en del av anropskedjan.
  • Self avser de resurser som förbrukas direkt av funktionen, exklusive dess underfunktioner. Ett högt självvärde innebär att den här funktionen är där resursen används.

Om till exempel GPUModelRunner._allocate_kv_cache_tensors har 55,1 GB egen allokering är det den funktion som anropar torch.empty() för att skapa nyckelvärdescachetensorerna (KV).

Använd följande navigeringstekniker:

  • Börja med bladnoder, som är staplar som inte har något ovanför sig. Hela bredden representerar självallokering.
  • Hoppa över breda staplar utan självallokering när du söker efter källan för en allokering. Dessa funktioner dirigerar anrop till andra funktioner.
  • Undersök breda staplar med hög egenallokering som möjliga kandidater för optimering.

Hitta den största resurskonsumenten

Använd följande steg för att identifiera hotspots:

  1. Titta på de bredaste staplarna överst i diagrammet. Dessa bladfunktioner allokerar minne. Ju bredare stapeln är, desto mer minne förbrukas.

  2. Kontrollera egen allokering jämfört med total allokering. Ett brett fält längst ner med self: 0 är en del av anropskedjan. Följ den uppåt tills du hittar en stapel med hög egenallokering.

  3. Läs anropsstacken nedifrån och upp för att förstå varför funktionen anropades. Följande exempel slutar med funktionen som utför allokeringen:

    <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
    

Använd följande tabell som snabbreferens:

Mål Vad du ska leta efter
Hitta det som allokerar mest minne Bredaste lövstapeln överst i stacken
Hitta det som är ansvarigt för mest minne Bredaste stapeln längst ned i stacken
Identifiera optimeringsmål Staplar med bred egen tilldelning
Identifiera funktioner som du kan hoppa över Breda staplar utan egen allokering

Nästa steg