paint-brush
ML ライフサイクルの改善のために GPU 上に Prometheus Alertmanager を設定する@danielcrouch
新しい歴史

ML ライフサイクルの改善のために GPU 上に Prometheus Alertmanager を設定する

Daniel11m2024/10/12
Read on Terminal Reader

長すぎる; 読むには

データの量と多様性により、AI ワークロードを処理するための複雑で洗練された ML アルゴリズムが台頭しています。
featured image - ML ライフサイクルの改善のために GPU 上に Prometheus Alertmanager を設定する
Daniel HackerNoon profile picture
0-item

データの量と多様性により、AI ワークロードを処理するための複雑で洗練された ML アルゴリズムが台頭しています。これらのアルゴリズムでは、GPU が効率的に動作し、地球規模のデータセットを処理してパターンを認識する必要があります。GPU は複雑な計算を処理することで価値とパフォーマンスを提供するのに非常に効果的であり、ML/AI 分野での需要が急増しています。


GPU は便利ですが、非常に高価です。高度な AI/ML ワークロードでは、コストを最適化しながらパフォーマンスと耐久性を向上させるために、直接実装ではなく、堅牢な監視および管理戦略が必要です。GPU レベルのメトリックを集約すると、優れた結果が得られ、AI/ML ライフサイクルが改善されます。

集計可能な 3 つの GPU メトリック

ソフトウェア ワークフローは、データの読み込み、初期化、変換、データの書き込みなどの複数のステージで構成されます。複雑な計算を伴う機械学習ワークロードにも同じステージが適用されます。ステージごとに需要を満たすために、GPU のさまざまな部分が使用されます。エンジニアリング チームにとって、継続的なトレーニングとデプロイメントの割り当てと使用率のメトリックを把握することが重要です。これにより、情報に基づいた意思決定を行い、リソースを 100% 活用して最大限の価値を引き出すことができます。


機械学習の観点から見ると、モデル トレーニングが開始されると、次の GPU コンポーネントがワークフロー ステージで利用されます。ここでは、GPU コンポーネントとそれらが公開するメトリックについて説明します。最後に、 Prometheus アラート マネージャーからそれらをキャプチャして活用し、全体的な ML ライフサイクルを改善する方法を学習します。




  1. GPU メモリ: データと ML パイプラインはメモリに大きく依存しています。ビッグ データ処理では、結果をより速く得るためにデータがメモリ内で計算されます。モデルの重み、勾配、その他のハイパーパラメータ/変数は GPU メモリにロードされます。メモリ使用率を追跡すると、モデルのトレーニング速度を拡張および向上させることができます。
  2. GPU コア: モデルが行列集約型の演算を実行し、フォワード/バックワード パスを適用する場合、GPU コアがこれらの演算を処理します。テンソル コア アクティビティ メトリックは、ハードウェア ユニットがどの程度活用されているか、改善の余地があるかを判断するのに役立ちます。
  3. SM クロック周波数: GPU コアで実行される操作では、必要な数学的計算を実行するためにストリーミング マルチプロセッサ (SM) が必要です。クロック周波数は計算速度を決定するのに役立ちます。

GPU メトリックのキャプチャ

GPU 上で直接 bash スクリプトを実行しても、Python の柔軟性は得られません。トレーニング プロセス全体を通じて GPU メトリックをクエリして分析し、動作を把握することができます。これらのメトリックを活用することで、重大なシナリオに対処するためのアラートと修復を設定できます。


柔軟性と拡張性を考慮して、しきい値に基づいてスクレイピングしてアラートをトリガーするように Prometheus を設定し、Python を使用して GPU メトリックをスクレイピングしてログに記録します。

1. メモリメトリクス

GPU が NVIDIA であり、GPU 上でNVIDIA DCGM エクスポーターのセットアップが完了していると仮定します。しきい値に基づいてメトリックを監視およびスクレイピングし、しきい値を超えた場合に Slack 通知をトリガーするように Prometheus 構成を定義します。


サブネット 172.28.61.90 の下の VPC にプロビジョニングされ、Prometheus 構成を通じてポート 9400 で公開されている GPU をターゲットにします。


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


ターゲットを定義すると、2 分ごとにメモリ使用量をチェックする式を導出できます。しきい値が 80% を超えると、重大なアラートがトリガーされます。


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


その後、メトリックはアラートとして送信されます。Slack には、アラートを設定するための最も簡単な統合オプションがあります。したがって、以下の YAML 構成を使用して、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."


監視とアラートは便利ですが、何か問題が発生したときに通知するなど、限られたメリットしかありません。分析のために指標を取得し、情報に基づいた意思決定を行う必要があります。


このシナリオでは、データ管理にDuckDB 、AWS S3 操作に boto3 を検討します。Nvidia 管理ライブラリ (pynvml) を使用すると、コードを通じて GPU にアクセスして管理できます。メトリックは parquet ファイルとして S3 に書き込みます。永続性のために、DuckDB を使用してログをメモリ内データベースに書き込み、アドホックまたはリアルタイム分析のためにデータのスナップショットを S3 に書き込みます。


 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コアメトリクス

GPU は、テンソル コアで有名です。これらは、多次元データを処理できるハードウェア ユニットです。コアがどのように負荷を分散または処理しているか、またいつしきい値に達したかを理解することが重要です。これらのアラートを通じて自動スケーリング ルールを実装し、ワークロードを処理して過熱やクラッシュを回避できます。


メモリ監視と同様に、GPU コア使用率メトリックを監視してキャプチャするための構成を設定します。 1 分ごとに、コア使用率が 80% を超えると重大なアラートが送信され、中程度の使用率の場合は 5 分ごとにステータス更新が送信されます。


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


ここでは、デバイス ハンドル インデックスを取得し、使用率を返すメソッドを呼び出します。応答はメモリ内の DuckDB データベースに記録され、処理されたタイムスタンプとともに s3 バケットに格納されます。


 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クロック周波数メトリクス

計算が行われる速度は、ストリーミング マルチプロセッサのクロック周波数に正比例します。SM クロック周波数メトリックは、テンソルまたは ML 計算がトリガーされ完了する速度を判断するのに役立ちます。


SM クロック周波数が 2000MHz を超えたときに Prometheus がアラートをトリガーするように設定できます。周波数が制限に近づいたときに通知を受け取るように警告アラートを設定できます。


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


SM クロック メトリックの蓄積は簡単にスクリプト化でき、メトリックをメモリ内データと 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)


これらのメトリクスを活用することで、ML エンジニアは内部で何が起こっているかを把握できます。メトリクスを分析し、重要度の高いアラートや優先度の高いアラートに対する修復策を設定することで、トレーニング プロセスを改善できます。

最後に

機械学習モデルのトレーニングは複雑で入り組んだプロセスです。確かな証拠や統計がなければ、どのモデルバリアントが高い推論で予測を示すかを結論付けるのは困難です。ML ワークロードの処理を担当するコンピューティングインスタンスがどのように動作しているかを把握するには、GPU メトリクスが必要です。十分なメトリクスとリアルタイムアラートがあれば、ML チームは堅牢で耐久性のある ML パイプラインを設定して合理化し、ML ライフサイクル全体を改善できます。