paint-brush
Konfigurera Prometheus Alertmanager på GPU:er för förbättrad ML-livscykelförbi@danielcrouch
226 avläsningar

Konfigurera Prometheus Alertmanager på GPU:er för förbättrad ML-livscykel

förbi Daniel11m2024/10/12
Read on Terminal Reader

För länge; Att läsa

Mängden och variationen av data driver uppkomsten av komplexa och sofistikerade ML-algoritmer för att hantera AI-arbetsbelastningar.
featured image - Konfigurera Prometheus Alertmanager på GPU:er för förbättrad ML-livscykel
Daniel HackerNoon profile picture
0-item

Mängden och variationen av data driver uppkomsten av komplexa och sofistikerade ML-algoritmer för att hantera AI-arbetsbelastningar. Dessa algoritmer kräver att GPU:er fungerar effektivt och bearbetar datauppsättningar i planetskala för att känna igen mönster. GPU:er är mycket effektiva på att leverera värde och prestanda genom att hantera komplexa beräkningar, vilket gör att deras efterfrågan skjuter i höjden inom ML/AI-domänen.


Trots deras användbarhet är GPU:er mycket dyra. Avancerade AI/ML-arbetsbelastningar kräver robusta observerbarhets- och hanteringsstrategier istället för direkta implementeringar för att öka prestanda och hållbarhet samtidigt som kostnaderna optimeras. Aggregerande mätvärden på GPU-nivå kan hjälpa till att ge exceptionella resultat, vilket förbättrar AI/ML-livscykeln.

Tre aggregeringsbara GPU-mått

Programvaruarbetsflöden består av flera steg som dataladdning, initiering, transformation och dataskrivning. Samma steg gäller för maskininlärningsarbetsbelastningar med komplexa beräkningar. Olika delar av GPU:n används för att möta efterfrågan i varje steg. Det är viktigt för ingenjörsteam att känna till tilldelnings- och användningsmåtten för kontinuerlig utbildning och driftsättning. Detta hjälper till att fatta välgrundade beslut och utnyttja 100 % av resurserna för maximalt värdeutvinning.


Ur maskininlärningssynpunkt används följande GPU-komponenter för arbetsflödesstadier när modellträning initieras. Vi kommer att förstå GPU-komponenterna och mätvärdena de exponerar. Slutligen kommer vi att lära oss hur man fångar och utnyttjar dem från Prometheus alertmanager för att förbättra den övergripande ML-livscykeln.




  1. GPU-minne : Data- och ML-pipelines är starkt beroende av minne. För big data-bearbetning beräknas data i minnet för snabbare resultat. Modellvikterna, gradienterna och andra hyperparametrar/variabler laddas i GPU-minnet. Att hålla reda på minnesanvändningen kan hjälpa till att skala och öka modellens träningshastighet.
  2. GPU-kärnor : När modeller utför matrisintensiva operationer och applicerar framåt-/bakåtpassningar, kommer GPU-kärnor att hantera dessa operationer. Tensorens kärnaktivitetsmått hjälper till att avgöra hur väl hårdvaruenheterna används och har utrymme för förbättringar.
  3. SM-klockfrekvenser : Operationerna som körs på GPU-kärnorna kräver strömmande multiprocessorer (SM) för att utföra önskade matematiska beräkningar. Klockfrekvenserna kan hjälpa till att bestämma beräkningshastigheten.

Fånga GPU-statistik

Att köra bash-skript direkt på GPU:n erbjuder inte Pythons flexibilitet. Vi kan fråga och analysera GPU-statistik under hela utbildningsprocessen för att förstå beteendet. Genom att utnyttja dessa mätvärden kan vi ställa in varningar och åtgärder för att hantera kritiska scenarier.


Med tanke på flexibilitet och utbyggbarhet kommer vi att ställa in Prometheus för att skrapa och utlösa varningar baserat på tröskelvärden och använda Python för att skrapa och logga GPU-statistik.

1. Minnesmått

Förutsatt att GPU är NVIDIA och NVIDIA DCGM Exporter -installationen är klar på din GPU. Vi kommer att definiera Prometheus-konfiguration för att övervaka och skrapa mätvärden baserat på tröskeln och utlösa slack-meddelande om tröskeln överskrider.


Inriktning på GPU:n tillhandahållen i en VPC under subnät 172.28.61.90 och exponerad på port 9400 genom Prometheus-konfigurationer.


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


Med målet definierat kan vi härleda uttrycket för att kontrollera minnesanvändningen varannan minut. När tröskeln överstiger 80 % utlöses en kritisk varning.


 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 }}."


Mätvärdena kan sedan skickas över som varningar. Slack har de enklaste integrationsalternativen för att ställa in varningar. Så med hjälp av YAML-konfigurationen nedan kan vi aktivera varning för grupper eller individuella användarnamn i 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."


Övervakning och varning är användbara och erbjuder begränsade fördelar, som att meddela oss när något är fel. Vi måste fånga måtten för analys och fatta välgrundade beslut.


För det här scenariot kommer vi att överväga DuckDB för datahantering och boto3 för AWS S3-manipulation. Med hjälp av Nvidias hanteringsbibliotek (pynvml) kan vi komma åt och hantera GPU:n genom kod. Vi kommer att skriva måtten till S3 som parkettfiler. För uthållighet kommer vi att skriva loggarna till en databas i minnet med DuckDB och skriva en ögonblicksbild av data till S3 för ad hoc- eller realtidsanalys.


 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. GPU Core Metrics

GPU:er är kända för sina tensorkärnor . Dessa är hårdvaruenheter som kan bearbeta flerdimensionell data. Det är avgörande att förstå hur kärnorna fördelar eller bearbetar lasterna och när de når tröskeln. Vi kan implementera regler för automatisk skalning genom dessa varningar för att hantera arbetsbelastningar och undvika överhettning eller krascher.


I likhet med minnesövervakning kommer vi att ställa in konfigurationer för att övervaka och fånga mätvärden för GPU-kärnanvändning. För varje minut, när kärnanvändningen överstiger 80 %, kommer en kritisk varning att skickas, och för måttlig användning kommer en statusuppdatering att skickas var femte minut.


 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."


Här kommer vi att få enhetens handtagsindex och anropa en metod som returnerar utnyttjandegraden. Svaret loggas sedan in i DuckDB-databasen i minnet och placeras i s3-hinken med den bearbetade tidsstämpeln.


 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. SM Clock Frequency Metrics

Hastigheten med vilken beräkningarna sker är direkt proportionell mot den strömmande multiprocessorklockfrekvensen. SM-klockfrekvensmåttet hjälper till att bestämma hastigheten med vilken tensor- eller ML-beräkningarna triggar och slutförs.


Vi kan göra det möjligt för Prometheus att utlösa varningar när SM-klockfrekvensen överstiger 2000MHz. Vi kan ställa in varningslarm för att få aviseringar när frekvensen närmar sig gränsen.


 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."


Ackumuleringen av SM-klockmått kan enkelt skriptas för att logga mätvärdena i minnesdata och 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)


Genom att utnyttja dessa mätvärden kan ML-ingenjörer veta vad som händer under huven. De kan förbättra utbildningsprocessen genom att analysera mätvärdena och ställa in korrigeringar för högkritiska och prioriterade varningar.

Slutliga tankar

Maskininlärningsmodellutbildning är en komplex och invecklad process. Precis som utan sunda bevis och statistik är det svårt att dra slutsatser om vilka modellvarianter som uppvisar förutsägelser med hög slutledning. Vi behöver GPU-mått för att förstå hur beräkningsinstansen som är ansvarig för att hantera och bearbeta ML-arbetsbelastningarna fungerar. Med tillräckligt med mätvärden och realtidsvarningar kan ML-team sätta upp och effektivisera robusta och hållbara ML-pipelines som förbättrar den övergripande ML-livscykeln.