この記事の要点
- 起動できた枠が、そのまま使える枠になるとは限らない。可否を分けるのは確保に成功したかどうかではなく、同じ入力を流したときに読み込み速度が保てているかどうか。
- 速度を比較した4つの枠のうち、小さい側の3つは読み込みも生成も同じ水準にとどまり、いちばん大きい枠だけが読み込みの途中で打ち切りになった。
- 専用 VRAM の値だけでは境目が出ない。頭打ちになったあとは共有 GPU メモリのほうに差が出るので、2つを併せて採る。
数字はすべて、表示に使っていない 16GB のカード 1 枚に 1 モデルを載せ、テキスト入力だけで測った 2026 年 9 月時点の値。KV の型は 1 種類、スロットは 1 つ、流した入力も 1 本で、他のモデル・他の量子化・複数スロット・長時間の対話は測っていない。
16GB 1枚で文脈をどこまで指定してよいか
16GB のカード 1 枚に Qwen3.8-27B の UD-Q3_K_XL を載せ、枠 (--ctx-size) だけを変えながら同じ 30,374 トークンの入力を流した。速度を比較したのは 32,768 / 131,072 / 196,608 / 262,144 の 4 点で、32,768・131,072・196,608 の 3 点は読み込みも生成もほぼ同じ水準に収まり、262,144 だけが読み込みの途中で 900 秒の待ち時間を使い切って打ち切りになった。起動そのものは 262,144 でも通っている。枠を確保できたことと、その枠で入力を流せることは別に出た。
65,536 と 98,304 の 2 点については確保量だけを採っていて、速度を測っていない。速度について言えるのは、比較した 4 点についてだけになる。
指定に使える上限そのものは配布元が示している。設定ファイルの max_position_embeddings は 262144 と記載され、モデルカードはこの長さを追加設定なしで扱えるものと位置づけたうえで、RoPE の設定 (YaRN) を書き換えれば約 1,000,000 トークンまで伸ばせると案内している。ただしそれは配布元の記載であって、実際に確保できる枠とも、確保した枠で入力を流せるかどうかとも別の話になる。拡張の可否は実行系にも依存する。
測定環境と、測っていないもの
枠を動かした測定はすべて次の 1 構成で行っている。
- カード: RTX 5060 Ti 16GB (表示に使っていない・OCuLink 接続・PCIe Gen4 x4 で動作)
- 実行系: llama.cpp b10356
- モデル: Qwen3.8-27B UD-Q3_K_XL (テキスト入力のみ。視覚側は読み込ませていない)
- KV: K と V とも q4_0 (
--cache-type-kと--cache-type-vに個別に指定) - スロット:
--parallel 1 - 先読み: なし (先読みの有無を比べた測定だけは別に取っている)
- 枠:
--ctx-sizeで明示指定。未指定だと起動時のフィット処理が文脈長を自動で縮めるため、指定して固定した - 入力: 30,374 トークン (サーバの tokenize で実測) / 生成 64 トークン / 各条件でリクエスト 1〜2 回
- 採取: 起動直後の 1 点採り。専用 VRAM は nvidia-smi の memory.used、共有 GPU メモリは Windows のパフォーマンスカウンタ GPU Process Memory の Shared Usage をプロセス単位で採取した
共有 GPU メモリの採り方は、タスクマネージャに出ている共有 GPU メモリと同じ系統の値だが、タスクマネージャ側は全プロセスの合計になる。表に載せた値はプロセス単位で取り出したものになる。表の KV と計算用バッファは起動ログが報告する確保量で、専用 VRAM に常駐している量とは別の値として扱う。
測っていない範囲を先に出しておく。1 機 1 モデル 1 量子化での測定なので、他のモデル・他の量子化・複数スロットを開いた場合・実運用の長い対話は含まない。本記事の実測値は2026年9月時点・当該構成での測定に基づく。同じモデルで量子化を変えた場合に必要な量はQwen3.8-27BをVRAM 16GBで実測|量子化3種の必要VRAMと起動オプションの差に、モデル本体が 16GB に収まるかどうかの早見表はVRAM 16GBで動かすローカルLLM完全ガイドにまとめてある。
枠を広げたときに増えるもの
枠を 32,768 から 262,144 まで 6 点動かし、起動直後に採ったのが次の内訳になる。
| 指定した枠 | 専用VRAM | 共有GPUメモリ | KV | 計算用バッファ |
|---|---|---|---|---|
| 32,768 | 12,776MiB | 132MiB | 576.00MiB | 240.28MiB |
| 65,536 | 13,512MiB | 164MiB | 1,152.00MiB | 400.28MiB |
| 98,304 | 14,248MiB | 196MiB | 1,728.00MiB | 560.28MiB |
| 131,072 | 14,984MiB | 228MiB | 2,304.00MiB | 720.28MiB |
| 196,608 | 16,008MiB | 740MiB | 3,456.00MiB | 1,040.28MiB |
| 262,144 | 16,008MiB | 2,276MiB | 4,608.00MiB | 1,360.28MiB |
この枠別の内訳は起動した直後に採った値で、生成中の値ではない。1 機 1 モデル 1 量子化の測定なので、他の構成では別の値になる。
起動ログが報告する量のうち、枠を変えても動かないものが 2 つある。モデル本体の 11671.15 MiB と、再帰状態の 149.62 MiB になる。この 2 つはどの枠でも同じ値で出るので、枠を広げて増えるのは KV と計算用バッファだけになる。
KV は枠に正確に比例している。32,768 の 576.00MiB を基準にすると、どの行も枠の倍率どおりの値で並ぶ。計算用バッファも枠とともに増えるが、240.28MiB から 1,360.28MiB までの伸びで、枠の倍率ほどは増えていない。専用 VRAM の増分は、131,072 までは KV と計算用バッファの増分とちょうど同じ幅で動いている。3 つの区間ともどちらも 736MiB ずつで、専用側に置ける間は増える要素がこの 2 つしかないことがそのまま出ている。この一致は 196,608 から崩れる。131,072 から 196,608 へ広げると KV と計算用バッファは合わせて 1,472MiB 増えるのに専用 VRAM は 1,024MiB しか増えず、196,608 から 262,144 では同じ 1,472MiB の増加に対して専用 VRAM は動かない。増加分のすべてが、専用 VRAM 使用量の増分としては現れなくなる。
KV の型を落として同じ VRAM でより広い枠を確保する方向の話は、この記事では扱わない。q4_0 に固定したうえで枠だけを動かしている。型を変えた場合の伸び方はVRAM 16GBでローカルLLMのコンテキスト長はどこまで伸ばせるか|KVキャッシュ量子化の実測に別に取ってある。
KV の量を決めている層構成
KV がここまできれいに枠へ比例するのは、量が層構成から決まっているからになる。配布元の config.json によれば、このモデルは 64 層のうち 4 層に 1 層が full attention で、残りは linear attention として設定されている。full attention の層は 16 層。あわせて num_key_value_heads は 4、head_dim は 256 と記載されている。
ここから 1 トークン 1 層あたり 1,152 バイトになり、full attention の 16 層に 262,144 トークンぶんを掛けると 4,608.00MiB になる。枠別の内訳で 262,144 の行に出ている KV の値と一致する。設定ファイルの記載だけで、実行時に確保される KV の量が説明できたことになる。
ただし層構成が決めているのは、枠を広げたときの伸び方そのものではなく、比例したまま到達する水準のほうになる。文脈の全長ぶんを保持しない層 (sliding window attention など) を持つモデルでは、ある枠から先で増え方が寝る。2 点だけ採って直線で外挿する手順を、構成を問わず使える方法として書くことはできない。外挿する前に、枠を広げた側でもう 1 点採って傾きが続いているかを確かめる必要がある。ここで示した層構成と KV の対応は、この記事が測った 1 モデルの config.json の記載に限った話で、他の構成のモデルと KV の大小を比べる材料にはならない。
専用 VRAM が頭打ちになる点がある
枠別の内訳をもう一度縦に読むと、専用 VRAM が 196,608 の行で 16,008MiB に達し、262,144 でも同じ 16,008MiB のまま止まっている。代わりに共有 GPU メモリが 228MiB (131,072)、740MiB (196,608)、2,276MiB (262,144) と増え始める。カードに載せきれる量の頭が来た点が、この 2 列の折れ目として見えている。
共有 GPU メモリという区分について、Microsoft のドライバ ドキュメントは共有システムメモリを次のように定義している。
This value is the amount of system memory that is shared to the GPU.
これは VidMm が計算する容量 (上限) 側の定義で、あるプロセスが実際に使っている量の定義ではない。使用量のほうは DirectX 開発者ブログの記述が近く、共有メモリは GPU と CPU のどちらからも使える通常のシステムメモリで、GPU プロセスメモリのカウンタはそのプロセスが使用している専用と共有のビデオメモリの量を示す、とされている。本記事が採っているのは後者、つまりプロセスが使用している量にあたる。
なぜ振り分けが起きるのかという機構までは、この測定では踏み込めない。観測として言えるのは、専用 VRAM が 16,008MiB で止まった枠から、プロセスが使用する共有 GPU メモリの値が増えている、というところまでになる。
この 2 点 (専用 VRAM の頭打ちと共有 GPU メモリの増加) が起きた枠を、そのまま「使えない枠」と読まないほうがいい。この構成では 196,608 で 2 点とも起きているが、あとで見るとおり読み込みも生成も速度は落ちていない。2 点は当たりを付けるための材料で、使えるかどうかを分けたのは同じ入力の読み込み速度のほうになる。
同じ入力でも枠が違うと結果が変わる
プロンプトを 30,374 トークンに固定し、枠だけを変えて同じリクエストを投げた。生成は 64 トークン、各条件でリクエストを 1〜2 回。読み込み速度は 1 回目の値、生成速度は 1〜2 回の中央値になる。
| 指定した枠 | 共有GPUメモリ | 読み込み | 生成 | 結果 |
|---|---|---|---|---|
| 32,768 | 132MiB | 毎秒826.9トークン | 毎秒24.32トークン | 完了 |
| 131,072 | 228MiB | 毎秒832.1トークン | 毎秒24.26トークン | 完了 |
| 196,608 | 740MiB | 毎秒826.7トークン | 毎秒24.36トークン | 完了 |
| 262,144 | 2,276MiB | 毎秒16.53〜20.19トークン | 測定できず | 900秒で打ち切り |
入力はどの行も同じ 30,374 トークンで、長い入力だから遅い、という読み方はここでは成立しない。動かしたのは枠だけになる。32,768・131,072・196,608 の 3 点は読み込みが毎秒 826〜832 トークン、生成が毎秒 24 トークン台で並び、枠を 6 倍に広げても速度が動いていない。262,144 だけが読み込みの段階で毎秒 16.53〜20.19 トークンまで落ち、900 秒の待ち時間内に読み込みが終わらなかった。
262,144 の行には注意点が 2 つある。生成に到達していないため生成速度そのものが存在しないこと、読み込み速度は打ち切りまでの途中経過の値であることになる。完走させればもっと下がる可能性も、途中から持ち直す可能性も、この測定では区別できない。
共有 GPU メモリの列と結果の列を並べると、740MiB の 196,608 は完了していて、2,276MiB の 262,144 で結果が変わっている。ただしこの 2 行のあいだで確保量以外にどれだけの差があるかは、この表からは出てこない。
起動そのものは通るのに速度が実用域を割る、という分かれ方は枠だけの話ではない。モデルの大きさを動かした側でも同じ形が出ており、27B・32B を 16GB で動かしたときに速度がどこまで落ちるかにまとめてある。
打ち切りまでの PCIe 受信量は 1.5 倍にしか増えていない
あふれたぶんが GPU と本体メモリのあいだを何度も往復して遅くなっている、という説明がまず浮かぶ。確かめるため、リクエストを投げてから完了 (または打ち切り) までの区間で、PCIe の累積バイトカウンタ (nvidia-smi pci -gCnt の RX_BYTES / TX_BYTES) を開始前と終了後に読み、その差を取った。各条件 1 回。比較のため、同じ区間で nvidia-smi dmon -s t -d 1 のスループット値を 1 秒ごとに採って積算した値も並べている。
| 指定した枠 | 受信 (実カウンタ) | 送信 (実カウンタ) | 所要 | 受信の平均レート | 参考: dmon の値を積算した場合 |
|---|---|---|---|---|---|
| 131,072 | 2.18GB | 0.71GB | 91.8秒 | 毎秒23.7MB | 1.2GB |
| 196,608 | 2.17GB | 0.71GB | 92.3秒 | 毎秒23.5MB | 3.0GB |
| 262,144 | 3.31GB | 2.41GB | 957.6秒 (打ち切り) | 毎秒3.5MB | 3,395.2GB |
262,144 の行は 900 秒で打ち切ったところまでの値で、完走した値ではない。所要はカウンタを読んだ区間の長さなので、読み込み速度から逆算した時間とは一致しない (前後の待ちを含む)。いちばん右の列は総量として使えないことを示すために置いたもので、次の章で単独に扱う。
所要は 91.8 秒・92.3 秒に対して 957.6 秒と 10 倍を超えて伸びているのに、実際に PCIe を通った受信量は 2.18GB から 3.31GB へ 1.5 倍に増えただけになる。受信の平均レートはむしろ毎秒 23.7MB から毎秒 3.5MB へ落ちている。131,072 と 196,608 は総量も所要もほぼ同じで、共有 GPU メモリが 3 倍以上違うにもかかわらず転送の側には差が出ていない。
したがって「溢れると往復量が桁で増えるから遅い」とは、この測定からは書けない。言えるのは、遅くなった条件でも累積受信量は時間に比例して増えておらず、平均受信レートはむしろ下がった、というところまでになる。その時間が何に使われているかは特定できていない。
毎秒の値を帯域として読むこと自体にも保留が要る。測定に使ったカードのリンクを照会した結果と、そこから計算した理論帯域を並べると次のようになる。
| 項目 | 値 |
|---|---|
| リンクの世代と幅 (実測時) | Gen4 x4 (このカードの最大は x8) |
| Gen4 x4 の理論帯域 (計算値) | 毎秒約7,877MB |
| 測定で観測したピーク | 毎秒8,908MB |
| 両者の関係 | 観測値が計算上の理論帯域を約13%上回っている |
リンクの世代と幅は接続方法で決まる値で、理論帯域は計算値であって測定値ではない。それでも、観測したピークが計算上の理論帯域を上回っている以上、毎秒の値をそのまま「リンクがどれだけ埋まっているか」として読むことはできない。混雑の指標として毎秒の数字を持ち出す前に、この不一致を踏まえる必要がある。
ホストバッファを迂回する起動オプション (--no-host) を付けた場合との対照も、枠 262,144 で取った。
| 起動オプション | 共有GPUメモリ | 所要 |
|---|---|---|
| なし | 2,276MiB | 約950秒 (どちらも打ち切り) |
| ホストバッファを迂回 | 2,276MiB | 約950秒 (どちらも打ち切り) |
共有 GPU メモリも所要もほとんど動かず、どちらも打ち切りで終わった。起動ログのホスト側バッファの出力 (0.95MiB と 276.28MiB) はこのオプションを付けても残っており、オプションが対象としている範囲がこの 2 つを含むかは確認できていない。この対照でもともと採っていた PCIe の列は、スループット値の積算で採ったもので総量として使えないため落とした。残る 2 列だけで見ている。
接続そのものを替えた対照も 1 組ある。同じモデル・同じ量子化・同じ 30,374 トークンの入力を、PCIe Gen5 x16 で動く別のカード (画面表示に使用している RTX 5080 16GB) で流した。各条件 1 回になる。
| カード (接続) | 指定した枠 | 共有GPUメモリ | 受信 (実カウンタ) | 生成 | 結果 |
|---|---|---|---|---|---|
| RTX 5060 Ti (Gen4 x4) | 131,072 | 228MiB | 2.18GB | 毎秒24.29トークン | 完了 (91.8秒) |
| RTX 5060 Ti (Gen4 x4) | 262,144 | 2,276MiB | 3.31GB | 測定できず | 打ち切り (957.6秒) |
| RTX 5080 (Gen5 x16) | 131,072 | 228MiB | 3.92GB | 毎秒45.28トークン | 完了 (66.6秒) |
| RTX 5080 (Gen5 x16) | 262,144 | 3,044MiB | 2.39GB | 測定できず | 打ち切り (949.7秒) |
この別カードとの対照で読めるのは、打ち切りになるかどうかだけになる。2 枚は GPU も接続の世代・幅も画面表示の有無も違うため、差が出てもどの違いによるものかは切り分けられない。さらに 5080 側は測定中に他プロセスの占有が 1,129MiB から 358MiB へ動いており、枠ごとに使える量が揃っていない。生成速度や受信量の大小をこの表から比べることはできない。
そのうえで残る事実は 1 つで、接続を Gen4 x4 から Gen5 x16 に広げても、同じ枠・同じ入力で同じように打ち切りになった。実際の受信量は 262,144 で 2.39GB と、完了した 131,072 の 3.92GB より少ない。接続の帯域が原因だと断定はしない。この測定の範囲では、接続を広げても結果が変わらなかったという事実までが言えることになる。
転送量の測り方で答えが変わる
転送量を出す方法には 2 通りある。累積バイトカウンタ (nvidia-smi pci -gCnt) の差分を取るやり方と、nvidia-smi dmon -s t -d 1 のスループット値を 1 秒ごとに採って積算するやり方になる。同じ区間で両方を採り、突き合わせた。
| 指定した枠 | (a) 実カウンタの差分 | (b) dmon の積算 | (b)/(a) |
|---|---|---|---|
| 131,072 | 2.18GB | 1.2GB | 0.55倍 (少なく出る) |
| 196,608 | 2.17GB | 3.0GB | 1.38倍 (多く出る) |
| 262,144 | 3.31GB | 3,395.2GB | 約1,026倍 (桁違いに多く出る) |
ずれの向きが条件によって反転しているため、一定の係数を掛けて補正する使い方も成り立たない。総量が要るなら累積カウンタの差分を使い、スループット値のほうは「毎秒どれだけ流れている状態だったか」を見る用途に限るのが安全になる。なぜこれだけずれるのかという内部動作は測っていないので、原因については何も言えない。
スループット値がその用途でも読み違いを生みうることは、5080 での 2 条件を並べると分かる。同じ区間について、スループット値が毎秒 1,000MB を超えたサンプルの割合と、累積バイトカウンタの差分による実際の受信量を並べた。
| 指定した枠 | 毎秒1,000MBを超えたサンプルの割合 | 観測されたピーク | 実際の受信量 | 結果 |
|---|---|---|---|---|
| 131,072 | 5.3% | 毎秒1,404MB | 3.92GB | 完了 |
| 262,144 | 99.4% | 毎秒34,021MB | 2.39GB | 打ち切り |
打ち切りになった条件では、サンプルの 99.4% がしきい値を超えていて、区間のほぼ全体で転送が張り付いているように見える。それでも実際に流れた量は 2.39GB で、5.3% しか超えていない完了条件の 3.92GB より少ない。サンプルの見かけと実際に流れた量は別物になる。ここでも、なぜこれだけ乖離するのかの内部動作は測っていない。
専用 VRAM の値だけでは境目が見えない
枠別の内訳に戻ると、196,608 と 262,144 の専用 VRAM はどちらも 16,008MiB で同じ値になる。この 2 つの枠は、同じ入力を流したときに完了と打ち切りに分かれた組み合わせでもある。つまり結果が分かれた 2 条件を、専用 VRAM の値だけで区別することはできない。差が出るのは共有 GPU メモリの 740MiB と 2,276MiB のほうになる。
nvidia-smi の memory.used が返すのは専用側だけになる。見えないのはこの値であって、計測ツール全般ではない。同じ nvidia-smi でも dmon の rxpci には条件ごとの差が出ている。何が見えないかを、道具ではなく値の単位で押さえておく必要がある。
読者が自分の構成で同じ区分を採れるように、採取手順を並べておく。値そのものではなく採り方になる。
| 採るもの | 手段 |
|---|---|
| 専用 VRAM | nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits -i <GPU番号> |
| 共有 GPU メモリ (プロセス単位) | (Get-Counter '\GPU Process Memory(*)\Shared Usage').CounterSamples | Where-Object { $_.InstanceName -like 'pid_<PID>_*' } | Measure-Object -Property CookedValue -Sum |
| 共有 GPU メモリ (画面で見る) | タスクマネージャのパフォーマンスタブで GPU を選び、共有 GPU メモリの項目を見る |
| PCIe の総転送量 | nvidia-smi pci -i <GPU番号> -gCnt の RX_BYTES / TX_BYTES を開始前と終了後に読み、その差を取る |
| PCIe が流れている状態の割合 | nvidia-smi dmon -s t -d 1 -i <GPU番号> を対象区間だけ回し、rxpci 列がしきい値を超えたサンプルの割合を見る (総量としては使わない) |
この手順は Windows 11 でのもので、読む時点は 2 つある。起動直後 (モデルを載せた状態) と、リクエストを流し終えた直後になる。記事の表に載せた値はすべて起動直後のものになる。
実行時の注意点も添えておく。インスタンス名の書式は環境で変わりうるので、PID は対象プロセスのものに置き換える (nvidia-smi の出力でも確認できる)。パフォーマンスカウンタ名は表示言語ごとに翻訳されるため、環境によっては英語表記のパスが通らない。その場合は Get-Counter -ListSet * で自分の環境の名前を確認して置き換える。今回測定した日本語表示の機体では、英語表記のまま通っている。
起動ログには見積もりの超過が出ている
枠 262,144 を --ctx-size で明示指定して起動したとき、ログには次の出力があった。b10356 のもので、版が変われば文言は変わる。
| 出力 | 意味 |
|---|---|
common_params_fit_impl: projected to use 17789 MiB of device memory vs. 15022 MiB of free device memory |
要求量が空き容量を上回っている |
cannot meet free memory target of 1024 MiB, need to reduce device memory by 3791 MiB |
どれだけ減らす必要があるかが出ている |
load_tensors: CUDA0 model buffer size = 11671.15 MiB |
モデル本体の量。枠を変えても動かない |
llama_memory_recurrent: CUDA0 RS buffer size = 149.62 MiB |
再帰状態の量。枠を変えても動かない |
見積もりの段階で 17789 MiB と 15022 MiB の差が報告され、1024 MiB の空きを残す目標に対して 3791 MiB 足りないところまで書かれている。それでも起動は続き、サーバは応答する状態になる。読み込みが打ち切りになる条件は、起動の失敗としては現れないことになる。
この出力の読み方には条件が付く。フィット処理が走れば出る報告なので、出ていること自体は超過を意味しない。判定に使うのは、そこに並ぶ 2 つの値の比較になる。要求量が空き容量を下回っていれば、同じ出力があっても超過ではない。
指定した枠がそのまま通ったかどうかは、別の出力で確かめられる。設定ファイルの上限より 4,096 大きい 266,240 を指定して起動すると、次の 2 つが出た。
| 出力 | 意味 |
|---|---|
srv load_model: the slot context (266240) exceeds the training context of the model (262144) - capping |
指定した枠がモデル側の値まで切り詰められた |
srv load_model: initializing, n_slots = 1, n_ctx_slot = 262144 |
切り詰められた後の値。指定がそのまま通ったかはこの値で確かめる |
指定した数字がそのまま有効になっている保証はどこにもない。切り詰めが起きた場合でも起動は続くため、確かめる先は自分が打ち込んだ値ではなく n_ctx_slot の値になる。
速度を比べるときは条件を1つずつ動かす
枠を 32,768 に固定し、先読み (投機的デコード) の有無だけを変えた。プロンプトは 30,374 トークン、各条件でリクエスト 2 回、生成速度はその中央値になる。
| 先読み | 生成 |
|---|---|
| 無効 | 毎秒24.32トークン |
| 有効 (先読み上限2) | 毎秒47.24トークン |
枠を一切動かさなくても、この 1 項目だけで生成速度が約 1.9 倍動く。枠ごとの結果を比べているつもりで先読みの設定が揃っていなければ、枠のせいだと読んだ差が別のものになる。1 構成での比較なので倍率そのものは構成によって変わるが、比較の設計としては、変える項目を 1 つに絞って残りを固定しておく必要がある。先読みを有効にしたときの増加ぶんと条件についてはQwen3.8-27BのMTPは16GBで速くなるかに別途まとめてある。
入力が長いこと自体の影響は別にある
枠を 131,072 に固定し、流し込むプロンプトの長さだけを変えた。各条件でリクエスト 2 回、読み込みは 1 回目、生成は中央値になる。
| 入力トークン | 読み込み | 生成 |
|---|---|---|
| 30,374 | 毎秒832.1トークン | 毎秒24.26トークン |
| 119,883 | 毎秒590.8トークン | 毎秒16.34トークン |
専用 VRAM が頭打ちにもなっていない枠でも、入力を 30,374 から 119,883 まで伸ばせば読み込みは毎秒 832.1 から 590.8 トークンへ、生成は毎秒 24.26 から 16.34 トークンへ落ちる。長い入力を流せば遅くなること自体は、枠があふれる話とは別に存在する。
プロンプトは同じ素材を段落単位で伸ばしたもので、内容の性質が変われば値は動く。枠を動かした測定 (30,374 トークン固定) で見えた打ち切りと、この入力長による低下を、同じ現象として束ねないほうがいい。
入力を伸ばしたときに KV がどれだけ膨らみ、どこで収まらなくなるかは長文を扱ったときの VRAM の増え方で別に測っている。
測っていないこと
ここまでの数字が届く範囲を、あらためて区切っておく。
- 他のモデル。1 機 1 モデルでの測定で、層構成が違えば KV の伸び方も到達する水準も変わる
- 他の量子化。モデルは UD-Q3_K_XL のみ
- KV 型の網羅。K と V をともに q4_0 に固定していて、他の型は採っていない
- 複数スロット。
--parallel 1のみで、スロットを増やした場合は測っていない - 長時間の運用。起動直後と 1 リクエストぶんの区間しか見ていない
- 別の OS。共有 GPU メモリという区分と採取手順は Windows のものになる
- 表示に使っているカードでの再現性。5080 では打ち切りになるかどうかを 1 回対照しただけで、条件を揃えた再現はしていない
- 262,144 の枠に短い入力を流した場合。枠を動かした測定は 30,374 トークンの入力 1 本で行っている
- 視覚側。このモデルは画像・動画入力に対応するが、本記事はテキスト入力のみで測っている
まとめ
この構成で速度を比較した 4 点のうち、32,768・131,072・196,608 は読み込みも生成も同じ水準で完了し、262,144 は読み込みの途中で打ち切りになった。65,536 と 98,304 は確保量だけを採っていて、速度は測っていない。専用 VRAM は 196,608 で 16,008MiB に達して止まり、262,144 でも同じ値のままだったので、この 2 条件は専用 VRAM の数字だけでは区別できない。
単一の推奨値は出さない。構成が 1 つ変われば枠あたりの確保量も、頭打ちが来る点も動く。代わりに、自分の構成で同じ区分を採る順序を置いておく。
- 枠を
--ctx-sizeで明示指定して起動する。未指定だとフィット処理が文脈長を勝手に縮める - 起動ログの n_ctx_slot を見て、指定した枠がそのまま通ったかを確かめる。切り詰められていても起動は続く
- 同じ入力を用意し、枠だけを変えて流す。読み込み速度が同じ水準を保っているか、その 1 点で可否を見る
- 枠ごとに専用 VRAM と共有 GPU メモリの両方を採る。専用側が頭打ちになった位置と、共有側が増え始めた位置が、当たりを付ける材料になる
- 転送量を見るなら累積バイトカウンタの差分を使う。スループット値の積算は総量として使えない
枠を確保できたかどうかと、その枠で入力を流せるかどうかは別に測る必要がある。起動が通ったことは前者の答えにしかならない。そもそもモデル本体が 16GB に収まらない場合の選択肢はVRAMに収まらない大型LLMをRAMオフロードで動かすで別に扱っている。
よくある質問
指定できる最大値はどこで調べればいいか
配布元の設定ファイル (config.json) の max_position_embeddings が出発点になる。このモデルでは 262144 と記載され、モデルカードは追加設定なしで扱える長さとして案内している。RoPE の設定 (YaRN) を書き換えれば約 1,000,000 トークンまで伸ばせるとも書かれているが、それは配布元の記載で、拡張の可否は実行系にも依存する。実際にその枠で起動できたかどうかは、起動ログの n_ctx_slot の値で確かめる。
共有 GPU メモリはどこで見るのか
画面で見るならタスクマネージャのパフォーマンスタブで GPU を選び、共有 GPU メモリの項目を見る。ただしこの項目に出るのは全プロセスの合計になる。プロセス単位で取り出すなら、パフォーマンスカウンタの GPU Process Memory の Shared Usage を PID で絞り込む。カウンタ名は表示言語で翻訳されることがあるので、通らなければ Get-Counter -ListSet * で自分の環境の名前を確認する。
他のモデルでも同じ枠で同じことが起きるか
枠あたりの確保量は層構成で決まるため、この記事の数字を他のモデルへ移すことはできない。確認の順序 (枠を明示指定する、切り詰めの有無を見る、同じ入力を流して読み込み速度を比べる) はモデルや量子化が変わっても同じ形で使える。一方、共有 GPU メモリという区分と、ここに載せた採取手順は Windows のもので、別の OS では同じ形では採れない。なお小さいモデルで同じ確認をした例としては、2.6B のモデルで 128K の枠を張れるかの実測がある。
KV の型を変えたら境目も動くか
この記事は K と V をともに q4_0 に固定していて、他の型では測っていない。型を変えれば同じ枠でも KV の量が変わるので、専用 VRAM が頭打ちになる位置も動く。ただし、どの枠で読み込みが打ち切りになるかまで同じように移動するかどうかは、測っていないので言えない。型を変えた場合の枠と確保量の関係はKV キャッシュの型を落として枠を伸ばせるかの実測で扱っている。
共有 GPU メモリが増え始めた時点で使えないと判断していいか
この構成ではそう判断すると 196,608 を落としてしまう。専用 VRAM が 16,008MiB で頭打ちになり、共有 GPU メモリが 740MiB まで増えたその枠で、読み込みも生成も速度は落ちていない。専用側の頭打ちと共有側の増加は、どのあたりから怪しいかの当たりを付ける材料になる。可否を分けたのは、同じ入力を流したときの読み込み速度のほうになる。
使える枠を計算だけで出せるか
KV の量までは層構成から計算できる。このモデルでは 1 トークン 1 層あたり 1,152 バイト、full attention の 16 層に枠を掛けた値が実測と一致した。ただし可否を分けたのは速度で、そこは計算からは出てこない。枠を 2 点採って直線で外挿する手順も、構成によっては途中で増え方が寝るため無条件には使えない。外挿するなら、広げた側でもう 1 点採って傾きが続いているかを確かめる。

