見出し画像

nvidia-smiとgnuplotで戯れてみる

生成AIと戯れていると、GPUリソースの状況が気になりますよね?ね?ね?とりあえす可視化したいですよね、メモリも温度もGPUも。
そんなあなたに送るnoteです。


1. 事の発端

nvidia-smiとは

nvidia-smi(NVSMI)は、NVIDIAのTesla、Quadro、GRID、GeForceデバイスの監視・管理機能を提供するコマンドです。

GPU使用率、メモリ使用量、温度、周波数など、いろいろなデータを取得できます。CSVやXMLの書式でファイルに書き出すことも可能です。

何度も叩くのが面倒くさい

時系列でデータが出力するわけですから、可視化のためにグラフにしたいよね、とデータを成形してgnuplotコマンドを叩く・・・ということを2回ほど繰り返していたわけですが、3回目ともなると当然「同じことを繰り返すの面倒くさい」ということになり、スクリプトを作成しました。

では、使用例にもとづいて説明していきましょう。

2. つかってみる

nvidia-smiにCSVデータを出力させる

以下のようなコマンドを叩きます。

nvidia-smi --query-gpu=timestamp,driver_version,vgpu_driver_capability.heterogenous_multivGPU,count,name,gpu_name,serial,gpu_serial,uuid,gpu_uuid,pci.bus_id,gpu_bus_id,pci.domain,pci.bus,pci.device,pci.device_id,pci.sub_device_id,vgpu_device_capability.fractional_multiVgpu,vgpu_device_capability.heterogeneous_timeSlice_profile,vgpu_device_capability.heterogeneous_timeSlice_sizes,pcie.link.gen.current,pcie.link.gen.gpucurrent,pcie.link.gen.max,pcie.link.gen.gpumax,pcie.link.gen.hostmax,pcie.link.width.current,pcie.link.width.max,index,display_mode,display_active,persistence_mode,addressing_mode,accounting.mode,accounting.buffer_size,driver_model.current,driver_model.pending,vbios_version,inforom.img,inforom.image,inforom.oem,inforom.ecc,inforom.pwr,inforom.power,reset_status.reset_required,reset_status.drain_and_reset_recommended,gom.current,gpu_operation_mode.current,gom.pending,gpu_operation_mode.pending,fan.speed,pstate,clocks_event_reasons.supported,clocks_throttle_reasons.supported,clocks_event_reasons.active,clocks_throttle_reasons.active,clocks_event_reasons.gpu_idle,clocks_throttle_reasons.gpu_idle,clocks_event_reasons.applications_clocks_setting,clocks_throttle_reasons.applications_clocks_setting,clocks_event_reasons.sw_power_cap,clocks_throttle_reasons.sw_power_cap,clocks_event_reasons.hw_slowdown,clocks_throttle_reasons.hw_slowdown,clocks_event_reasons.hw_thermal_slowdown,clocks_throttle_reasons.hw_thermal_slowdown,clocks_event_reasons.hw_power_brake_slowdown,clocks_throttle_reasons.hw_power_brake_slowdown,clocks_event_reasons.sw_thermal_slowdown,clocks_throttle_reasons.sw_thermal_slowdown,clocks_event_reasons.sync_boost,clocks_throttle_reasons.sync_boost,memory.total,memory.reserved,memory.used,memory.free,compute_mode,compute_cap,utilization.gpu,utilization.memory,utilization.encoder,utilization.decoder,utilization.jpeg,utilization.ofa,encoder.stats.sessionCount,encoder.stats.averageFps,encoder.stats.averageLatency,ecc.mode.current,ecc.mode.pending,ecc.errors.corrected.volatile.device_memory,ecc.errors.corrected.volatile.dram,ecc.errors.corrected.volatile.register_file,ecc.errors.corrected.volatile.l1_cache,ecc.errors.corrected.volatile.l2_cache,ecc.errors.corrected.volatile.texture_memory,ecc.errors.corrected.volatile.cbu,ecc.errors.corrected.volatile.sram,ecc.errors.corrected.volatile.total,ecc.errors.corrected.aggregate.device_memory,ecc.errors.corrected.aggregate.dram,ecc.errors.corrected.aggregate.register_file,ecc.errors.corrected.aggregate.l1_cache,ecc.errors.corrected.aggregate.l2_cache,ecc.errors.corrected.aggregate.texture_memory,ecc.errors.corrected.aggregate.cbu,ecc.errors.corrected.aggregate.sram,ecc.errors.corrected.aggregate.total,ecc.errors.uncorrected.volatile.device_memory,ecc.errors.uncorrected.volatile.dram,ecc.errors.uncorrected.volatile.register_file,ecc.errors.uncorrected.volatile.l1_cache,ecc.errors.uncorrected.volatile.l2_cache,ecc.errors.uncorrected.volatile.texture_memory,ecc.errors.uncorrected.volatile.cbu,ecc.errors.uncorrected.volatile.sram,ecc.errors.uncorrected.volatile.total,ecc.errors.uncorrected.aggregate.device_memory,ecc.errors.uncorrected.aggregate.dram,ecc.errors.uncorrected.aggregate.register_file,ecc.errors.uncorrected.aggregate.l1_cache,ecc.errors.uncorrected.aggregate.l2_cache,ecc.errors.uncorrected.aggregate.texture_memory,ecc.errors.uncorrected.aggregate.cbu,ecc.errors.uncorrected.aggregate.sram,ecc.errors.uncorrected.aggregate.total,retired_pages.single_bit_ecc.count,retired_pages.sbe,retired_pages.double_bit.count,retired_pages.dbe,retired_pages.pending,temperature.gpu,temperature.gpu.tlimit,temperature.memory,power.management,power.draw,power.draw.average,power.draw.instant,power.limit,enforced.power.limit,power.default_limit,power.min_limit,power.max_limit,clocks.current.graphics,clocks.gr,clocks.current.sm,clocks.sm,clocks.current.memory,clocks.mem,clocks.current.video,clocks.video,clocks.applications.graphics,clocks.applications.gr,clocks.applications.memory,clocks.applications.mem,clocks.default_applications.graphics,clocks.default_applications.gr,clocks.default_applications.memory,clocks.default_applications.mem,clocks.max.graphics,clocks.max.gr,clocks.max.sm,clocks.max.sm,clocks.max.memory,clocks.max.mem,mig.mode.current,mig.mode.pending,gsp.mode.current,gsp.mode.default,c2c.mode,protected_memory.total,protected_memory.used,protected_memory.free,fabric.state,fabric.status --format csv -l 1 -f ~/log/gpu.log

--query-gpuが対応する全項目(timestampからfabric.statusの)173の項目がカンマ区切り(--format=csv)で、1秒単位(-l 1)に ~/log/gpu.log(-f)ファイルに出力されます。

出力されたCSVファイル(ログ)は、こんな感じです。

$ head -3 ~/log/gpu.log
timestamp, driver_version, vgpu_driver_capability.heterogenous_multivGPU, count, name, name, serial, serial, uuid, uuid, pci.bus_id, pci.bus_id, pci.domain, pci.bus, pci.device, pci.device_id, pci.sub_device_id, vgpu_device_capability.fractional_multiVgpu, vgpu_device_capability.heterogeneous_timeSlice_profile, vgpu_device_capability.heterogeneous_timeSlice_sizes, pcie.link.gen.current, pcie.link.gen.gpucurrent, pcie.link.gen.max, pcie.link.gen.gpumax, pcie.link.gen.hostmax, pcie.link.width.current, pcie.link.width.max, index, display_mode, display_active, persistence_mode, addressing_mode, accounting.mode, accounting.buffer_size, driver_model.current, driver_model.pending, vbios_version, inforom.img, inforom.img, inforom.oem, inforom.ecc, inforom.pwr, inforom.pwr, reset_status.reset_required, reset_status.drain_and_reset_recommended, gom.current, gom.current, gom.pending, gom.pending, fan.speed [%], pstate, clocks_event_reasons.supported, clocks_event_reasons.supported, clocks_event_reasons.active, clocks_event_reasons.active, clocks_event_reasons.gpu_idle, clocks_event_reasons.gpu_idle, clocks_event_reasons.applications_clocks_setting, clocks_event_reasons.applications_clocks_setting, clocks_event_reasons.sw_power_cap, clocks_event_reasons.sw_power_cap, clocks_event_reasons.hw_slowdown, clocks_event_reasons.hw_slowdown, clocks_event_reasons.hw_thermal_slowdown, clocks_event_reasons.hw_thermal_slowdown, clocks_event_reasons.hw_power_brake_slowdown, clocks_event_reasons.hw_power_brake_slowdown, clocks_event_reasons.sw_thermal_slowdown, clocks_event_reasons.sw_thermal_slowdown, clocks_event_reasons.sync_boost, clocks_event_reasons.sync_boost, memory.total [MiB], memory.reserved [MiB], memory.used [MiB], memory.free [MiB], compute_mode, compute_cap, utilization.gpu [%], utilization.memory [%], utilization.encoder [%], utilization.decoder [%], utilization.jpeg [%], utilization.ofa [%], encoder.stats.sessionCount, encoder.stats.averageFps, encoder.stats.averageLatency, ecc.mode.current, ecc.mode.pending, ecc.errors.corrected.volatile.device_memory, ecc.errors.corrected.volatile.dram, ecc.errors.corrected.volatile.register_file, ecc.errors.corrected.volatile.l1_cache, ecc.errors.corrected.volatile.l2_cache, ecc.errors.corrected.volatile.texture_memory, ecc.errors.corrected.volatile.cbu, ecc.errors.corrected.volatile.sram, ecc.errors.corrected.volatile.total, ecc.errors.corrected.aggregate.device_memory, ecc.errors.corrected.aggregate.dram, ecc.errors.corrected.aggregate.register_file, ecc.errors.corrected.aggregate.l1_cache, ecc.errors.corrected.aggregate.l2_cache, ecc.errors.corrected.aggregate.texture_memory, ecc.errors.corrected.aggregate.cbu, ecc.errors.corrected.aggregate.sram, ecc.errors.corrected.aggregate.total, ecc.errors.uncorrected.volatile.device_memory, ecc.errors.uncorrected.volatile.dram, ecc.errors.uncorrected.volatile.register_file, ecc.errors.uncorrected.volatile.l1_cache, ecc.errors.uncorrected.volatile.l2_cache, ecc.errors.uncorrected.volatile.texture_memory, ecc.errors.uncorrected.volatile.cbu, ecc.errors.uncorrected.volatile.sram, ecc.errors.uncorrected.volatile.total, ecc.errors.uncorrected.aggregate.device_memory, ecc.errors.uncorrected.aggregate.dram, ecc.errors.uncorrected.aggregate.register_file, ecc.errors.uncorrected.aggregate.l1_cache, ecc.errors.uncorrected.aggregate.l2_cache, ecc.errors.uncorrected.aggregate.texture_memory, ecc.errors.uncorrected.aggregate.cbu, ecc.errors.uncorrected.aggregate.sram, ecc.errors.uncorrected.aggregate.total, retired_pages.single_bit_ecc.count, retired_pages.single_bit_ecc.count, retired_pages.double_bit.count, retired_pages.double_bit.count, retired_pages.pending, temperature.gpu, temperature.gpu.tlimit, temperature.memory, power.management, power.draw [W], power.draw.average [W], power.draw.instant [W], power.limit [W], enforced.power.limit [W], power.default_limit [W], power.min_limit [W], power.max_limit [W], clocks.current.graphics [MHz], clocks.current.graphics [MHz], clocks.current.sm [MHz], clocks.current.sm [MHz], clocks.current.memory [MHz], clocks.current.memory [MHz], clocks.current.video [MHz], clocks.current.video [MHz], clocks.applications.graphics [MHz], clocks.applications.graphics [MHz], clocks.applications.memory [MHz], clocks.applications.memory [MHz], clocks.default_applications.graphics [MHz], clocks.default_applications.graphics [MHz], clocks.default_applications.memory [MHz], clocks.default_applications.memory [MHz], clocks.max.graphics [MHz], clocks.max.graphics [MHz], clocks.max.sm [MHz], clocks.max.sm [MHz], clocks.max.memory [MHz], clocks.max.memory [MHz], mig.mode.current, mig.mode.pending, gsp.mode.current, gsp.mode.default, c2c.mode, protected_memory.total [MiB], protected_memory.used [MiB], protected_memory.free [MiB], fabric.state, fabric.status
2024/01/13 20:20:41.502, 546.33, [N/A], 2, NVIDIA GeForce RTX 4090 Laptop GPU, NVIDIA GeForce RTX 4090 Laptop GPU, [N/A], [N/A], GPU-02c3e3e7-5892-b531-20d7-a8bff3b7c966, GPU-02c3e3e7-5892-b531-20d7-a8bff3b7c966, 00000000:02:00.0, 00000000:02:00.0, 0x0000, 0x02, 0x00, 0x275710DE, 0x37021558, [N/A], [N/A], [N/A], 4, 4, 4, 4, 5, 8, 16, 0, Enabled, Enabled, Enabled, [N/A], Disabled, 4000, WDDM, WDDM, 95.03.2b.00.f6, G002.0000.00.03, G002.0000.00.03, 2.0, [N/A], [N/A], [N/A], No, [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], P8, 0x00000000000001FF, 0x00000000000001FF, 0x0000000000000001, 0x0000000000000001, Active, Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, 16376 MiB, 312 MiB, 835 MiB, 15228 MiB, Default, 8.9, 0 %, 7 %, 0 %, 0 %, 0 %, 0 %, 0, 0, 0, [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], 49, 38, N/A, [N/A], 6.96 W, 6.96 W, 9.54 W, [N/A], 150.00 W, 150.00 W, 20.00 W, 175.00 W, 210 MHz, 210 MHz, 210 MHz, 210 MHz, 405 MHz, 405 MHz, 765 MHz, 765 MHz, [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], 3105 MHz, 3105 MHz, 3105 MHz, 3105 MHz, 9001 MHz, 9001 MHz, [N/A], [N/A], Disabled, Disabled, [N/A], [N/A], [N/A], [N/A], state  N/A, status N/A
2024/01/13 20:20:41.626, 546.33, [N/A], 2, NVIDIA GeForce RTX 4090, NVIDIA GeForce RTX 4090, [N/A], [N/A], GPU-848cdd43-17a2-335a-81c4-c2b26738055e, GPU-848cdd43-17a2-335a-81c4-c2b26738055e, 00000000:0B:00.0, 00000000:0B:00.0, 0x0000, 0x0B, 0x00, 0x268410DE, 0x40D61458, [N/A], [N/A], [N/A], 3, 3, 3, 4, 4, 4, 16, 1, Disabled, Disabled, Enabled, [N/A], Disabled, 4000, WDDM, WDDM, 95.02.3c.80.0a, G002.0000.00.03, G002.0000.00.03, 2.0, 6.16, [N/A], [N/A], No, [N/A], [N/A], [N/A], [N/A], [N/A], 30 %, P8, 0x00000000000001FF, 0x00000000000001FF, 0x0000000000000001, 0x0000000000000001, Active, Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, Not Active, 24564 MiB, 408 MiB, 0 MiB, 24156 MiB, Default, 8.9, 0 %, 0 %, 0 %, 0 %, 0 %, 0 %, 0, 0, 0, Disabled, Disabled, [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], 32, 52, N/A, Enabled, 8.16 W, 8.16 W, 13.73 W, 450.00 W, 450.00 W, 450.00 W, 150.00 W, 500.00 W, 210 MHz, 210 MHz, 210 MHz, 210 MHz, 405 MHz, 405 MHz, 1185 MHz, 1185 MHz, [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], [N/A], 3105 MHz, 3105 MHz, 3105 MHz, 3105 MHz, 10501 MHz, 10501 MHz, [N/A], [N/A], Disabled, Disabled, [N/A], [N/A], [N/A], [N/A], state  N/A, status N/A

(注)173項目も出力するのはただのディスクの肥やしにしかならないので適切な項目に絞りましょう。

作ったプログラムを実行してみる

こちらです。

home/bin/plot4nvsmi.sh at main · ngc-shj/home · GitHub

プログラムの仕様は端的に言えば、

nvidia-smiの--query-gpuオプションを介して出力されたCSVデータを取り込んで、plotする

です。CSV限定です。XMLはInternet-Draftを書いていたときの思い出がよみがえりますが、対応していません。

nvidia-smiコマンド結果が出力されている ~/log/gpu.logファイルに書き出されているデータを入力にして、

$ plot4nvsmi.sh -o plot ~/log/gpu.log

と実行します。-o は出力先ディレクトリ(予め作成しておいてください)です。指定しない場合はカレントディレクトリに出力します。

すると、以下のようにPNG形式でグラフが生成されます。

$ ls plot
gpu-clocks.current.graphics.png  gpu-fan.speed.png            gpu-power.draw.png              gpu-utilization.encoder.png
gpu-clocks.current.memory.png    gpu-memory.free.png          gpu-power.limit.png             gpu-utilization.gpu.png
gpu-clocks.current.sm.png        gpu-memory.reserved.png      gpu-power.max.limit.png         gpu-utilization.jpeg.png
gpu-clocks.current.video.png     gpu-memory.total.png         gpu-power.min.limit.png         gpu-utilization.memory.png
gpu-clocks.max.graphics.png      gpu-memory.used.png          gpu-protected.memory.free.png   gpu-utilization.ofa.png
gpu-clocks.max.memory.png        gpu-power.default.limit.png  gpu-temperature.gpu.png
gpu-clocks.max.sm.png            gpu-power.draw.average.png   gpu-temperature.gpu.tlimit.png
gpu-enforced.power.limit.png     gpu-power.draw.instant.png   gpu-utilization.decoder.png
$

作成されたPNGファイルはこんな感じです。

3. プログラムの仕様

入力ファイル(CSV)

  • ヘッダー:
    CSVファイルの1行目に必須です。

  • データの必須項目:
    index
    (GPUのID)とtimestamp(時刻)は必須です。当然それ以外のデータも含めてくださいね、グラフが作れません

  • データの並び順:
    indexやtimestampなども含めて並び順の規定はありません。ヘッダー情報から自動判別するようにしています。ま、基本ですよね。

  • データの単位:
    出力していてもしていなくても大丈夫です。あれば削ります。
    --formatオプションにnounitsと追加すると、そもそものCSVファイルのサイズもおさえられますからオススメです。

出力ファイル(PNG)

  • 出力されるPNGファイル名:
    「入力ファイル名(拡張子抜き)-データ名.png」という書式です。

  • PNGファイルの出力対象となるデータ
    ヘッダーに単位が明記されているもの(MiB、MHz、W、%)と、温度系(temperature.*)のデータだけです。自動判別です。

  • X軸とY軸:
    X軸は時間軸(timestamp)、Y軸が各データです。

  • 複数のGPUが存在していた場合:
    まとめて1つのPNGファイルに書き出します。

  • PNGファイルを生成しないケース:
    gnuplotがエラーとなるため、すべてのデータが空(N/A)の場合はPNGファイルを生成しません。

ぼやき

コマンドラインで完結するのが理想ですよね。
表計算ソフトを立ち上げてファイル開いてグラフ作って…なんてとても面倒です。はい。

この記事が気に入ったらサポートをしてみませんか?