TT Lab
はじめる
学ぶ 学習パス コース

PCA — Prometheus認定アソシエイト

GPU とサービング指標 — DCGM が語ること、語らないこと

TT Labで続きを見る

一言でいうと

GPUメトリクスで最もよく間違える判定は、「このカードはアイドルだ」です。使用率は0なのに、メモリ13.7 GiBを確保しているカードを、どちらに数えるべきか。答えは、メトリクス1つではなく、使用率・メモリ・電力をウィンドウ全体であわせて見ることです。

なぜ必要なのか

GPUは高価で、なかなか増やせません。そのため、「何枚必要か」を判定する場面がよくありますが、このとき、ダッシュボードの使用率だけを見ると、必ず間違えます。このクラスターの実測が、その例です。

RTX 3090が1枚、3時間ずっと使用率0なのに、フレームバッファー14ギガバイトを確保していた。電力も21ワットで底をついている

計算は本当にしていません。ところが、その13.7 GiBは、他のワークロードが使えません。カードがアイドルでも、場所は空いていません。この状態を「アイドルのGPU」として数えると、容量計画が間違い、「使っているGPU」として数えると、無駄を見つけられません。両方を書く必要があります。

どう動くのか

dcgm-exporterは、DCGMライブラリのフィールドを、そのままメトリクスとして出力します。よく使うものは次のとおりです。

メトリクス 種類 単位・意味
DCGM_FI_DEV_GPU_UTIL gauge GPU使用率(%)
DCGM_FI_DEV_FB_USED・FB_FREE gauge フレームバッファーの使用・空き(MiB)
DCGM_FI_DEV_POWER_USAGE gauge 電力(W)
DCGM_FI_DEV_TOTAL_ENERGY_CONSUMPTION counter 累積エネルギー(mJ)
DCGM_FI_DEV_SM_CLOCK gauge SMクロック(MHz)
DCGM_FI_PROF_SM_ACTIVE gauge ワープが載っていた時間の割合(デフォルトは無効)

エネルギーがカウンターだという点が興味深いところです。rate(...[30m]) / 1000で微分するとワットが出て、同じ時刻のPOWER_USAGEゲージと比べると、ほぼ同じ値になります(実測: 54.7 W対55.3 W)。同じものを、カウンターでもゲージでも測れることを、目で確認できる貴重な場面です。

GPU_UTILについて、DCGMの公式のフィールドの説明は、「GPU Utilization.」の一行だけです。何をどう測るのかをもっと知りたければ、プロファイリングのメトリクスを見る必要があります。公式ドキュメントは、PROF_SM_ACTIVEを「少なくとも1つのワープがSMに載っていた時間の割合を、すべてのSMについて平均した値」と定義し、「ここでactiveは、必ずしも計算中を意味しない。メモリのリクエストを待っているワープもactiveとして数える」と付け加えています。カーネル1つがGPUの5分の1しか使っていなくても、使用率が100%に見えることがある理由が、ここにあります。ただし、このexporterのデフォルトの設定では、PROF_*は無効になっており、データセンター級(Volta以上)という制限もあります。

帰属(attribution)ラベルは保証されません。dcgm-exporterは、kubeletに問い合わせてexported_namespace・exported_pod・exported_containerを付けてくれますが、ノードの構成によっては、このラベルがまるごと空になることがあります。このクラスターでも、4枚のうち1枚がそうです。帰属のないGPUは、「誰が使っているのかわからないリソース」であり、コストの配分と回収の判定が、そこで止まります。

現場での姿: サービングメトリクス

推論サーバーは、GPUメトリクスだけでは判定できません。キューが溜まって、最初のトークンが遅れているあいだも、GPU使用率は100%に見えるからです。そのため、vLLMは、サービング側のメトリクスを別に出力します。

メトリクス 種類 意味
vllm:num_requests_running・vllm:num_requests_waiting gauge 実行中・待機中のリクエスト数
vllm:time_to_first_token_seconds histogram 最初のトークンまでにかかった時間
vllm:inter_token_latency_seconds histogram トークン間の間隔
vllm:prompt_tokens_total・vllm:generation_tokens_total counter 処理したトークン数
vllm:kv_cache_usage_perc gauge KVキャッシュの占有(1が100%)
vllm:request_success_total counter 完了したリクエスト数、finished_reasonラベル

v1エンジンで、名前がいくつか変わったことも、知っておくとよいでしょう。gpu_cache_usage_percはkv_cache_usage_percになり、ラベルがmodel_name1つから、model_name・engineの2つに増えました。ソースでは、カウンターが接尾辞なしで宣言され、クライアントライブラリが_totalを付けます。そのため、ソースをgrepして、名前を書き写すと、間違えます。

次のラボのサービングメトリクスは、実測ではありません。このクラスターのvLLMのデプロイは、現在レプリカ0で停止していて、メトリクスが1つもありません。ないものをあるふりをしないために、形式だけを似せた合成サンプルを使い、すべての時系列にsource="synthetic"ラベルを付けてあります。GPU・コンテナ・ノードのメトリクスはすべて実測で、vllm:の系列だけがサンプルです。

次のラボですること

GPU4枚の3時間分の実測で、「アイドルのカード」を判定し、帰属ラベルが抜けているカードを探し、累積エネルギーのカウンターから平均電力を導き出してゲージと比べ、最後に、合成サンプルの最初のトークンまでの遅延のp95を、ヒストグラムから求めます。最後には、何が実測で、何がサンプルなのかを区別して、レポートに書きます。