paint-brush
Configuración de Prometheus Alertmanager en GPU para mejorar el ciclo de vida del aprendizaje automáticopor@danielcrouch
251 lecturas

Configuración de Prometheus Alertmanager en GPU para mejorar el ciclo de vida del aprendizaje automático

por Daniel11m2024/10/12
Read on Terminal Reader

Demasiado Largo; Para Leer

La cantidad y variedad de datos impulsan el surgimiento de algoritmos de aprendizaje automático complejos y sofisticados para gestionar cargas de trabajo de IA.
featured image - Configuración de Prometheus Alertmanager en GPU para mejorar el ciclo de vida del aprendizaje automático
Daniel HackerNoon profile picture
0-item

La cantidad y variedad de datos impulsan el surgimiento de algoritmos de aprendizaje automático complejos y sofisticados para manejar cargas de trabajo de IA. Estos algoritmos requieren que las GPU funcionen de manera eficiente y procesen conjuntos de datos a escala planetaria para reconocer patrones. Las GPU son muy eficaces a la hora de ofrecer valor y rendimiento al manejar cálculos complejos, lo que hace que su demanda se dispare en el dominio del aprendizaje automático y la IA.


A pesar de su utilidad, las GPU son muy caras. Las cargas de trabajo de IA/ML avanzadas requieren estrategias de gestión y observabilidad sólidas en lugar de implementaciones directas para aumentar el rendimiento y la durabilidad, al tiempo que se optimizan los costos. La agregación de métricas a nivel de GPU puede ayudar a obtener resultados excepcionales, mejorando el ciclo de vida de la IA/ML.

Tres métricas de GPU agregables

Los flujos de trabajo de software constan de varias etapas, como la carga de datos, la inicialización, la transformación y la escritura de datos. Las mismas etapas se aplican a las cargas de trabajo de aprendizaje automático con cálculos complejos. Se utilizan diferentes partes de la GPU para satisfacer la demanda en cada etapa. Es importante que los equipos de ingeniería conozcan las métricas de asignación y utilización para la capacitación y las implementaciones continuas. Esto ayuda a tomar decisiones informadas y a aprovechar el 100 % de los recursos para obtener el máximo valor.


Desde el punto de vista del aprendizaje automático, los siguientes componentes de la GPU se utilizan para las etapas del flujo de trabajo cuando se inicia el entrenamiento del modelo. Comprenderemos los componentes de la GPU y las métricas que exponen. Por último, aprenderemos a capturarlos y aprovecharlos desde el administrador de alertas de Prometheus para mejorar el ciclo de vida general del aprendizaje automático.




  1. Memoria de GPU : los flujos de trabajo de datos y ML dependen en gran medida de la memoria. Para el procesamiento de big data, los datos se calculan en la memoria para obtener resultados más rápidos. Los pesos del modelo, los gradientes y otros hiperparámetros/variables se cargan en la memoria de la GPU. Realizar un seguimiento del uso de la memoria puede ayudar a escalar y aumentar la velocidad de entrenamiento del modelo.
  2. Núcleos de GPU : cuando los modelos realizan operaciones con uso intensivo de la matriz y aplican pases hacia adelante y hacia atrás, los núcleos de GPU se encargarán de estas operaciones. Las métricas de actividad del núcleo tensorial ayudan a determinar qué tan bien se utilizan las unidades de hardware y si tienen margen de mejora.
  3. Frecuencias de reloj del SM : las operaciones que se ejecutan en los núcleos de la GPU requieren multiprocesadores de transmisión (SM) para realizar los cálculos matemáticos deseados. Las frecuencias de reloj pueden ayudar a determinar la velocidad computacional.

Captura de métricas de GPU

La ejecución de scripts bash directamente en la GPU no ofrece la flexibilidad de Python. Podemos consultar y analizar las métricas de la GPU durante todo el proceso de entrenamiento para comprender el comportamiento. Al aprovechar estas métricas, podemos configurar alertas y soluciones para manejar situaciones críticas.


Teniendo en cuenta la flexibilidad y la extensibilidad, configuraremos Prometheus para extraer y activar alertas según el umbral y usaremos Python para extraer y registrar métricas de GPU.

1. Métricas de memoria

Suponiendo que la GPU es NVIDIA y que la configuración del exportador NVIDIA DCGM está completa en su GPU, definiremos la configuración de Prometheus para monitorear y extraer métricas en función del umbral y activar la notificación de Slack si se excede el umbral.


Apunta a la GPU aprovisionada en una VPC bajo la subred 172.28.61.90 y expuesta en el puerto 9400 a través de configuraciones de Prometheus.


 configs_scrapper: - job_name: 'nvidia_gpu_metrics_scrapper' static_configs: - targets: ['172.28.61.90:9400']


Con el objetivo definido, podemos derivar la expresión para comprobar el uso de la memoria cada dos minutos. Cuando el umbral supera el 80%, se activa una alerta crítica.


 groups: -name: GPU_Memory_Alerts rules: - alert: HighGPUMemoryUsage expr: (dcgm_gpu_mem_used / dcgm_gpu_mem_total) * 100 > 80 for: 2m   labels: severity: critical   annotations:summary: "GPU Memory usage is high on {{ $labels.instance }}" description: "GPU memory utilization is over 80% from more than 2 minutes on {{ $labels.instance }}."


Las métricas se pueden enviar como alertas. Slack tiene las opciones de integración más sencillas para configurar alertas. Por lo tanto, con la siguiente configuración YAML, podemos habilitar las alertas para grupos o nombres de usuario individuales en Slack.


 global: resolve_timeout: 2m route: receiver: 'slack_memory_notifications' group_wait: 5s group_interval: 2m repeat_interval: 1h receivers: - name: 'slack_memory_notifications' slack_configs: - api_url: 'https://databracket.slack.com/services/shrad/webhook/url' channel: 'databracket' username: 'Prometheus_Alertmanager' send_resolved: true title: 'GPU Memory Utilization >80% Alert' text: "A high memory utilization was observed triggering alert on GPU."


El monitoreo y las alertas son útiles y ofrecen beneficios limitados, como notificarnos cuando algo está mal. Necesitamos capturar las métricas para analizarlas y tomar decisiones informadas.


Para este escenario, consideraremos DuckDB para la gestión de datos y boto3 para la manipulación de AWS S3. Con la biblioteca de gestión de Nvidia (pynvml), podemos acceder y gestionar la GPU a través del código. Escribiremos las métricas en S3 como archivos parquet. Para la persistencia, escribiremos los registros en una base de datos en memoria utilizando DuckDB y escribiremos una instantánea de los datos en S3 para un análisis ad hoc o en tiempo real.


 import time import pynvml import duckdb import boto3 import osfrom datetime import datetime pynvml.nvmlInit() s3 = boto3.client('s3') con = duckdb.connect(database=':memory:') con.execute(''' CREATE TABLE gpu_memory_usage ( Timestamp VARCHAR, Overall_memory DOUBLE, Memory_in_use DOUBLE, Available_memory DOUBLE ) ''') def get_gpu_memory_info(gpu_id=0): handle = pynvml.nvmlDeviceGetHandleByIndex(gpu_id) memory_info = pynvml.nvmlDeviceGetMemoryInfo(handle) return { "Overall_memory": memory_info.total / (1024 ** 2), "Memory_in_use": memory_info.used / (1024 ** 2), "Available_memory": memory_info.free / (1024 ** 2) } def upload_parquet_to_s3(bucket_name, object_name, file_path): try: s3.upload_file(file_path, bucket_name, object_name) print(f"Parquet file uploaded to S3: {object_name}") except Exception as e: print(f"Failed to upload Parquet to S3: {e}") def log_memory_utilization_to_parquet(bucket_name, filename, gpu_id=0, interval=1.0, local_file_path='gpu_memory_stats.parquet'): try: while True: gpu_memory_info = get_gpu_memory_info(gpu_id) timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') con.execute(''' INSERT INTO gpu_memory_usage VALUES (?, ?, ?, ?) ''', (timestamp, gpu_memory_info['Overall_memory'], gpu_memory_info['Memory_in_use'], gpu_memory_info['Available_memory'])) print(f"Logged at {timestamp}: {gpu_memory_info}") if int(datetime.now().strftime('%S')) %60 == 0: # Upload Every Minute object_name = f"{filename}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.parquet" upload_parquet_to_s3(bucket_name, object_name, local_file_path) time.sleep(interval) except KeyboardInterrupt: print("Logging stopped by user.") bucket_name = 'prometheus-alerts-cof' filename = 'gpu_memory_stats' log_memory_utilization_to_parquet(bucket_name, filename, gpu_id=0, interval=2.0)


2. Métricas del núcleo de la GPU

Las GPU son famosas por sus núcleos tensoriales . Se trata de unidades de hardware que pueden procesar datos multidimensionales. Es fundamental comprender cómo distribuyen o procesan los núcleos las cargas y cuándo alcanzan el umbral. Podemos implementar reglas de escalado automático a través de estas alertas para gestionar las cargas de trabajo y evitar el sobrecalentamiento o las fallas.


De manera similar a la supervisión de la memoria, configuraremos configuraciones para supervisar y capturar métricas de utilización del núcleo de la GPU. Cada minuto, cuando la utilización del núcleo supere el 80 %, se enviará una alerta crítica y, en caso de utilización moderada, se enviará una actualización de estado cada cinco minutos.


 groups: - name: gpu_alerts rules: - alert: HighGPUCoreUtilization expr: gpu_core_utilization > 80 for: 1m labels: severity: critical annotations: summary: "GPU Core Utilization >80% Alert" description: "GPU core utilization is above 80% for over 1 minute." - alert: MediumGPUCoreUtilization expr: gpu_core_utilization > 50 for: 5m labels: severity: warning annotations: summary: "GPU Memory Utilization = Moderate" description: "GPU core utilization is above 50% for over 5 minutes."


Aquí, obtendremos el índice del identificador del dispositivo y llamaremos a un método que devuelve las tasas de utilización. Luego, la respuesta se registra en la base de datos DuckDB en memoria y se coloca en el depósito s3 con la marca de tiempo procesada.


 con.execute(''' CREATE TABLE gpu_core_usage ( Timestamp VARCHAR, GPU_Utilization_Percentage DOUBLE ) ''') def get_gpu_utilization(gpu_id=0): """Returns the GPU utilization percentage.""" handle = pynvml.nvmlDeviceGetHandleByIndex(gpu_id) utilization = pynvml.nvmlDeviceGetUtilizationRates(handle) return utilization.gpu def log_gpu_utilization_to_parquet(bucket_name, filename, gpu_id=0, interval=1.0, local_file_path='gpu_core_stats.parquet'): """Logs GPU utilization to a Parquet file and uploads it to S3 periodically.""" try: while True: gpu_utilization = get_gpu_utilization(gpu_id) timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') con.execute(''' INSERT INTO gpu_core_usage VALUES (?, ?) ''', (timestamp, gpu_utilization)) print(f"Logged at {timestamp}: GPU Utilization = {gpu_utilization}%") if int(datetime.now().strftime('%S')) % 60 == 0: con.execute(f"COPY gpu_core_usage TO '{local_file_path}' (FORMAT PARQUET)") object_name = f"{filename}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.parquet" upload_parquet_to_s3(bucket_name, object_name, local_file_path) con.execute("DELETE FROM gpu_core_usage") time.sleep(interval) except KeyboardInterrupt: print("Logging stopped by user.") # Example usage: bucket_name = 'prometheus-alerts-cof' filename = 'gpu_core_stats' log_gpu_utilization_to_parquet(bucket_name, filename, gpu_id=0, interval=2.0)

3. Métricas de frecuencia de reloj SM

La velocidad a la que se realizan los cálculos es directamente proporcional a la frecuencia de reloj del multiprocesador de transmisión. La métrica de frecuencia de reloj del multiprocesador ayuda a determinar la velocidad a la que se activan y completan los cálculos del tensor o del ML.


Podemos habilitar Prometheus para que active alertas cuando la frecuencia del reloj SM supere los 2000 MHz. Podemos configurar alertas de advertencia para recibir notificaciones cuando la frecuencia se acerque al límite.


 groups: - name: gpu_sm_clock_alerts rules: - alert: LowSMClockFrequency expr: gpu_sm_clock_frequency >= 1000 for: 1m labels: severity: warning annotations: summary: "Low SM Clock Frequency" description: "The SM clock frequency is below 500 MHz for over 1 minute." - alert: HighSMClockFrequency expr: gpu_sm_clock_frequency > 2000 for: 1m labels: severity: critical annotations: summary: "High SM Clock Frequency" description: "The SM clock frequency is above 2000 MHz for over 1 minute."


La acumulación de métricas de reloj SM se puede programar fácilmente para registrar las métricas en datos en memoria y S3.


 con.execute(''' CREATE TABLE sm_clock_usage ( Timestamp VARCHAR, SM_Clock_Frequency_MHz INT ) ''') def get_sm_clock_frequency(gpu_id=0): handle = pynvml.nvmlDeviceGetHandleByIndex(gpu_id) sm_clock = pynvml.nvmlDeviceGetClockInfo(handle, pynvml.NVML_CLOCK_SM) return sm_clock def log_sm_clock_to_parquet(bucket_name, filename, gpu_id=0, interval=1.0, local_file_path='sm_clock_stats.parquet'): try: while True: sm_clock_frequency = get_sm_clock_frequency(gpu_id) timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S') con.execute(''' INSERT INTO sm_clock_usage VALUES (?, ?) ''', (timestamp, sm_clock_frequency)) print(f"Logged at {timestamp}: SM Clock Frequency = {sm_clock_frequency} MHz") if int(datetime.now().strftime('%S')) % 10 == 0: con.execute(f"COPY sm_clock_usage TO '{local_file_path}' (FORMAT PARQUET)") object_name = f"{filename}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.parquet" upload_parquet_to_s3(bucket_name, object_name, local_file_path) con.execute("DELETE FROM sm_clock_usage") time.sleep(interval) except KeyboardInterrupt: print("Logging stopped by user.") bucket_name = 'prometheus-alerts-cof' filename = 'sm_clock_stats' log_sm_clock_to_parquet(bucket_name, filename, gpu_id=0, interval=2.0)


Al aprovechar estas métricas, los ingenieros de ML pueden saber qué está sucediendo en segundo plano. Pueden mejorar el proceso de capacitación analizando las métricas y configurando soluciones para alertas de alta criticidad y prioridad.

Reflexiones finales

El entrenamiento de modelos de aprendizaje automático es un proceso complejo y enrevesado. Al igual que sin evidencia sólida y estadísticas, es difícil concluir qué variantes del modelo exhiben predicciones con alta inferencia. Necesitamos métricas de GPU para comprender cómo está operando la instancia de cómputo responsable de manejar y procesar las cargas de trabajo de ML. Con suficientes métricas y alertas en tiempo real, los equipos de ML pueden configurar y optimizar procesos de ML robustos y duraderos que mejoren el ciclo de vida general de ML.