実録⑥:同じ機体で速度が3倍、--n-cpu-moe と3つの罠

オンプレLLM/技術記録

前回の続きです。Ubuntu 24.04 / CUDA 13.0 / nvidia-driver-595-server、llama.cpp を -DGGML_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES=86 でビルドし、104GB(4分割GGUF)を配置。構築作業そのものはAIエージェント主導で実働1日でした。

本題はチューニングです。同じバイナリ・同じ重みで、設定だけで3倍の幅がありました。

核心は --n-cpu-moe:層で切らず、役割で切る

llama.cppでGPUに載せる量を決める従来のオプションは -ngl N(上からN層をGPUへ)です。しかしMoEでこれをやると、各層には「共通部」と「専門家」が同居しているため、VRAMに貴重な専門家が中途半端に載り、共通部がCPUに残ります。

2025年8月PR #15077・2025-08-04マージ)に入った --n-cpu-moe は、これを直交する軸で切ります

-ngl 99 --n-cpu-moe 999 -t 16 -fa on -c 8192 --no-mmap

-ngl 99 で全層をGPUに指定しつつ、--n-cpu-moe 999専門家だけをCPU側へ引き剥がす。結果、VRAMには共通部だけが残り6.7GB、104GBの専門家はRAM常駐という配置になります。この1行があるかないかで、12GBのGPUで177Bが動くかどうかが決まりました。

罠1:最初の計測が、そもそも間違っていた

組み上げ直後の llama-bench5.36 tok/s を返しました。実際にはこれは無効値です。104GBがページキャッシュに載り切る前に測っていたため、計測中もディスクから読んでいたのです。

ウォームアップ後の同一条件は 16.66 tok/s3.1倍の差があり、ここで「遅い」と判断して構成を変えていたら、正しい設定を捨てていました。以降、計測前に必ず free の buff/cache がモデルサイズを超えていることを確認する手順にしました。

罠2:KVキャッシュがモデルをページキャッシュから追い出す

常駐サービス化にあたり -c 16384 でコンテキストを取ったところ、4.8 tok/s しか出ませんでした。原因は容量です。モデル104GBに対しRAMは125GiB。ここにKVキャッシュが乗ると余白が消え、mmapされたモデルページが追い出され、毎トークンHDDを読みに行く状態になります。

対処は2つ組み合わせました。-c 8192 でコンテキストを削り、--no-mmapモデルを匿名メモリに完全展開して、そもそも追い出されない状態にする。ページキャッシュに依存する構成を、依存しない構成に変えたわけです。

罠3:スレッドを倍にすると遅くなる(2×2で切り分ける)

当初 -t 32 --numa distribute-t 16 を比べて「遅くなった」ことは分かりました。ただしこれでは、スレッド数とNUMA指定のどちらが効いたのか分かりません。片方ずつ動かした要因計画で測り直します。

  • -t 16 --numa distribute:生成 16.79 / PP 131.0
  • -t 16 --numa isolate:生成 16.83 / PP 136.1
  • -t 32(NUMA指定なし):生成 13.74 / PP 135.6
  • -t 32 --numa distribute:生成 13.83 / PP 135.9

結果は明確でした。効いているのはスレッド数だけで、-t 32 にすると生成が 18%落ちます。一方 NUMA指定は誤差の範囲(distributeとisolateで0.2%、指定の有無で0.7%)でした。

より重要なのは非対称性です。スレッドを倍にすると、生成は18%悪化するのに、プロンプト処理は4%改善します。同じ設定変更が逆方向に効くということは、2つの処理の律速要因が違うということです——生成はメモリ帯域律速(SMTでスレッドを増やしても帯域を奪い合うだけ)、プロンプト処理は演算律速(バッチで行列積を回すためスレッドが増えれば素直に効く)。

余ったVRAM 5.2GBを使い切る

ここまでで --n-cpu-moe 999(専門家を全部CPU)でしたが、VRAMは6.7GB/12GBしか使っていません。余りに専門家を数層ぶん戻せます。

  • 999(=48層すべてCPU):生成 16.66 / PP 131.1
  • 46(2層をGPUへ):生成 17.01 / PP 138.6
  • 45(3層をGPUへ):生成 17.31 / PP 140.1
  • 44(4層をGPUへ):VRAM不足で起動せず

ここから 1層あたりの専門家=約1.73GB移設1層あたり0.73ms/token の短縮が求まります。さらに逆算すると、60.0ms/token の内訳が「専門家の読み出し43ms(72%)+その他17ms」と分解できます。この機体の性能は、7割がメモリ帯域で決まっているということです。

カタログ値では決まらない

3つの罠はいずれも、一般論としては逆が正しいものでした。スレッドは多いほうが速い、コンテキストは長いほうが良い、ベンチマークは動かせば数字が出る——この機体とこのモデルの組み合わせでだけ反転します。

AI駆動開発というと生成が注目されますが、実際に効いたのは条件を変えて測り直す作業を、何十回でも厭わず回せることでした。人間だけなら「こんなものだろう」で止まっていた3倍です。

次回は実用性編。ベンチマーク値と実運用値が2.5倍乖離するという、いちばん重要な話を書きます。

当社は、お手元の遊休ハードウェアを活用した「社内専用AI基盤」の構築を支援しています。
既存機材の適性診断は無料。買う前に、config.json とメモリ帯域から「動かせるモデルと速度」を計算してお示しします。

お問い合わせフォーム(「社内AI基盤 相談希望」とお書き添えください)/ info@flagship-ai.jp

シリーズ「レガシー to AI 実録」

※本記事の数値は2026年9月時点、Threadripper 1950X / DDR4-2400 4ch 128GB / RTX 3060 12GB / llama.cpp CUDAビルドでの自社実測です。構成により結果は異なります。

カテゴリー:

タグ:

🌐 日本語