Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Gráficos de chama de perfil da GPU mostram quais funções consomem mais memória da GPU. Este artigo explica como interpretar os grafos de chama gerados pelas ferramentas de criação de perfil de GPU para AKS (Serviço de Kubernetes do Azure).
Important
As funcionalidades em versão preliminar do AKS estão disponíveis de forma optativa e por autoatendimento. As versões prévias são fornecidas “no estado em que se encontram” e “conforme disponíveis” e são excluídas dos contratos de nível de serviço e da garantia limitada. As versões prévias do AKS são parcialmente cobertas pelo suporte ao cliente em uma base de melhor esforço. Dessa forma, esses recursos não são destinados ao uso em produção. Para obter mais informações, consulte os seguintes artigos:
Antes de começar, configure a criação de perfil de GPU e confirme se os dados de criação de perfil estão disponíveis no Pyroscope e no Grafana.
Note
A primeira execução de criação de perfil pode não mostrar todos os símbolos, incluindo símbolos de operações de inicialização, como o carregamento de modelos, enquanto o criador de perfil analisa a carga de trabalho e resolve símbolos. Execute a carga de trabalho novamente após a análise inicial para capturar esses símbolos em perfis subsequentes.
Entender grafos de chama
Um gráfico de chama visualiza pilhas de chamadas com perfil. Cada barra representa uma função e as barras empilhadas mostram a cadeia de chamadas ou qual função chamou outra função. A largura de cada barra representa a quantidade do recurso medido, como tempo de CPU ou memória de GPU alocada, que flui por essa função.
Regra de chave: quanto maior a barra, mais o recurso medido flui por essa função.
Os seguintes gráficos de chama de exemplo foram capturados de uma carga de trabalho de inferência de vLLM.
Tip
Use Expandir todos os grupos no painel do gráfico de chama do Grafana para ver a pilha de chamadas completa sem recolhimento. Use a caixa Pesquisar para localizar funções ou palavras-chave específicas. Para evitar que o painel se recolha novamente, pause a atualização automática do painel definindo o intervalo de atualização como Desativado no canto superior direito do painel do Grafana enquanto você inspeciona o gráfico de chama expandido.
Tip
Use o bloco de foco para focar em um caminho de alocação específico.
Ler os símbolos
Os rótulos de grafo de chama seguem estas convenções:
| Formato de símbolo | Meaning |
|---|---|
Foo > bar |
class Foo: method def bar() |
Foo > __init__ |
Construtor de classe Foo |
bar (sozinho) |
Função independente def bar() |
<interpreter trampoline> |
Sobrecarga de CPython. Você pode ignorar esse símbolo. |
<raw-address>, por exemplo, 0x7f151 |
Código C nativo ou CUDA sem nenhum símbolo de Python disponível. |
Os exemplos incluem:
-
GPUModelRunner/_allocate_kv_cache_tensors: um método em uma classe. Leia este símbolo comoclass GPUModelRunner: def _allocate_kv_cache_tensors(self). -
LlamaMLP/__init__: um construtor chamado ao se criar um objetoLlamaMLP(...). -
_compile_fx_inner: uma função autônoma no nível do módulo que não está dentro de uma classe.
Compreender a alocação própria em comparação com a alocação total
Use os valores Self e Total para determinar onde o recurso é consumido:
- Total é o recurso consumido por uma função e tudo o que ele chama. Uma função pode ter um total elevado, mas não alocar nada por si só, porque faz parte da cadeia de chamadas.
- Self é o recurso consumido diretamente pela função, excluindo suas funções filhas. Um alto auto-valor significa que essa função é onde o recurso é consumido.
Por exemplo, se GPUModelRunner._allocate_kv_cache_tensors tiver 55,1 GB de alocação própria, essa é a função que chama torch.empty() para criar os tensores de cache de chave-valor (KV).
Use as seguintes técnicas de navegação:
- Comece pelos nós folha, que são barras que não têm nada acima. Toda a sua largura corresponde à autoalocação.
- Ignore barras amplas com autoalocação zero ao pesquisar a origem de uma alocação. Essas funções orquestram as chamadas para outras funções.
- Investigue barras amplas com alta autoalocação como possíveis alvos de otimização.
Localizar o maior consumidor de recursos
Use as seguintes etapas para identificar pontos de acesso:
Examine as barras mais largas na parte superior do grafo. Essas funções folha alocam memória. Quanto maior a barra, mais memória ela consome.
Verifique a alocação própria em relação à alocação total. Uma barra larga na parte inferior com
self: 0faz parte da cadeia de chamadas. Siga para cima até encontrar uma barra com alta alocação própria.Leia a pilha de chamadas de baixo para cima para entender por que a função foi chamada. O exemplo a seguir termina com a função que executa a alocação:
<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
Use a tabela a seguir como uma referência rápida:
| Goal | O que procurar |
|---|---|
| Localizar o que aloca mais memória | Barra de folha mais larga no topo da pilha |
| Localizar o que é responsável pela maior parte da memória | Barra mais larga na parte inferior da pilha |
| Identificar destinos de otimização | Barras com ampla autoalocação |
| Identificar funções que você pode ignorar | Barras largas sem alocação própria |