Hoeveelheid en verscheidenheid aan data voeden de opkomst van complexe en geavanceerde ML-algoritmen om AI-werklasten te verwerken. Deze algoritmen vereisen dat GPU's efficiënt werken en datasets op wereldschaal verwerken om patronen te herkennen. GPU's zijn zeer effectief in het leveren van waarde en prestaties door complexe berekeningen te verwerken, waardoor hun vraag in het ML/AI-domein omhoog schiet.
Ondanks hun bruikbaarheid zijn GPU's erg duur. Geavanceerde AI/ML-workloads vereisen robuuste observatie- en beheerstrategieën in plaats van directe implementaties om de prestaties en duurzaamheid te verbeteren en tegelijkertijd de kosten te optimaliseren. Het aggregeren van GPU-niveau-metrieken kan helpen uitzonderlijke resultaten te leveren, waardoor de AI/ML-levenscyclus wordt verbeterd.
Softwareworkflows bestaan uit meerdere fasen, zoals het laden van gegevens, initialisatie, transformatie en het schrijven van gegevens. Dezelfde fasen zijn van toepassing op machine learning-workloads met complexe berekeningen. Verschillende delen van de GPU worden gebruikt om in elke fase aan de vraag te voldoen. Het is belangrijk dat engineeringteams de toewijzings- en gebruiksstatistieken kennen voor continue training en implementaties. Dit helpt bij het nemen van weloverwogen beslissingen en het benutten van 100% van de resources voor maximale waarde-extractie.
Vanuit een machine learning-standpunt worden de volgende GPU-componenten gebruikt voor workflowfasen wanneer modeltraining wordt gestart. We zullen de GPU-componenten en de statistieken die ze blootleggen, begrijpen. Tot slot zullen we leren hoe we ze kunnen vastleggen en gebruiken vanuit de Prometheus alertmanager om de algehele ML-levenscyclus te verbeteren.
Het direct uitvoeren van bash-scripts op de GPU biedt niet de flexibiliteit van Python. We kunnen GPU-metrieken opvragen en analyseren tijdens het trainingsproces om het gedrag te begrijpen. Door deze metrieken te benutten, kunnen we waarschuwingen en herstelmaatregelen instellen om kritieke scenario's aan te pakken.
Met het oog op flexibiliteit en uitbreidbaarheid stellen we Prometheus in om meldingen te verzamelen en activeren op basis van drempelwaarden. Daarnaast gebruiken we Python om GPU-statistieken te verzamelen en te loggen.
Ervan uitgaande dat de GPU NVIDIA is en de NVIDIA DCGM Exporter -installatie op uw GPU is voltooid. We definiëren Prometheus-configuratie om metrische gegevens te monitoren en te schrapen op basis van de drempelwaarde en Slack-melding te activeren als de drempelwaarde wordt overschreden.
Gericht op de GPU die is ingericht in een VPC onder subnet 172.28.61.90 en via Prometheus-configuraties op poort 9400 is blootgesteld.
configs_scrapper: - job_name: 'nvidia_gpu_metrics_scrapper' static_configs: - targets: ['172.28.61.90:9400']
Met het gedefinieerde doel kunnen we de expressie afleiden om het geheugengebruik elke twee minuten te controleren. Wanneer de drempelwaarde 80% overschrijdt, wordt een kritieke waarschuwing geactiveerd.
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 }}."
De statistieken kunnen vervolgens als waarschuwingen worden verzonden. Slack heeft de eenvoudigste integratieopties voor het instellen van waarschuwingen. Dus met behulp van de onderstaande YAML-configuratie kunnen we waarschuwingen inschakelen voor groepen of individuele gebruikersnamen in 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."
Monitoring en alerting zijn nuttig en bieden beperkte voordelen, zoals ons waarschuwen wanneer er iets mis is. We moeten de statistieken vastleggen voor analyse en weloverwogen beslissingen nemen.
Voor dit scenario zullen we DuckDB overwegen voor databeheer en boto3 voor AWS S3-manipulatie. Met behulp van de Nvidia-beheerbibliotheek (pynvml) kunnen we de GPU benaderen en beheren via code. We zullen de metrische gegevens naar S3 schrijven als parketbestanden. Voor persistentie zullen we de logs naar een in-memory database schrijven met behulp van DuckDB en een momentopname van de gegevens naar S3 schrijven voor ad-hoc- of realtime-analyse.
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)
GPU's staan bekend om hun tensorcores . Dit zijn hardware-eenheden die multidimensionale data kunnen verwerken. Het is cruciaal om te begrijpen hoe de cores de ladingen verdelen of verwerken en wanneer ze de drempel bereiken. We kunnen auto-scalingregels implementeren via deze waarschuwingen om workloads te verwerken en oververhitting of crashes te voorkomen.
Vergelijkbaar met geheugenbewaking, zullen we configuraties instellen om GPU-coregebruiksstatistieken te bewaken en vast te leggen. Voor elke minuut, wanneer het coregebruik 80% overschrijdt, wordt een kritieke waarschuwing verzonden, en voor matig gebruik wordt elke vijf minuten een statusupdate verzonden.
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."
Hier halen we de apparaathandle-index op en roepen we een methode aan die gebruikspercentages retourneert. De respons wordt vervolgens vastgelegd in de DuckDB-database in het geheugen en in de s3-bucket geplaatst met de verwerkte tijdstempel.
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)
De snelheid waarmee de berekeningen plaatsvinden is recht evenredig met de streaming multiprocessor klokfrequentie. De SM klokfrequentie-metriek helpt de snelheid te bepalen waarmee de tensor- of ML-berekeningen worden geactiveerd en voltooid.
We kunnen Prometheus inschakelen om waarschuwingen te activeren wanneer de SM-klokfrequentie 2000 MHz overschrijdt. We kunnen waarschuwingswaarschuwingen instellen om op de hoogte te worden gesteld wanneer de frequentie de limiet nadert.
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."
De verzameling van SM-klokgegevens kan eenvoudig worden gescript om de gegevens in in-memory data en S3 te loggen.
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)
Door deze statistieken te benutten, kunnen ML-engineers weten wat er onder de motorkap gebeurt. Ze kunnen het trainingsproces verbeteren door de statistieken te analyseren en oplossingen in te stellen voor waarschuwingen met een hoge criticaliteit en prioriteit.
Het trainen van machine learning-modellen is een complex en ingewikkeld proces. Net zoals het zonder solide bewijs en statistieken moeilijk is om te concluderen welke modelvarianten voorspellingen met hoge inferentie vertonen. We hebben GPU-metrieken nodig om te begrijpen hoe de compute-instantie die verantwoordelijk is voor het verwerken van de ML-workloads, functioneert. Met voldoende metrieken en realtime-waarschuwingen kunnen ML-teams robuuste en duurzame ML-pipelines opzetten en stroomlijnen die de algehele ML-levenscyclus verbeteren.