使っていない画像機能を外したら、メモリは1GiB減り、速度は変わらなかった 使っていない画像機能を外したら、メモリは1GiB減り、速度は変わらなかった
はじめに
プロンプトキャッシュの回で、サーバの起動ログにこの行を見つけました。
srv load_model: cache_reuse is not supported by multimodal, it will be disabled
使っている Qwen3.6-35B-A3B は画像も扱えるモデルで、
-hf で指定すると画像用の mmproj(約 0.9 GB のファイル)が自動で読み込まれます。
ところが、llm コマンドも dev-orchestra のレビューも、テキストしか使っていません。
使わない機能のために、毎回ファイルを読んでメモリを使っていたことになります。
外したら何が変わるのか。候補は 3 つありました。
- メモリが減る(ほぼ確実)
- 起動が速くなる(読むファイルが 1 つ減る)
- 読み込み・生成が速くなる(llama-bench と実サーバの速度差、約 2 割の原因かもしれない)
3 つ目が当たれば、毎日の llm がそのまま速くなります。
チェックリストから設計する
前回、測定で 19 回間違えた経験をチェックリストにまとめました。 今回はそれを最初から当てはめています。
| チェック項目 | 今回の対応 |
|---|---|
| 設定が本当に有効か | 起動ログに mmproj の読み込み行が出ていないことを確かめ、想定と違えば止まる |
| 比べ方 | あり → なし → あり → なし → あり と交互に 5 回。最初と最後の「あり」が揃うかでずれを見る |
| 本番と同じ条件 | serve.ps1 と同じ引数(-c 65536、MTP あり)。違いは --no-mmproj だけ |
| 割り込み | llama 以外が使った CPU・GPU を 10 秒ごとに記録 |
| 安全装置 | スリープ抑止が効かなければ止まる。サーバが起動しなければ止まる |
| 生データ | 生成した文章の冒頭を記録し、両条件でまともな出力かを見る |
1 つ目は --cache-reuse の件の反省です。
「入れた設定が効いているはず」で 4 日間間違えていたので、効いていなければ計測自体を止めるようにしました。
測ったのは、起動時間、メモリ、32K トークンの読み込み時間、生成速度(256 トークン × 3 回)です。
1 回目の結果
| # | mmproj | 起動 | メモリ(起動後) | 生成(平均) | 32K の読み込み |
|---|---|---|---|---|---|
| 1 | あり | 9.7 秒 | 25.11 GiB | 18.00 t/s | 140.4 秒 |
| 2 | なし | 8.3 秒 | 24.12 GiB | 19.13 t/s | 133.6 秒 |
| 3 | あり | 9.4 秒 | 25.21 GiB | 18.42 t/s | 144.9 秒 |
| 4 | なし | 9.6 秒 | 24.12 GiB | 17.25 t/s | 134.9 秒 |
| 5 | あり | 10.1 秒 | 25.21 GiB | 19.22 t/s | 125.5 秒 |
メモリは、はっきり 1 GiB 減った
「あり」は 25.11〜25.21 GiB、「なし」は 2 回とも 24.12 GiB。差は約 1.0 GiB です。 5 回の中で値がほとんど動かず、両者の範囲は重なりません。これは言い切れます。
速度は、何も言えなかった
一方で速度は、表を見ても方向が定まりません。 生成は「なし」の 1 回目が速く、2 回目が遅い。読み込みは「なし」が真ん中あたりに来ています。
決め手は、最初と最後の「あり」が揃っていないことでした。
| #1(あり) | #5(あり) | ずれ | |
|---|---|---|---|
| 32K の読み込み | 140.4 秒 | 125.5 秒 | −11% |
| 生成 | 18.00 t/s | 19.22 t/s | +7% |
同じ条件なのに、計測の始めと終わりで 1 割動いています。 「あり」どうしのばらつき(読み込み 125〜145 秒)の中に、「なし」の 134 秒がすっぽり収まっています。
条件の差より、計測中のずれのほうが大きい。 この状態で「速くなった」とも「変わらない」とも言えません。 挟み込みで測ったおかげで、それが分かったとも言えます。 1 回ずつの比較だったら、#4 と #5 を並べて「mmproj ありのほうが速い」と書いていたかもしれません。
監視に引っかかったもの
監視ログを見ると、16:14〜16:20 に llama 以外の CPU が 13〜22% まで上がっていました。 上位は python3.13 と StreamDeck です。python3.13 は計測スクリプトではありません。
調べると、この PC の Python は Microsoft Store 版の 3.13 で、プロセス名が python3.13 と見えます。
そして同じ時間帯に、別の Claude のセッションが dev-orchestra で作業していました。
dev-orchestra はこの Python で動くツールです。裏で動いていたのは、それだと見ています
(別セッションのログまでは確かめていないので、状況からの判断です)。
この区間は #3 の終盤と #4 にあたります。#4 の生成(17.25 t/s)が低いのは、その影響かもしれません。 ただ、重なっていない #1 と #5 のあいだでも 1 割ずれているので、ずれの原因がこれだけとは言えません。
裏を止めて、測り直した
チェックリストの「割り込み」に**「別の Claude のセッションが動いていないか確かめる」**を足し、測り直しました。
測り始める前に確かめると、dev-orchestra のセッションの最終操作が 40 秒前でした。 まさに使われていたわけです。そのセッションを止めてもらい、python のプロセスが無いことを確かめてから始めました。
回数も増やしています。あり → なし を交互に 7 回(あり 4 回、なし 3 回)。 こうすると「なし」の各回を、前後の「あり」の平均と比べられます。 計測中にゆっくりずれていっても、前後で挟めば打ち消せます。
| # | mmproj | 起動 | メモリ(起動後) | 生成(平均) | 32K の読み込み |
|---|---|---|---|---|---|
| 1 | あり | 25.0 秒 ※ | 25.06 GiB | 18.91 t/s | 133.2 秒 |
| 2 | なし | 8.3 秒 | 23.97 GiB | 19.39 t/s | 136.6 秒 |
| 3 | あり | 8.0 秒 | 25.06 GiB | 18.87 t/s | 136.0 秒 |
| 4 | なし | 7.1 秒 | 23.97 GiB | 18.77 t/s | 134.7 秒 |
| 5 | あり | 8.1 秒 | 25.06 GiB | 18.91 t/s | 136.8 秒 |
| 6 | なし | 7.3 秒 | 23.97 GiB | 18.85 t/s | 136.9 秒 |
| 7 | あり | 7.8 秒 | 25.06 GiB | 18.86 t/s | 136.3 秒 |
※ #1 は、直前まで動いていたサーバを止めた直後の起動です。
監視では、llama 以外の CPU は中央値 7.1% で、1 回目のような連続した山はありませんでした。
ずれが、1 割から 2% 前後まで縮みました。
| 生成 | 32K の読み込み | |
|---|---|---|
| 最初と最後の「あり」(#1 と #7) | −0.2% | +2.3% |
| #2(なし)と前後の「あり」 | +2.6% | +1.5% |
| #4(なし)と前後の「あり」 | −0.6% | −1.2% |
| #6(なし)と前後の「あり」 | −0.2% | +0.3% |
「なし」と前後の「あり」の差は、向きが回ごとにばらばらで、大きさは 3% 以内です。 mmproj を外しても速度は変わらない、と言ってよさそうです。 正確には、差があったとしても 3% 未満です。
メモリは今回も、7 回とも同じ値でした(あり 25.06 GiB、なし 23.97 GiB、差 1.09 GiB)。
1 回目の 1 割のずれが、すべて dev-orchestra のせいだったのかは分かりません。 重なっていない #1 と #5 のあいだでもずれていたからです。 ただ、裏を静かにしただけで、同じスクリプトのばらつきが 5 分の 1 になったのは確かです。
出力は一字一句同じ
2 回の計測の計 12 回とも、生成した文章は冒頭から同じでした。
ローカルLLMをiGPU(統合グラフィックス)で動作させる最大の利点は、専用メモリ(VRAM)を必要とせず、…
mmproj は画像を読むための部品なので、テキストだけなら影響しないのは予想どおりです。 ただ、予想どおりかどうかも確かめておくのが、今回のやり方です。
期待していた 2 つは外れた
--cache-reuse は、外しても使えませんでした。
srv load_model: cache_reuse is not supported by this context, it will be disabled
理由が「マルチモーダルだから」から「このコンテキストでは非対応」に変わるだけです。 このモデルは SSM とのハイブリッド構成で、KV をずらして使い回す仕組みとは両立しません。 前回確かめたとおりでした。
llama-bench と実サーバの速度差も、mmproj では説明できませんでした。 読み込みが 2 割速くなれば当たりでしたが、測り直した結果は 3% 未満の差です。原因は未解明のままです。
既定を変えた
既定は mmproj なしにしました。
| あり | なし | |
|---|---|---|
| メモリ | 約 25.1 GiB | 約 24.0 GiB |
| 起動 | 約 8 秒 | 約 7〜8 秒 |
| テキストの出力 | — | 同じ |
| 画像の入力 | 使える | 使えない |
失うのは画像の入力だけで、今は使っていません。 93.6 GiB 積んだ機体で 1 GiB は小さな差です。それでも、使わない機能のためにメモリを使い続ける理由もありません。
serve.ps1 には -Vision を足し、画像が必要なときだけ読み込めるようにしました。
# 普段(llm の自動起動もこちら)
pwsh -File scripts\serve.ps1 # --no-mmproj が付く
# 画像を使うとき
llm -Stop
pwsh -File scripts\serve.ps1 -Vision # mmproj を読み込む
変更後に llm から自動起動させ、--no-mmproj 付きで立ち上がって応答が返ること、
メモリが 24.27 GiB になっていることを確認しています。
まとめ
- テキストしか使わないのに、画像用の mmproj を毎回読み込んでいた
- 外すとメモリが約 1 GiB 減る。2 回の計測の 12 回ともほぼ同じ値で、言い切れる
- 1 回目は同じ条件の最初と最後が 1 割ずれ、速度について何も言えなかった
- 裏で別の Claude のセッションが dev-orchestra を動かしていた。止めて測り直すと、ずれは 2% 前後に縮んだ
- 測り直した結果、速度の差は 3% 未満。mmproj を外しても速くも遅くもならない
--cache-reuseは外しても使えず、llama-bench との速度差の原因でもなかった- 既定は mmproj なしに変更。画像を使うときは
-Vision
速くなる話を期待して測り始めましたが、速さは変わらず、確かに得たのは 1 GiB のメモリでした。
1 回目で「分からない」と書けたのも、2 回目で「変わらない」と言えるようになったのも、 挟み込みで測って、ずれの大きさを見ていたからです。 そして、ずれを 5 分の 1 にしたのは、測り方ではなく裏を静かにしたことでした。
関連記事 Related Posts
128K の文書の奥まで、ちゃんと読めているのか 128K の文書の奥まで、ちゃんと読めているのか
ローカルLLMに128Kトークンの文書を読ませ、20か所に仕込んだ事実を拾えるか測りました。深さによる取りこぼしは無く、文書に無いことは「記載なし」と答えました。唯一の誤りは、先頭2文字が同じ別の番号との取り違えで、片方の名前を変えると消えました。 ローカルLLMに128Kトークンの文書を読ませ、20か所に仕込んだ事実を拾えるか測りました。深さによる取りこぼしは無く、文書に無いことは「記載なし」と答えました。唯一の誤りは、先頭2文字が同じ別の番号との取り違えで、片方の名前を変えると消えました。
128K の文書は、読ませ直さずに使い回せるのか 128K の文書は、読ませ直さずに使い回せるのか
ローカルLLMに128Kトークンの文書を読ませると20分以上かかります。2回目以降を速くできるか、プロンプトキャッシュを6通りの使い方で測りました。質問を変えるだけなら数秒で済みますが、ディスクに保存して再起動すると全部読み直しになります。理由はモデルのハイブリッド構成にありました。以前の記事の誤りも見つかりました。 ローカルLLMに128Kトークンの文書を読ませると20分以上かかります。2回目以降を速くできるか、プロンプトキャッシュを6通りの使い方で測りました。質問を変えるだけなら数秒で済みますが、ディスクに保存して再起動すると全部読み直しになります。理由はモデルのハイブリッド構成にありました。以前の記事の誤りも見つかりました。
コンテキストを 128K まで伸ばしたら、壁はメモリではなく待ち時間だった コンテキストを 128K まで伸ばしたら、壁はメモリではなく待ち時間だった
ローカルLLMのコンテキストを32Kから128Kまで伸ばして測りました。予想していたメモリ不足は起きず、理由はモデルの構造にありました。代わりに見えた壁はプロンプトの取り込み時間で、128Kを読ませるだけで21〜24分かかります。途中で自分の自動起動に計測を汚された話も含みます。 ローカルLLMのコンテキストを32Kから128Kまで伸ばして測りました。予想していたメモリ不足は起きず、理由はモデルの構造にありました。代わりに見えた壁はプロンプトの取り込み時間で、128Kを読ませるだけで21〜24分かかります。途中で自分の自動起動に計測を汚された話も含みます。