ローカルで言語モデルを実行するllama.cppの新バージョンは、Gemmaモデルのトークン埋め込み重み、つまりトークンを数値ベクトルに変換する学習値がCPUメモリに二重に確保される問題を修正した。モデルファイルをメモリに直接結び付けるメモリマッピングを無効にしている利用者は、該当する条件で同じモデルをより少ないメモリで読み込める。
1. 入力と出力で重みを共有するよう修正
修正対象はGemma 3nとGemma 4だ。両モデルは、入力処理に使うトークン埋め込み重み、つまりトークンを数値ベクトルに変換する学習値を、モデルの答えを出す最後の計算段階である出力層でも共有する。入力と出力が同じ表を見るようなもので、同じメモリ領域を使えるなら表を二重に保管する必要はない。
従来は出力層を先に作るため共有する埋め込みが見つからなかったが、今回は埋め込みを先に作り、出力層がそれを参照する順序に変えた。モデルの重みの内容を変えるのではなく、共有先を先に用意することで不要なコピーが生じる原因を取り除く修正だ。
変更の作者によると、入力と出力で重みを共有するほかの94個のモデルアーキテクチャはすでにこの順序を使っており、両モデルだけが例外だった。今回の修正により、両モデルも既存のアーキテクチャと同じ順序で重みを用意するようになった。
2. 重複はメモリマッピングを無効にしたCPU実行で発生
問題が生じる条件は、ファイルの読み込み方法とデバイス配置の組み合わせにある。メモリマッピングを使わず、入力と出力が同じ種類のメモリバッファを使うと重複が発生していた。CPUのみでの実行と、一部の層を別のデバイスに送っても出力層はCPUに残す実行がこれに当たる。
標準のメモリマッピングでは、入力と出力の重みが同じマッピング領域を指すため、もともと別のコピーは確保しない。そのため、更新の効果を確認したい利用者は、CPUを使うかどうかに加え、モデルをどの方法で読み込むかも確認する必要がある。
3. 試験モデルでバッファが216 MiB減少
変更の作者がgemma-4-E2B-it Q4_K_MをCPUのみ、メモリマッピングなしで読み込んで測定した結果、モデルの重みを格納するCPUモデルバッファは3163.73 MiBから2947.73 MiBに減った。作者は変更提案で、差の216 MiBはトークン埋め込み1組のサイズと完全に一致すると説明した。
表:Gemma 4のCPUモデルバッファ測定
条件:gemma-4-E2B-it Q4_K_M、CPUのみ、メモリマッピングなし、重みの再パック無効
単位:MiB
| 項目 | 値 |
|---|---|
| 変更前 | 3163.73 |
| 変更後 | 2947.73 |
| 減少量 | 216 |
比較基準は修正前の開発バージョンcf24317beだ。表の減少量は作者が示した差であり、重複して確保されていた埋め込みのコピーが1つなくなったことで減ったメモリだ。
作者は同じモデルをCPUのみで実行し、毎回最も確率の高いトークンを選ぶ方式の出力も確認した。メモリマッピングの有効時と無効時のどちらも、修正前と出力が同じだったと述べた。
4. 再現コマンドとメモリ削減の範囲
以下は変更提案に掲載された試験コマンドそのものだ。CPUのみでの実行とメモリマッピングの無効化に加え、重みの配列を実行用に再構成する再パックを無効にする設定が含まれ、モデル読み込み中に報告されるバッファサイズの確認に使う。
llama-server -m gemma-4-E2B-it-Q4_K_M.gguf -dev none -ngl 0 -lm none --no-repack -lv 4実質的な利点は、CPUメモリに余裕のない環境でモデルを収める余地が生まれることだ。一方、出力層をGPUに置く構成では、そのデバイスに埋め込みのコピーを別途置くメモリコストはそのまま残る。
公開された削減値は上記のモデルと設定での結果であり、別途の実行速度測定は示されていない。
b12008はGemmaの共有重みを正しい順序で結び付け、メモリマッピングなしのCPU実行で重複メモリの使用を減らす。
