Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Los gráficos de llama de perfilado de GPU muestran qué funciones consumen más memoria de GPU. En este artículo se explica cómo interpretar los gráficos de llama generados por las herramientas de generación de perfiles de GPU para Azure Kubernetes Service (AKS).
Important
Las características en versión preliminar de AKS están disponibles en modalidad de autoservicio y previa suscripción. Las versiones preliminares se proporcionan "tal cual" y "como están disponibles", y están excluidas de los Acuerdos de nivel de servicio y la garantía limitada. Las versiones preliminares de AKS cuentan con soporte parcial por parte del servicio al cliente en la medida de lo posible. Por lo tanto, estas características no están diseñadas para su uso en producción. Para más información, consulte los siguientes artículos de soporte:
Antes de empezar, configure la generación de perfiles de GPU y confirme que los datos de generación de perfiles están disponibles en Pyroscope y Grafana.
Note
Es posible que la primera ejecución de generación de perfiles no muestre todos los símbolos, incluidos los símbolos de las operaciones de inicio, como la carga de modelos, mientras que el generador de perfiles analiza la carga de trabajo y resuelve los símbolos. Vuelva a ejecutar la carga de trabajo después del análisis inicial para capturar estos símbolos en perfiles posteriores.
Comprender los gráficos de llama
Un gráfico de llama muestra pilas de llamadas perfiladas. Cada barra representa una función y las barras apiladas muestran la cadena de llamadas o qué función llamó a otra función. El ancho de cada barra representa la cantidad del recurso medido, como el tiempo de CPU o la memoria de GPU asignada, que fluye a través de esa función.
Regla clave: cuanto más ancha sea una barra, mayor será la cantidad del recurso medido que fluye a través de esa función.
Los siguientes gráficos de llama de ejemplo se han obtenido a partir de una carga de trabajo de inferencia de vLLM.
Tip
Use Expandir todos los grupos en el panel del gráfico de llamas de Grafana para ver la pila de llamadas completa sin contraerse. Use el cuadro Buscar para buscar funciones o palabras clave específicas. Para evitar que el panel vuelva a contraerse, detén la actualización automática del panel de control estableciendo el intervalo de actualización en Desactivado en la esquina superior derecha del panel de control de Grafana mientras examinas el gráfico de llama expandido.
Tip
Usa Focus block para centrarte en una ruta de asignación específica.
Leer los símbolos
Las etiquetas de gráfico de llama siguen estas convenciones:
| Formato de símbolo | Meaning |
|---|---|
Foo > bar |
class Foo: method def bar() |
Foo > __init__ |
Constructor de clase Foo |
bar (solo) |
Función independiente def bar() |
<interpreter trampoline> |
Sobrecarga de CPython. Puede omitir este símbolo. |
<raw-address>, por ejemplo, 0x7f151 |
Código nativo de C o CUDA sin ningún símbolo de Python disponible. |
Algunos ejemplos son:
-
GPUModelRunner/_allocate_kv_cache_tensors: un método en una clase. Lea este símbolo comoclass GPUModelRunner: def _allocate_kv_cache_tensors(self). -
LlamaMLP/__init__: Un constructor que se llama al crear un objetoLlamaMLP(...). -
_compile_fx_inner: función de nivel de módulo independiente que no está dentro de una clase.
Comprender la asignación propia frente a la asignación total
Use los valores Self y Total para determinar dónde se consume el recurso:
- Total es el recurso consumido por una función y todo lo que esta invoca. Una función puede tener un total elevado pero no asignar nada por sí misma porque forma parte de la cadena de llamadas.
- Self es el recurso consumido directamente por la función, excluyendo sus funciones secundarias. Un valor self alto indica que en esta función se consume el recurso.
Por ejemplo, si GPUModelRunner._allocate_kv_cache_tensors tiene 55,1 GB de autoasignación, se trata de la función que invoca a torch.empty() para crear los tensores de la caché de clave-valor (KV).
Use las siguientes técnicas de navegación:
- Empiece por los nodos hoja, que son barras que no tienen nada encima. Todo su ancho representa la autoasignación.
- Omite las barras anchas con autoasignación nula cuando busques el origen de una asignación. Estas funciones orquestan llamadas a otras funciones.
- Investigue las barras anchas con una alta autoasignación como posibles objetivos de optimización.
Encuentra el recurso que más consume
Siga estos pasos para identificar zonas activas:
Examine las barras más anchas en la parte superior del gráfico. Estas funciones hoja asignan memoria. Cuanto más ancho sea la barra, más memoria consume.
Compare la asignación propia con la asignación total. Una barra ancha en la parte inferior con
self: 0forma parte de la cadena de llamadas. Sígala hacia arriba hasta que encontrar una barra con una autoasignación alta.Lea la pila de llamadas de abajo a arriba para comprender por qué se llamó a la función. En el ejemplo siguiente se termina con la función que realiza la asignación:
<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 la tabla siguiente como referencia rápida:
| Goal | Qué se debe tener presente |
|---|---|
| Descubra qué es lo que más memoria asigna | La barra de hoja más ancha en la parte superior de la pila |
| Descubre qué consume más memoria | La barra más ancha en la parte inferior de la pila |
| Identificación de los destinos de optimización | Barras con una amplia autoasignación |
| Identificar funciones que puede omitir | Barras anchas con autoasignación nula |