このページの目次
ローカルLLM導入ノート
消費向けGPUでローカル大規模言語モデルを動かす場合、核心は予算管理の問題です。モデルの重み、KVキャッシュ、デスクトップ環境が同じVRAMを奪い合っており、どのように配分するかによって、実行可能なモデルのサイズやコンテキストの長さが決まります。本稿では24GBのRX 7900 XTXを例に、モデル選定の方法と完全に再現可能な設定手順を示し、16GB / 12GBのGPUへの拡張についても言及します。記載されているコマンドはLinux互換であり、WSL2でも同様の手順で動作します。
1. 制約: 解くべき不等式
ローカル導入におけるすべての決定——どの量子化を選ぶか、KVキャッシュの精度をどう設定するか、コンテキストをどの程度確保するか——は、すべて同じ問題を解くことに他なりません:
モデル重み + KVキャッシュ + 実行バッファ + デスクトップ余裕分 ≤ VRAM容量
この不等式は24GB、16GB、12GBのいずれのGPUにも適用されます。重要なのは右辺の値が異なるだけで、これを予算として配分することが、導入における普遍的な出発点となります。本機は7900 XTX (24GB)を搭載しており、以下ではこれを例に進めていきます。
2. 第一段階: GPUに合ったバックエンドを選択
llama.cppは複数のGPUバックエンドをサポートしており、ベンダー固有のAI学習スタック(CUDA Toolkit / ROCm / oneAPI)をインストールする必要はありません。GPUドライバに付属するランタイムのみを使用します。お使いのGPUに合わせて選択してください:
| お使いのGPU | バックエンド | コンパイルオプション |
|---|---|---|
| NVIDIA(GTX 10シリーズ以降) | CUDA | -DGGML_CUDA=ON |
| AMD(RXシリーズ / Radeon VII) | Vulkan | -DGGML_VULKAN=ON |
| Intel Arc | Vulkan | -DGGML_VULKAN=ON |
| Apple Silicon(Mシリーズ) | Metal | -DGGML_METAL=ON |
よくある質問:
「NVIDIAカードにCUDA Toolkitをインストールする必要があるのか?」——いいえ。llama.cppはGPUドライバに付属するCUDAランタイムのみを依存関係として必要とし、数GBに及ぶCUDA Toolkitのインストールは不要です。
「AMDカードでなぜROCmではなくVulkanなのか?」——ROCmはPyTorchやvLLMでの学習用であり、インストールが面倒です(特にWindows環境では)。GGUF形式での推論には不要です。VulkanはGPUドライバに付属するランタイムを使用するため、LinuxおよびWindowsでそのまま動作します。
「内蔵GPUとディスクリートGPUの両方が搭載されている場合どうするか?」——Vulkanユーザーは GGML_VK_VISIBLE_DEVICES=0 でディスクリートGPUをロックしてください(0 = 最初のGPU)。CUDAユーザーは CUDA_VISIBLE_DEVICES=0 を使用します。Metalユーザーは通常不要です。
Windowsユーザー: 以下のコマンドはすべてWSL2内で実行してください。WSL2はGPUに直接アクセス可能です(NVIDIAカードは公式ドライバをインストールすればそのまま使用可能; AMDカードはカーネル5.15以降かつAMD公式WSLドライバのインストールが必要です)。コンパイルおよびインストールの手順はLinuxと同じです。まず
wsl --installでディストリビューションをインストールし、以降の手順に従ってください。
ここからが核心問題です。VRAMをどのように配分するか。
3. 選び方: VRAMを効果的に使う
調整可能なパラメータは4つあります。パラメータ数と量子化レベルはダウンロード時にファイル選択によって決定されます。コンテキスト長とKV精度は起動時のパラメータであり、毎回変更可能です。まずは本機での選択例を示し、その後、ご自身のGPUで同様の意思決定を行う方法を解説します。
本機での選択: 節約したVRAMはKV精度ではなくコンテキスト長に投入する
Qwen3.6-35B-A3B (MoE、総パラメータ数は35Bだが、各ステップでアクティブになるのは3Bのみ。そのため、小モデルのような速度と大モデルのような知識量を両立)を選択します。真のトレードオフは、節約したVRAMをどこに投入するか——「どの程度の長さの会話を記憶できるか」に使うのか、「KVをどの程度正確に記憶させるか」に使うか——です。
24GBの内訳:
- モデル重み 16.96 GiB(IQ4_XS)。MoEにより高速に動作し、IQ4_XSにより十分な品質を確保。
- KVキャッシュは q4_0 + flash-attn を使用し、192Kのコンテキストを約5GBに圧縮。f16にすると、同じコンテキスト長で4倍のVRAMが必要となりオーバーフローする。Q8にすると半分しか収まらない。KV精度が生成品質に与える影響は、コンテキスト長に与える影響よりもはるかに小さい——したがって、この予算はすべて長さに投じる。
- 実測常駐 21.8G、残り 2.2G。アイドル時は低消費電力モードに落ち、デスクトップ動作にも支障なし。
初期には Q3_K_XL + 短いコンテキストの保守的な構成で試したが、IQ4_XS + q4_0 KVに切り替えた結果、品質、速度、コンテキスト長のバランスがさらに良くなった。デスクトップの負荷が一時的に高まった場合は、Q3グレードに切り替えて対応すればよい。
どのパラメータをいつ調整するか
ご自身のGPUに適用する場合、4つのパラメータは2つのグループに分けられます:
ステップ1: パラメータ数と重みの量子化を選択(ダウンロード時に決定)
パラメータ数の選択は、後述の「グレード表」を参照——24GBでは30–35B、16GBでは14B、12GBでは8Bが目安。
重みの量子化の選択: 同じモデルでもHugging Faceには複数のGGUFファイルが公開されており、ファイル名の接尾辞が量子化レベルを示す:
- 数字 ≈ ビット数:
Q8_0(8bit、ほぼ無損失、最大サイズ) >Q6_K>Q5_K_M>Q4_K_M(4bit、最も一般的なバランス点) >Q3_K_M(メモリ節約型、品質低下)。 IQ4_XS/IQ3_XXSは i-quant: 同じビット数でもサイズが小さく、品質はほぼ同等。imatrixが必要(パブリッシャーが既に付与済み)。VRAMが限られている場合はこれを使用。_S / _M / _L= 小 / 中 / 大 バリエーション。同じビット数では_Mが最も一般的。
選び方: GGUFファイルのサイズ ≈ 占有するVRAM。重み用予算に対してファイルサイズを照合し、収まる最大のサイズを選ぶ:
重み用予算 = VRAM - KVキャッシュ - デスクトップ余裕分(約2Gを残す)
例: 24 - 5(192K q4_0) - 2 ≈ 17G → 35Bモデルは IQ4_XS(実質 16.96G)がちょうど良い;
Q5_K_M(~24G)にすると収まらない。
経験則による優先順位: まず Q4_K_M を目指す。収まらない場合は IQ4_XS → IQ3 に下げる。余裕がある場合は Q5_K_M / Q6_K に上げる。Q3以下はやむを得ない場合を除いて使用しない。
ステップ2: KV精度を決定(起動時に調整)
KV精度とコンテキスト長はどちらも起動パラメータであり、毎回調整可能。KVには3つのスイッチがある:
| スイッチ | 役割 | 一般的な値 |
|---|---|---|
--flash-attn / -fa | 量子化KVの前提条件。必須 | オン / オフ |
--cache-type-k / -ctk | Kキャッシュの精度 | f16(デフォルト) / q8_0 / q4_0 |
--cache-type-v / -ctv | Vキャッシュの精度 | 同上 |
KとVは別々に設定可能。精度の段階は f16 → q8_0 → q4_0 で、占有VRAMは概ね 1 → 1/2 → 1/4——これがq4_0でf16の約4倍のコンテキスト長を実現できる理由である。3つの典型的な設定:
# アグレッシブ: 長コンテキスト優先
# コンサーバティブ: 品質優先、コンテキスト長を半分
# 非対称: Kは量子化により敏感なため、極限まで省メモリ化する場合はKを維持しVを圧縮
調整結果の検証方法: 起動ログに KV self size = ... が表示されるので、そこから占有サイズを確認。品質面ではq8_0はほぼ無損失、q4_0は日常会話やコーディングではほとんど知覚できないが、長文の正確な検索では occasionally 弱点が見える。VRAM使用量の確認コマンドはプラットフォームによって異なる: nvidia-smi(NVIDIAカード)、cat /sys/class/drm/card0/device/mem_info_vram_used(AMD Linux)、タスクマネージャー → パフォーマンス → GPU(Windows)。
注意点:
-faをオフにした状態で-ctv q4_0を設定すると、エラーまたは無視される——量子化Vキャッシュはflash attentionに依存するため。
異なるVRAM容量でのスタート地点
同じ予算の式を適用して推計(これらは概算値であり、ご自身のGPUで実測して調整すること):
| VRAM | 現実的な選択 |
|---|---|
| 24G | 30–35B MoE(IQ4/Q4) または 32B Dense IQ4; 長コンテキストは q4_0 KV で実現 |
| 16G | 14B Dense Q4–Q5、または 30B MoE Q3 + 適度な層のオフロード; 中程度コンテキスト |
| 12G | 8–9B Q4–Q5 が快適(例: Qwen3-8B GGUF ~5.4G)、または 14B Q4 でコンパクト |
| 8G | 7–8B Q4、短コンテキスト |
VRAM不足時の優先度: まずKV精度を下げる(f16→q8_0→q4_0)してコンテキスト長を確保 → 次にコンテキスト長を短縮 → 最後により小さなモデルまたはより強力な量子化に変更。デスクトップやゲームも同じGPUを共有していることを忘れず、数GBは確保すること。
意思決定が完了したら、モデルをダウンロードして実行する。
4. 実行: インストールから最初の応答まで
llama.cpp をインストール(server + 対応バックエンド付き、優先度順):
- 公式リリースのバイナリを使用——全プラットフォーム共通。ダウンロードして解凍するだけで使用可能。各バックエンドが含まれている。
- Linuxディストリビューションにはパッケージが存在する:
apt install llama-cpp(Debian/Ubuntu)、pacman -S llama.cpp-vulkan(Arch)。 - 上記がない場合はソースからコンパイル(セクション2で選択したスイッチに
<YOUR_BACKEND>を置き換える、例:-DGGML_CUDA=ON):
# 生成物は build/bin/ にある
モデルをローカルモデルディレクトリにダウンロード:
# HFで "<モデル名> GGUF" を検索し、unsloth / bartowski の量子化リポジトリを探す
大規模モデルのGGUFは分割されていることが多く(…-00001-of-0000N.gguf)、--include "*IQ4_XS*" で一度にすべてダウンロード。llama.cpp は最初のファイルにアクセスすると、自動的に残りをロードする。
起動(単一モデル、初回試用に適す):
Vulkanユーザーで複数のGPUがある場合は、前に GGML_VK_VISIBLE_DEVICES=0 を追加してディスクリートGPUをロック。CUDAユーザーはスキップ。
http://localhost:18080 はOpenAI互換エンドポイント。動作確認:
パス内の
MTPは何か、なぜunslothのGGUFを使用するのか、使わなくてもよいか——これらは次のセクション5で詳しく解説する。
単一モデルのコマンドは試用に適しているが、常駐運用では ルーターモード を推奨する(models.iniで複数のモデルを一元管理し、必要に応じてLRUでアンロード)。MTP加速や潮汐スケジューリングもルーターモードを基盤としているため、以下で詳しく解説する。
5. 高速化: MTP投機的デコーディング
これは何か
MTP(Multi-Token Prediction)は投機的デコーディング技術である: 逐次トークン生成ではなく、1回のフォワードパスで複数のトークンを予測する。本機では Qwen3.6-35B-A3B(IQ4_XS) で実測: MTPなしで約75 t/s、MTPありで約111 t/s、約50%の高速化。使用するモデルや量子化レベルによって、実際の向上幅は異なる。
標準的なllama.cppモデルにはこの機能がない——これは unsloth(GGUF量子化と高速化を専門とするチーム)が量子化時にGGUFにドラフトヘッダー(draft head)を埋め込んだことによる。ドラフトヘッダーはまず次の2トークンを「予測」し、メインモデルが1回のフォワードパスで並列検証する。予測が合えば利益、外れればロールバック。独立したドラフトモデルは不要で、追加のVRAMも消費しない:
探し方、MTPを使わない場合
MTPはモデル本来の機能ではなく、unslothが量子化時に追加したものである。 したがって:
- HFで
unsloth/<モデル名>-MTP-GGUFを検索した場合のみMTP版が存在する。例:unsloth/Qwen3.6-35B-A3B-MTP-GGUF。bartowskiなどの標準的な量子化リポジトリにはない。 - ファイル名に
MTPが含まれている必要がある。例:…-MTP-UD-IQ4_XS.gguf。含まれていなければドラフトヘッダーがなく、投機的デコーディングは実行できない。 - すべてのモデルにunsloth製のMTP版があるわけではない——unslothは主にQwenシリーズに追加している。ない場合は通常版のGGUFを使用すればよく、MTP加速なしで動作する。
MTPを使用しない場合の設定: ダウンロードコマンドから MTP を削除し、通常のリポジトリ(例: bartowski/Qwen3.6-35B-A3B-GGUF)に置き換える。設定ファイルから spec-type と spec-draft-n-max の2行を削除し、他は変更しない。
ルーターモードと完全なプリセット
複数のモデルを管理したり、起動時に自動起動させたりする場合は、ルーターモードにアップグレードする: すべてのモデルとパラメータを ~/.config/llama.cpp/models.ini に書き込み、serverは --models-preset でロードし、--models-max 1 で同時に常駐するモデルを1つのみに制限(24GBでは1つのみ収まる)。LRUで自動的にアンロードする:
# ~/.config/llama.cpp/models.ini
[qwen3.6-mtp-instruct]
model = ~/models/Qwen3.6-35B-A3B-MTP-UD-IQ4_XS.gguf
ngl = 99 # すべての層をGPUに(99=all)
ctx-size = 196608 # 192K コンテキスト
chat-template = chatml # OpenAI 対話テンプレート。ツール不使用時も設定を推奨
chat-template-kwargs = {"enable_thinking": false}
flash-attn = 1
cache-type-k = q4_0
cache-type-v = q4_0
spec-type = draft-mtp # 以下の2行はMTPモデルのみ必要
spec-draft-n-max = 2
注意点:
chat-template=chatmlは明示的に設定する必要がある——モデル本来のテンプレートを使用すると、ツール呼び出しのプレフィックス部分で誤ったトークンが生成され、早期のEOS(llama.cpp #19513)を引き起こす可能性がある。MTP不使用、ツール呼び出し不使用の場合でも設定が必要。
新しいモデルの追加はINIファイルに1行追加するだけで、Open WebUIのリストは自動的に更新される。systemdユニットと有効化コマンドは「完全な設定」セクションを参照。
6. 常駐スケジューリング: モデルはオンライン、消費電力は潮汐(Linux)
速く動くことは一時的であり、常駐して無駄を省くことが日常である。以下はLinux systemdとAMD sysfsインターフェースを基盤としている(WSL2ユーザーは本节を直接参照、ディストリビューションにsystemdが搭載済み。純粋なWindowsユーザーはスキップ、核心となる考え方は同じ: llama-serverのバックグラウンドプロセスを管理し、GPU負荷に応じて消費電力モードを切り替える):
3つのメカニズム:
① 起動時ウォームアップ。 ルーターの遅延ロードにより、systemd ExecStartPost で起動後にリクエストを1回送信してモデルをVRAMにロードする。ウォームアップペイロードは -d @ファイル 形式でなければならない——インラインJSONはsystemdによって引用符が削除されるため。warmup.json の中身は1行: {"model":"qwen3.6-mtp-instruct","messages":[{"role":"user","content":"hi"}],"max_tokens":1}。
② 消費電力は実際の負荷に応じてモードを切り替える。 llama-gpu-sync.timer は15秒ごとにトリガーされ、gpu_busy_percent ≥ 50% の場合にのみCOMPUTE(モード5)に切り替え、アイドルが90秒以上続くとBOOTUP_DEFAULT(モード0)に降格する。0と5のみを操作し、ゲーム用の 3d_full_screen には触れない。重要なのは「モデルがロードされているか」ではなく「GPUの実際の使用率」に基づいて切り替えること——常駐していても推論中でなければ省電力モードに留まるべきである。AMDはsysfs pp_power_profile_mode で実現し、NVIDIAは nvidia-smi -pl を使用する。
③ ゲーム中は全GPUを明け渡す。 gamemode(多くのディストリビューションにパッケージあり)はSteamゲームの起動を検知するとllama-serverを停止し、VRAMをすべてゲームに提供する。終了後に再起動。モデルはページキャッシュ内に残っており、ウォームアップは約6秒で完了:
# ~/.config/gamemode.ini
[custom]
start = systemctl --user stop llama-server
end = systemctl --user start llama-server
完全なsystemdユニット、消費電力モード切替スクリプト、sudoersのパスワード不要設定、有効化コマンドは「完全な設定」セクションを参照。
7. パフォーマンスベンチマーク
llama.cppのベンチマーク用語:
- pp512(prompt processing): 512個の入力トークンを並列処理する速度(token/s)。「長いコンテキストの読み込み」がどれだけ速いかを決定。
- tg128(text generation): 128個の出力トークンを連続生成する速度。直感的な「応答速度」——人間の読書速度は約5–10 t/s、100+ なら「話が終わる前に画面が埋まる」。
- MTPドラフト受け入れ率: ドラフトヘッダーが予測したトークンがメインモデルによって検証された割合。高いほど実質的な高速化効果が高い。
本機の実測値(Qwen3.6-35B-A3B · IQ4_XS · 192K):
| 指標 | 値 | 概念 |
|---|---|---|
| pp512 | ~3150 t/s | 長いコンテキストのプリフィックス処理で詰まらない |
| tg128 | ~111 t/s | 読書速度を大幅に超え、即時応答の体感 |
| MTP受け入れ率 | ~52% | ドラフトヘッダーの約半分が的中 |
| 常駐VRAM | 21.8 / 24 GB | 残り2.2G |
自分で測定: llama-bench で1コマンド、GPUや量子化を変更して比較:
# 出力には pp512 / tg128 の2行が含まれる
# 常駐サービスが実行中の場合は事前に停止: systemctl --user stop llama-server(Linux)
8. 実行後: クライアントとの接続
llama-serverは OpenAI互換エンドポイント(http://localhost:18080/v1)を公開しており、カスタムbase_urlを設定できるクライアントであればすべて接続可能——Open WebUI、IDEプラグイン、CLIエージェントなど、base_urlを指すだけでよい。
これでモデルは使用可能になった。しかし「何に使うか、どのタスクを委ねるべきか、Claude Opusに任せるべきか、クラウドフォールバックを設定する必要があるか」は別の話題——それこそがローカルモデルの本質的な価値であり、別途1本の記事で解説する: local-llm-usage.md を参照。
9. トラブルシューティング
- systemd内のインラインJSONで引用符が削除される → ウォームアップは必ず
-d @ファイルを使用。 - 内蔵GPUとディスクリートGPUが共存している場合、モデルが内蔵GPUで実行される →
GGML_VK_VISIBLE_DEVICES=0(Vulkan)またはCUDA_VISIBLE_DEVICES=0(CUDA)でディスクリートGPUをロック。 - 量子化KVでflash-attnが有効になっていない →
--flash-attnはcache-type q4_0/q8_0の前提条件であり、否则無視またはエラー。 - ツール呼び出しで早期EOS →
chat-template=chatmlを明示的に指定し、本来のテンプレートのバグ(llama.cpp #19513)を回避。 - 常駐=常に高消費電力 →
gpu_busy_percent(AMD)またはnvidia-smi(NVIDIA)でモードを切り替え、アイドル時は省電力モードに降格。 - VRAM予算の計算ミス → まず
モデルサイズ + KV(層数×ctx×精度) + バッファ + デスクトップを見積もり、1–2Gの余裕を残す。ゼロに近づけない。
10. 完全な設定(Linux)
前述の各セクションでは「何をすべきか」を明確にするため、重要な断片のみを記載。ここでは全体のチェーンを構成するすべてのファイルを完全な状態で記載し、順番に作成し、最後に有効化する。
WSL2ユーザーは本节を直接参照。純粋なWindowsユーザーはタスクスケジューラでsystemdを置き換え、消費電力モードの切替はAMD/NVIDIAカードに応じて個別に処理。
事前準備: スクリプト + パスワード不要sudo
llama-profile-sync は gpu-profile-set を呼び出し、後者はroot権限で pp_power_profile_mode(AMD GPU sysfs)に書き込む必要がある。systemctlの ExecStopPost も同様。userユニットではsudoパスワードプロンプトが表示できないため、パスワード不要設定が必要:
# パスワード不要sudo(USERNAMEは自分のユーザー名に置き換え):
# echo "USERNAME ALL=(ALL) NOPASSWD: /usr/local/bin/gpu-profile-set" | sudo tee /etc/sudoers.d/llama-profile
pp_power_profile_mode/gpu_busy_percentはAMD GPUのsysfsインターフェース。NVIDIAカードの消費電力管理はnvidia-smi -plまたはnvidia-persistencedを使用するため、本节のスクリプトは適用できない。
systemd userユニット(3つのファイル)
# ~/.config/systemd/user/llama-server.service
[Unit]
Description=llama.cpp server (router mode, Vulkan)
After=network.target
[Service]
Environment=GGML_VK_VISIBLE_DEVICES=0 # VulkanでディスクリートGPUをロック; CUDAユーザーは此行を削除またはCUDA_VISIBLE_DEVICES=0に置換
ExecStart=/usr/bin/llama-server \
--models-preset %h/.config/llama.cpp/models.ini \
--models-max 1 \
--host 0.0.0.0 \
--port 18080 \
--metrics
# ウォームアップ: モデルをVRAMにプリロード; -d @file でsystemdによる引用符の削除を回避
ExecStartPost=-/usr/bin/bash -c 'for i in $(seq 1 60); do curl -sf --max-time 90 http://127.0.0.1:18080/v1/chat/completions -H "Content-Type: application/json" -d @%h/.config/llama.cpp/warmup.json >/dev/null && exit 0; sleep 2; done'
# サービス停止時にGPUを省電力モードに戻す
ExecStopPost=/usr/bin/sudo /usr/local/bin/gpu-profile-set bootup_default # AMD消費電力管理; NVIDIAユーザーは此行を削除
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.target
# ~/.config/systemd/user/llama-gpu-sync.service
[Unit]
Description=Sync GPU profile with llama-server model state
After=llama-server.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/llama-profile-sync
# ~/.config/systemd/user/llama-gpu-sync.timer
[Unit]
Description=Poll llama-server model state for GPU profile switching
[Timer]
OnBootSec=15s
OnUnitActiveSec=15s
[Install]
WantedBy=timers.target
ウォームアップ
有効化
# linger — 常駐モデルの鍵: ログアウト後もサービスが存続
# リロード + 有効化
# 検証
--userは--systemではない: GPUコンテキスト(DRM render node)はユーザーセッション内にあり、systemユニットで実行するとデバイスが開けない可能性がある。権限もはるかに小さい。
関連ドキュメント
- local-llm-usage.md — 実行後: 境界(ローカル vs Opus)、何ができるか、llm-jobs自動化、実践的な教訓
- software.md — ソフトウェアスタック一覧
- timers-and-crons.md — llama-gpu-sync.timer などのタイマータスク
- monitoring.md — モニタリングアーキテクチャ(GPUメトリクスはnode_exporter→Prometheus→Grafana経由)