Skip to content

필사 모드: DCGM Exporter — GPU利用率はあなたが思っているものではない

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

はじめに — DCGMとexporterの関係

GPUダッシュボードを作れと言われると、たいてい同じところから始まります。DCGM Exporterを立て、既定のダッシュボードを取り込み、大きなゲージにGPU利用率を挿す。そのゲージが95パーセントを指すと皆が満足します。問題は、その数字が人々の期待するものを測っていないことです。

構造から整理するとこうです。GPUから実際に値を読むのはDCGMであり、exporterはその値をPrometheusの公開形式へ移す薄い層です。 GPU Operatorのチャート既定値でdcgm.enabledが偽なのもここに理由があります。コメントがそのまま述べるとおり、exporterに内蔵されたnv-hostengineを使うため別途DCGMのDaemonSetは不要です。

メトリクス名と設定は2026-08-12に公式ドキュメント・リポジトリで確認しました。バージョンによって異なる場合があるため、使用中のバージョンで再確認してください。

既定で有効なメトリクス

何が公開されるかはリポジトリのetc/default-counters.csvが決めます。この主題における唯一の権威ある出どころであり、形式はDCGMフィールド名、Prometheusメトリクス型、ヘルプ文字列の三列です。まず実際の出力を見ます。

kubectl -n gpu-operator port-forward svc/nvidia-dcgm-exporter 9400:9400

curl -s localhost:9400/metrics | grep -E '^DCGM_FI_(DEV|PROF)' | head -20

リポジトリのREADMEが示す出力の形はこうです。

DCGM_FI_DEV_SM_CLOCK{gpu="0", UUID="GPU-604ac76c-d9cf-fef3-62e9-d92044ab6e52",container="",namespace="",pod=""} 139
DCGM_FI_DEV_MEM_CLOCK{gpu="0", UUID="GPU-604ac76c-d9cf-fef3-62e9-d92044ab6e52",container="",namespace="",pod=""} 405

既定CSVでコメントアウトされていない、つまり実際に有効なフィールドを性格別にまとめると次のとおりです。括弧内はCSVのヘルプ文字列です。

  • クロック: DCGM_FI_DEV_SM_CLOCK (SM clock frequency (in MHz))、DCGM_FI_DEV_MEM_CLOCK
  • 温度と電力: DCGM_FI_DEV_GPU_TEMPDCGM_FI_DEV_MEMORY_TEMPDCGM_FI_DEV_POWER_USAGE (Power draw (in W))、DCGM_FI_DEV_TOTAL_ENERGY_CONSUMPTION (counter、起動以降、単位mJ)
  • メモリ: DCGM_FI_DEV_FB_USEDDCGM_FI_DEV_FB_FREEDCGM_FI_DEV_FB_RESERVED — いずれもMiB単位
  • 利用率: DCGM_FI_DEV_GPU_UTILDCGM_FI_DEV_MEM_COPY_UTILDCGM_FI_DEV_ENC_UTILDCGM_FI_DEV_DEC_UTIL
  • エラー: DCGM_FI_DEV_XID_ERRORS (Value of the last XID error encountered)、DCGM_FI_DEV_PCIE_REPLAY_COUNTER
  • 行リマップ: DCGM_FI_DEV_UNCORRECTABLE_REMAPPED_ROWSDCGM_FI_DEV_CORRECTABLE_REMAPPED_ROWSDCGM_FI_DEV_ROW_REMAP_FAILURE
  • プロファイリング: DCGM_FI_PROF_GR_ENGINE_ACTIVEDCGM_FI_PROF_PIPE_TENSOR_ACTIVEDCGM_FI_PROF_DRAM_ACTIVEDCGM_FI_PROF_PCIE_TX_BYTESDCGM_FI_PROF_PCIE_RX_BYTES

ここで既に重要な事実が一つ出ます。この一覧にDCGM_FI_PROF_SM_ACTIVEDCGM_FI_PROF_SM_OCCUPANCYがありません。両フィールドはCSVに存在しますがコメントアウトされています。つまり既定設定のままでは、これから論じる本命の指標がそもそも収集されません。

利用率という語の罠

DCGM_FI_DEV_GPU_UTILのCSVヘルプは一行です。GPU utilization (in %)。この名前とこの説明だけ見ると、GPU性能の何パーセントを使っているという意味に読めます。ところがCSVのセクションコメントは静かに別のヒントを与えます。標本区間が製品ごとに異なると書かれています。

同じ名前の値を、NVIDIAのNVML APIドキュメントははるかに露骨に定義します。nvmlUtilization_tのgpuフィールドは、直前の標本区間のうちGPUで一つ以上のカーネルが実行されていた時間の割合です。この文を分解すると、何を測っていないかが見えます。カーネルが何個か、SMをいくつ使うか、テンサーコアに触るか、メモリ帯域をどれだけ動かすかは一切含まれていません。 測っているのは時間だけです。カーネルが一つでも載っていたか否かです。

そこでこういうことが起きます。ブロック一つだけのカーネルを延々と回すPodがあるとします。SMが108個のカードで、そのカーネルはSMを一つしか使いません。残り107個は遊んでいます。それでもカーネルは走り続けているので、利用率ゲージは100パーセントを指します。ダッシュボードは緑で、カードは実質1パーセントも使われていません。

DCGMのドキュメントがこの隔たりを埋める指標として挙げるのがDCGM_FI_PROF_SM_ACTIVEです。フィールドIDは1002で、定義は「少なくとも一つのワープがマルチプロセッサ上で活性だった時間の割合を、全マルチプロセッサについて平均した値」です。同じドキュメントが添える計算例がこの指標の性格を正確に示します。GPUにSMがN個あるとき、N個のブロックを使うカーネルが区間全体にわたって回れば活動率は1になります。N/5個のブロックを使うカーネルが区間全体にわたって回れば0.2です。そしてN個のブロックを使うが区間の五分の一だけ回り、残りはSMが遊んでいたなら、その値も0.2です。

先の例に戻ると答えが出ます。利用率は100パーセントなのにDCGM_FI_PROF_SM_ACTIVEは0.01付近です。二つの数字は同じ状況を説明しており、真実を語っているのは後者です。

では何を併せて見るか

DCGMのドキュメントはDCGM_FI_PROF_SM_ACTIVEに解釈基準まで付けています。0.8以上はGPUを効果的に使うための必要条件であって十分条件ではなく、0.5未満なら非効率な使い方である可能性が高い、というものです。必要条件という表現が肝です。SMが忙しいことと有用な仕事をしていることは別の主張です。

そこで最低四つを併せて見ます。

DCGM_FI_PROF_SM_ACTIVE (1002)でどれだけ広く行き渡っているかを見ます。DCGM_FI_PROF_SM_OCCUPANCY (1003)は、マルチプロセッサに常駐するワープ数をそのマルチプロセッサが支える最大同時ワープ数で割った割合で、SMの中がどれだけ埋まっているかを示します。ただし解釈に注意が要ります。ドキュメントが直接警告するとおり、占有率が高いことが必ずしもGPUをより良く使っていることを意味しません。メモリ帯域制約のワークロードではそうですが、演算制約のワークロードでは必ずしも相関しません。

DCGM_FI_PROF_PIPE_TENSOR_ACTIVE (1004)はテンサーパイプが活性だったサイクルの割合でテンサーコアが実際に回っているかを、DCGM_FI_PROF_DRAM_ACTIVE (1005)はデバイスメモリへデータが送受信されたサイクルの割合でメモリが律速かを示します。LLM推論サーバで前者が床なら行列演算がテンサーコアへ行っていないということで、デコード中心の区間で後者が高く前者が低いのは正常な姿です。

クエリにするとこういう形になります。Prometheusの式はラベルセレクタに波括弧を使うため、必ずコードブロックの中に置きます。

# ノード別の平均SM活動率
avg by (hostname) (DCGM_FI_PROF_SM_ACTIVE)

# 利用率は高いのにSMが空いているGPUを探す
DCGM_FI_DEV_GPU_UTIL > 90 and on(gpu, UUID) DCGM_FI_PROF_SM_ACTIVE < 0.3

# フレームバッファ使用率
DCGM_FI_DEV_FB_USED / (DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE)

# Grafana変数はドル記号を使うので必ずコードブロック内でのみ
avg by (gpu) (rate(DCGM_FI_DEV_TOTAL_ENERGY_CONSUMPTION{hostname=~"$node"}[$__rate_interval]))

もう一つあります。プロファイリングメトリクスはハードウェア制約により特定のグループのみ同時に読めるため、DCGMは統計的な標本抽出による自動多重化を行います。そのためドキュメントは、収集周期を短くしすぎるとメトリクスをまとめる過程でゼロが返ると警告しています。ダッシュボードに理由のないゼロが出るなら、この話を思い出す必要があります。

カスタムメトリクスの設定

既定CSVを変える方法は三つです。

第一に、CSVファイルを直接指定します。フラグは-fまたは--collectors、環境変数はDCGM_EXPORTER_COLLECTORS、既定値は/etc/dcgm-exporter/default-counters.csvです。

第二に、YAML設定ファイルを使います。--config-fileまたはDCGM_EXPORTER_CONFIG_FILEです。READMEが示す構造はこうです。

version: 1
metrics:
  file: /etc/dcgm-exporter/default-counters.csv
collection:
  interval: 30s

インラインでフィールドを並べることもでき、その場合の各項目のキーはnameprometheusTypehelpです。Kubernetesでは、カスタムメトリクスのConfigMapをファイルとしてマウントしmetrics.fileをそのパスに設定せよとREADMEが案内しています。YAMLは起動時にのみ読まれるため編集には再起動が要ります。

第三に、GPU Operatorを使うならチャート値で指定します。dcgmExporter.configブロックにnamecreatedataがあり、チャートのコメントが重要な制約を明示します。既存のConfigMapを指す場合それはリリースと同じ名前空間になければならず、メトリクス一覧はdcgm-metrics.csvというキーの下に置かれることが期待されます。

# helm values の例
dcgmExporter:
  config:
    name: custom-dcgm-exporter-metrics
    create: true
    data: |-
      DCGM_FI_DEV_GPU_UTIL,      gauge, GPU utilization (in %).
      DCGM_FI_DEV_FB_USED,       gauge, Framebuffer memory used (in MiB).
      DCGM_FI_PROF_SM_ACTIVE,    gauge, The ratio of cycles an SM has at least 1 warp assigned.
      DCGM_FI_PROF_SM_OCCUPANCY, gauge, The ratio of number of warps resident on an SM.
      DCGM_FI_PROF_PIPE_TENSOR_ACTIVE, gauge, Ratio of cycles the tensor (HMMA) pipe is active.
      DCGM_FI_PROF_DRAM_ACTIVE,  gauge, Ratio of cycles the device memory interface is active sending or receiving data.

収集周期は-cまたは--collect-interval、環境変数はDCGM_EXPORTER_INTERVAL、単位はミリ秒で既定値は30000です。リッスンアドレスは-aまたはDCGM_EXPORTER_LISTENで既定は9400番ポートです。チャートはServiceMonitorを既定で有効にしスクレイプ間隔は15秒ですが、収集周期30秒とずれるため同じ値を二度取る区間が生じます。

Podとコンテナのラベルを付ける

既定状態の時系列にはGPU識別ラベルしか付きません。ソースで確認したラベルはgpuUUIDpci_bus_iddevicemodelNamehostnameで、MIGインスタンスではGPU_I_PROFILEGPU_I_IDが加わります。これだけではどのチームがカードを食べているのか分かりません。

Kubernetesマッピングを有効にするフラグが--kubernetesまたは-k、環境変数はDCGM_EXPORTER_KUBERNETES、既定値は偽です。有効にするとpodnamespacecontainerラベルが付きます。Pod UIDが欲しければ--kubernetes-enable-pod-uidを有効にしてpod_uidラベルを得て、Podラベルまで欲しければ--kubernetes-enable-pod-labelsを有効にします。このときラベルキーにはpod_label_接頭辞が付きます。

Podラベルを丸ごと入れるとカーディナリティが爆発するので--kubernetes-pod-label-allowlist-regexで絞ります。環境変数はDCGM_EXPORTER_KUBERNETES_POD_LABEL_ALLOWLIST_REGEXで、空にすると全ラベルが入ります。チャートではこう露出します。

dcgmExporter:
  enablePodLabels: true
  enablePodUID: true
  podLabelAllowlistRegex:
    - '^app$'
    - '^team$'

チャートのコメントが警告を添えます。どちらか一つでも有効にすると、オペレータがPodに対するget、list、watch権限を持つクラスタ範囲のClusterRoleとバインディングを作ります。権限が広がる変更なので、知ったうえで有効にする必要があります。

補足が三つあります。GPUとPodを突き合わせる識別子は--kubernetes-gpu-id-typeで選び、値はuiddevice-name、既定はuidです。time-slicingやMPSから生じる仮想GPUのメトリクスを捕まえるには--kubernetes-virtual-gpusが必要で、このときvgpuラベルが付きます。そして-oまたはDCGM_EXPORTER_USE_OLD_NAMESPACEを有効にすると、ラベル名が旧方式のpod_namepod_namespacecontainer_nameに変わります。引き継いだダッシュボードでクエリが合わない、よくある理由です。

Podラベルが付くと、こうした問いに答えられるようになります。

# 名前空間別のフレームバッファ使用量合計
sum by (namespace) (DCGM_FI_DEV_FB_USED)

# Pod別のSM活動率 (SM_ACTIVEをCSVに追加した後にのみ動作)
avg by (namespace, pod) (DCGM_FI_PROF_SM_ACTIVE)

# GPUを掴んでいるのにSMをほとんど使っていないPod
avg by (namespace, pod) (DCGM_FI_PROF_SM_ACTIVE) < 0.2
  and on(namespace, pod) (avg by (namespace, pod) (DCGM_FI_DEV_FB_USED) > 1024)

おわりに — 名前を信じず定義を読む

実質的に守るべきことは二つです。第一に、ダッシュボードに利用率ゲージを一つだけ置かないことです。 あの数字はカーネルが載っていたかだけを述べ、カードがどれだけ使われているかは述べません。少なくともSM活動率とフレームバッファ使用量を隣に置いて初めて絵が完成します。

第二に、必要なフィールドを自分でCSVに入れることです。 既定CSVでDCGM_FI_PROF_SM_ACTIVEDCGM_FI_PROF_SM_OCCUPANCYがコメントアウトされている事実を知らないと、クエリをどれだけ上手に書いてもデータが無いので空のグラフを眺めることになります。

次回は層を一つ上げてアプリケーション側のメトリクスを見ます。vLLMが公開する時系列は、今いくつ待っていて最初のトークンまで何秒かかるかという、GPUメトリクスが答えられない問いに答えます。

試してみる

シリーズ

参考資料

현재 단락 (1/84)

GPUダッシュボードを作れと言われると、たいてい同じところから始まります。DCGM Exporterを立て、既定のダッシュボードを取り込み、大きなゲージにGPU利用率を挿す。そのゲージが95パーセント...

작성 글자: 0원문 글자: 8,891작성 단락: 0/84