「遅い」の原因が分からないまま設定を変えていないか
ローカルLLMが遅い。-nglを上げてみる。コンテキスト長を下げてみる。量子化を変えてみる。どれかで速くなったらラッキー、ならなかったら「8GBでは限界」と諦める。
これは問題の切り分けができていない。
nvidia-smiの出力には、ボトルネックがGPU演算なのかメモリ帯域なのかVRAM容量なのかを判別するのに十分な情報がある。3つの数値を読むだけで、次に何をすべきかが決まる。この記事はそのフローチャートを提供する。
読むべき3つの数値
nvidia-smiの出力から注目すべきはこの3つだけ:
+-------------------------+
| GPU-Util: XX% | ← ① GPU使用率
| Memory-Usage: XXXX/8188MiB | ← ② VRAM使用量
| Power: XX.XW | ← ③ 消費電力
+-------------------------+
この3つの組み合わせで、ボトルネックの種類が特定できる。
判断フローチャート
① GPU-Util を確認
│
├─ 90%以上 → GPU演算律速(正常。これ以上はハードウェア上限)
│ └─ ③ Power確認
│ ├─ TDP近い(140-150W) → サーマルスロットリング確認
│ └─ TDP未満 → 正常動作。速度はこれが上限
│
├─ 50-90% → 部分的ボトルネック
│ └─ ② VRAM確認
│ ├─ 95%超 → VRAM枯渇。KVキャッシュかモデルを縮小
│ └─ 95%未満 → CPU-GPU転送律速。-nglを上げるべき
│
└─ 50%未満 → GPUが遊んでいる
└─ ② VRAM確認
├─ 95%超 → VRAM枯渇でGPUに仕事が来ない。-nglを下げるかctxを縮小
└─ 50%未満 → モデルの大半がCPU上。-nglが低すぎる
パターン別: 何が起きていて何をすべきか
パターンA: GPU-Util 95%、Power 68W、VRAM 5.2/8GB
診断: 正常動作。GPUが全力で推論しており、VRAMにも余裕がある。
意味: これがこの構成の最大速度。もし「遅い」と感じるなら、ハードウェアの限界に達している。量子化を下げる(Q4_K_M → IQ4_XS等)か、モデルサイズを下げる以外の選択肢はない。
RTX 4060 + Qwen2.5-7B Q4_K_Mの場合: GPU-Util 90%超、VRAM ~5.3GB、残り~2.7GB。この状態で60-75 tok/s前後が出ていれば正常。
パターンB: GPU-Util 40%、Power 45W、VRAM 7.8/8GB
診断: VRAM枯渇。GPUは仕事をしたいが、VRAMが足りずにデータを待っている。
原因: KVキャッシュがVRAMを圧迫している。コンテキスト長を上げすぎたか、エージェントのツール呼び出しでトークンが蓄積している。
対処:
- コンテキスト長を下げる(
-c 8192→-c 4096) - KVキャッシュを量子化する(
--cache-type-k q8_0 --cache-type-v q8_0) - FlashAttentionを有効化する(
--flash-attn) - それでもダメなら
-nglを2-3下げてGPU上のモデル層を減らし、KVキャッシュにVRAMを譲る
見分け方: nvidia-smiを1秒間隔で監視しながら推論すると、VRAM使用量がトークン生成とともに漸増していく。これが見えたらKVキャッシュ膨張。
# 1秒間隔でVRAMを監視
nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits --loop=1
パターンC: GPU-Util 30%、Power 35W、VRAM 3.5/8GB
診断: GPU-CPU転送律速。GPUに載っている層が少なすぎて、大半の演算がCPU上で行われている。
原因: -nglの値が低い。モデルの重みの多くがCPU RAM上にあり、GPU→CPU→GPUのデータ転送がボトルネックになっている。
対処: -nglを段階的に上げる。OOMが出る直前の値が最適。
14Bハイブリッドの場合: Qwen2.5-14B Q4_K_M (48層) で-ngl 30だとGPU-Util 40%程度。-ngl 35に上げるとGPU-Util 70%以上に跳ね上がることが多い。この差が速度に直結する。
パターンD: GPU-Util 95%、Power 148W、VRAM 6.0/8GB
診断: サーマルスロットリング寸前。GPUは全力で動いているが、TDP上限に張り付いており、温度が上がるとクロックが落ちる。
原因: ラップトップGPUに多い。RTX 4060 Laptopの定格TDPは115-140W(メーカー設定による)。長時間推論で筐体内温度が上昇すると、GPUがクロックを自動的に下げて発熱を抑える。
対処:
- ラップトップの排熱を改善する(冷却台、室温管理)
- GPU温度を監視する:
nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader --loop=1 - 83℃を超えてクロックが下がるようなら、バッチサイズを下げるか、推論の間にクールダウン時間を入れる
- 根本的にはデスクトップGPUへの移行が解決策
Sustained性能の重要性: ピーク75 tok/sが出ても、5分後にサーマルスロットリングで50 tok/sに落ちるなら、実効速度は50 tok/s。ベンチマーク(短時間測定)と実運用(30分以上の連続推論)で速度が違うのはこれが原因。
パターンE: GPU-Util 0%、Power 15W、VRAM 500/8MB
診断: GPUがLLM推論に使われていない。CPU上で全演算が行われている。
原因:
- CUDAが認識されていない(ドライバの問題)
- llama.cppがCPU版ビルドで動いている
-
-ngl 0で起動している
確認方法:
# CUDAが使えるか確認
nvidia-smi
# llama-serverのログでGPUオフロードを確認
# "offloaded X/Y layers to GPU" が出ていれば正常
対処: CUDA対応バイナリを使っているか確認。GitHub Releasesのcuda付きZIPをダウンロードする。
監視の自動化
手動でnvidia-smiを見る代わりに、推論中に自動判定するスクリプト:
import subprocess
import time
def diagnose_gpu(threshold_util=50, threshold_vram_pct=95):
"""nvidia-smiの出力からボトルネックを診断"""
result = subprocess.run(
["nvidia-smi",
"--query-gpu=utilization.gpu,memory.used,memory.total,power.draw,temperature.gpu",
"--format=csv,noheader,nounits"],
capture_output=True, text=True
)
if result.returncode != 0:
return "ERROR: nvidia-smi failed"
values = result.stdout.strip().split(", ")
gpu_util = float(values[0])
mem_used = float(values[1])
mem_total = float(values[2])
power = float(values[3])
temp = float(values[4])
vram_pct = mem_used / mem_total * 100
# 診断
if gpu_util >= 90:
if temp >= 83:
return f"⚠ サーマルスロットリング (GPU {temp}℃, {power}W)"
return f"✅ 正常 (GPU-Util {gpu_util}%, VRAM {vram_pct:.0f}%, {power}W)"
elif gpu_util >= threshold_util:
if vram_pct >= threshold_vram_pct:
return f"🔴 VRAM枯渇 (VRAM {vram_pct:.0f}%, GPU-Util {gpu_util}%)"
return f"🟡 CPU転送律速 (GPU-Util {gpu_util}%, VRAM {vram_pct:.0f}%) → -ngl上げるべき"
else:
if vram_pct >= threshold_vram_pct:
return f"🔴 VRAM枯渇でGPU遊休 (GPU-Util {gpu_util}%, VRAM {vram_pct:.0f}%)"
return f"🟡 GPU未活用 (GPU-Util {gpu_util}%, VRAM {vram_pct:.0f}%) → -ngl低すぎ"
# 推論中に5秒間隔で診断
for _ in range(12):
print(f"{time.strftime('%H:%M:%S')} {diagnose_gpu()}")
time.sleep(5)
nvidia-smiが暴く「意外なVRAM消費者」
フローチャートでVRAM枯渇と診断されたとき、「モデルもKVキャッシュも計算上は入るはずなのに」と思ったら、LLM以外の何かがVRAMを食っている。nvidia-smiのプロセスリストを見ると犯人が見つかる。
# VRAMを使っているプロセスを全表示
nvidia-smi --query-compute-apps=pid,name,used_memory --format=csv
8GB環境で実際にハマりがちな犯人たち:
犯人1: LM Studio / Ollama のバックグラウンド常駐
LM StudioやOllamaは、UIを閉じてもモデルをVRAMに保持し続ける。7Bモデルをロードしたまま忘れていると、それだけで4-5GBが消費される。llama-serverを起動した時点でVRAMが足りずにOOMになる。
発見方法: nvidia-smiのプロセスリストにollama_llama_serverやLM Studioが残っている。
対処: 使い終わったらOllamaはollama stop、LM Studioはモデルをアンロード。タスクマネージャーでプロセスが残っていないか確認。
犯人2: ブラウザのGPU加速
Chrome、Edge、FirefoxはデフォルトでGPU加速が有効。タブを大量に開いていると200-500MBのVRAMを消費する。YouTubeやGoogle Mapsを開いたタブがあるとさらに増える。
発見方法: nvidia-smiにchrome.exeやmsedge.exeが表示される。
対処: LLM推論中はブラウザを閉じるか、GPU加速を無効にする(chrome://flags/#use-angle → Disabled)。ただし常時無効にするとブラウザ描画が遅くなる。
犯人3: Windows DWM(デスクトップ合成)
Windowsのデスクトップウィンドウマネージャー(dwm.exe)は、ディスプレイ合成にGPUを使う。これだけで200-400MBのVRAMを常時消費する。消せない。
意味: 8GBのうち「LLMに使える量」は実質7.5-7.6GB。よく「8GBに4.7GBのモデルを載せるとKVキャッシュに3.3GB使える」と計算するが、実際は2.9-3.1GB。この差がctx 8192で効いてくる。
犯人4: 画面共有・録画ツール
Discord、OBS、GeForce Experienceの画面キャプチャやオーバーレイはGPUリソースを消費する。Discordの画面共有中にLLM推論を回すと、目に見えて速度が落ちる。
対処: LLM推論中はDiscordの画面共有を切る。GeForce Experienceのインスタントリプレイも同様。
犯人5: 前回のllama-serverが残っている
llama-serverをCtrl+Cで止めたつもりが、プロセスが残っていることがある。次のllama-serverを起動するとVRAMが二重消費される。
# llama関連プロセスを確認
tasklist /fi "imagename eq llama*"
このフローチャートで解決できないケース
すべてが正常に見える(GPU-Util 90%、VRAM余裕あり、サーマルOK)のに遅い場合:
- モデルが本当に遅い: 一部のモデルはアーキテクチャ上、同パラメータ数の他モデルより遅い。別モデルで比較する
-
prefill律速: 長いプロンプトを処理するprefillフェーズはcompute律速。GPU-Utilが高いのは正常だが、prefill中はトークン生成が始まらない。
--prompt-cacheでprefillを省略できる -
バックグラウンドプロセス: ゲーム、ブラウザ(GPU加速)、動画再生がVRAMを消費している。
nvidia-smiのプロセスリストで確認
結論: 「遅い」の前にnvidia-smiを開け
nvidia-smiの3つの数値(GPU-Util、VRAM使用量、Power)を見れば、次に何をすべきかが分かる。設定を闇雲に変えるのは時間の無駄だ。
- GPU-Util 90%超: 正常。これ以上はハードウェア限界。モデルを小さくするか、GPUを買い替える
-
VRAM 95%超: KVキャッシュかモデルサイズを削る。
--flash-attnと--cache-type-k q8_0を試す -
GPU-Util 50%未満:
-nglを上げる。GPUに仕事を与える
このフローチャートを頭に入れておけば、ローカルLLMの「遅い」を体系的に潰せる。