本記事の執筆と調査には Anthropic の Claude とそのリサーチ機能を使用しています。
はじめに
2026 年 8 月 25 日、Alibaba の Qwen チームが Hugging Face と ModelScope に Qwen3.8-Flash-Next のティーザーページを公開しました。Hugging Face では「A Preview of the Qwen4 Architecture」、ModelScope では「Onward to the Next-Gen — Lightning-Fast」を掲げ、公開は 2026 年 8 月 26 日 23:00(UTC+8、日本時間 27 日 0:00)とされています。非公式に伝えられている構成は「本体 125B、N-gram 埋め込み 51B、トークンあたりアクティブ 6B のマルチモーダル MoE」です。
本記事は、この「51B の N-gram 埋め込み」に注目します。名前の通りであれば、これは学習済みの巨大なルックアップテーブルであり、通常の重みとはアクセスパターンがまったく異なります。結論を先に書くと、N-gram テーブルは「ランダムアクセスだが 1 トークンあたりの読み出し量が極端に少ない」という性質を持つため、手持ちの PC の SSD に置いたままストリーミングする構成が原理的に成立する見込みがあります。(メモリが高騰しており、追加投資できないのでSSDストリーミングに強い興味を持っています...)
ただし、執筆時点(2026 年 8 月 26 日 6:46 日本時間。公開予定の 8 月 27 日 0:00 日本時間まで約 17 時間)ではモデルの重みも技術文書も公開されておらず、以降の議論は仮定の上に成り立つ机上検討です。事実と推定の区別は「情報源の区分」の節で明示し、リリース後に確認すべき項目を末尾にまとめます。
そもそも N-gram があると何がよいのか?
一言でいうと、N-gram 埋め込みは「推論コストをほとんど増やさずに、モデルの記憶容量だけを増やす」ための仕組みです。Transformer は知識や定型パターンを主に FFN の重みに蓄えますが、FFN は全トークンが通るので、増やせば計算量も毎トークン読み出す重みの量も比例して増えます。MoE は「トークンごとに一部のエキスパートだけを計算する」条件付き計算でこれを緩和しましたが、選ばれたエキスパートは行列積として計算し、その重みを毎トークン読み出す点は変わりません。N-gram テーブルはさらに進めて、計算をせずに「引くだけ」で済む記憶を追加します。Engram 論文はこれを、MoE の条件付き計算に対する「条件付き記憶(conditional memory)」という新しいスパース性の軸と位置づけています(区分 A)。
| 方式 | トークンごとに選ぶもの | 1 トークンの計算 | 1 トークンで読む重み | 容量を増やしたときのコスト |
|---|---|---|---|---|
| dense FFN | 選ばない(全部使う) | 全重みの行列積 | 全重み(27B の Q4_K_M で約 16 GB) | 計算も帯域も比例して増える |
| MoE エキスパート(条件付き計算) | ルータが hidden state から数個 | 選んだエキスパートの行列積 | アクティブ分(6B で約 3.4 GB) | 総パラメータを増やしても計算は一定、帯域はアクティブ分 |
| N-gram テーブル(条件付き記憶) | トークン ID のハッシュで数〜数十行 | ほぼゼロ(gather とゲート) | 数十〜数百 KiB | 総パラメータを増やしても計算も帯域もほぼ一定 |
図1 の縦軸が、本記事全体を貫く論点です。N-gram テーブルは総パラメータでは MoE 本体の半分近くを占めるのに、1 トークンで触れる量は 4 桁前後小さい。この非対称性が、テーブルを本体とは別の置き場所に追い出せる根拠になります。
期待できるメリット
| メリット | 内容 | 区分 |
|---|---|---|
| 本体の層を高次の処理に回せる | 初期層は、複数トークンに割れた単語や熟語、コードの定型構文(always_ff @(posedge clk) のような固定列)の再構成にかなりの容量を使っている。これを引き算で済ませると、その分の層と容量を推論や長い文脈の追跡に回せる。Engram 論文は、初期層を静的な局所文脈の再構成から解放し、実効的にネットワークを深くすると分析している | A |
| 同じ計算量で性能が上がる | Engram 論文は、同一パラメータ数・同一計算量の MoE と比べて MMLU +3.4、BBH +5.0、HumanEval +3.0、MATH +2.4 などの改善を報告している(Engram-27B での値) | A |
| 学習が安い | テーブルは引かれた行だけが更新される疎な学習で、FLOPs をほとんど消費しない。Flash-Next の「Qwen3.7-Plus 相当を約 1/9 の訓練コストで」というベンダー主張の一因と考えられるが、N-gram 埋め込みの寄与度は未公表 | C |
| 日本語やコードに効きやすい可能性 | 1 語が複数トークンに割れる言語や、トークンの並びで意味が決まるコードは、複数トークンをまとめて引ける仕組みと相性が良いと考えられる(筆者の推測) | C |
| ハードウェアに優しい | 参照先がトークン ID だけで決まる決定的なアドレッシングなので、ホストメモリからの先読みが可能でオーバーヘッドは無視できると、論文自身が述べている。Engram を CXL メモリにプールする研究(arXiv:2603.10087)も、遅延に寛容なワークロードとして下位メモリ階層へのオフロードに適すると評価している | A |
限界
| 限界 | 内容 |
|---|---|
| 扱えるのは表層パターン | キーは直前数トークンの並びだけ。意味理解や長距離依存は本体の仕事のまま |
| ハッシュ衝突 | 稀な N-gram は他のパターンと同じ行に落ちる。複数ヘッドで緩和するが消えない |
| メモリ容量 | 51B 分の重みをどこかに置く必要がある。本記事の主題はこの置き場所 |
| 実行時に育たない | 学習済みの固定テーブルで、推論中に更新されない。SystemVerilog や UVM の定型句を覚えさせたければ学習側で対応するしかない |
| Flash-Next での効果は未検証 | 上記の性能改善は Engram-27B での報告で、Flash-Next が Engram 型かどうかを含めて未確認 |
メリットのうち最後の「ハードウェアに優しい」という性質が本記事の主題です。以降では、この性質を手持ちの PC で活かせるか、つまり 51B のテーブルを SSD に置いたままストリーミングできるかを、数値で確かめていきます。
この記事の要点
| 項目 | 内容 |
|---|---|
| 主張 | N-gram 埋め込みテーブル(噂値 51B)は 1 トークンあたり数十〜数百 KiB しか読まないため、SSD に置いたままでもデコード速度をほぼ落とさずに運用できる見込みがある |
| 根拠の骨子 | 1 トークンあたりの読み出し量が MoE のアクティブ重みより 4 桁前後小さいこと(図3)、行番号がトークン ID だけで決まるため先読みできること(図4、図6)、参照頻度の偏り(Zipf 的分布)でページキャッシュが効くこと(図8) |
| 手持ちの環境への含意 | M5 Max 128GB では、262K のフルコンテキストでも本体を Q6_K に引き上げる余地が生まれる(KV を q8_0 にすれば余裕は約 21 GB。図9、図10)。Linux PC(DDR5 128GB + VRAM 32GB)では SSD オフロードは必須ではないが、ホスト RAM の余裕を本体側へ回せる |
| 前提 | Flash-Next の N-gram 埋め込みが、ハッシュ化した N-gram で固定テーブルを引く Engram 型の設計であること。Qwen 公式の言及はなく、ティーザーの「51B N-gram embeddings」という表記と Embedding 領域の変更という記述からの推定 |
| 未確認 | 注入層の位置と数、1 トークンあたりの参照数、1 行のサイズ、テーブルの物理配置、推論エンジンの対応状況 |
情報源の区分
本記事では情報を次の 3 区分で扱い、表や本文に区分を付記します。
| 区分 | 内容 | 主な情報源 |
|---|---|---|
| A | 公式一次情報で確認できる事項 | Hugging Face / ModelScope のティーザーページ、Qwen3-Next-80B-A3B と Qwen3.8-27B の公式モデルカードと config.json、Engram 論文(arXiv:2601.07372)、FreeToken 論文(arXiv:2608.16157)、Silicon Motion と Micron の公式資料 |
| B | 非公式・二次情報 | NVIDIA Developer Forums への転載、X の投稿、OrcaRouter などのまとめ記事、SSD レビュー各誌の実測 |
| C | 本記事の仮定と概算 | 筆者による計算 |
Engram 論文の記述は原論文で確認していますが、Flash-Next が Engram 型の設計であること自体は Qwen 公式の言及がなく未確認です。この点は区分 C の仮定として扱います。
Qwen3.8-Flash-Next のティーザー情報
| 項目 | 内容 | 区分 |
|---|---|---|
| 正式名称 | Qwen/Qwen3.8-Flash-Next | A |
| ティーザー公開 | 2026 年 8 月 25 日 | A |
| 位置づけ | Hugging Face: 「A Preview of the Qwen4 Architecture」、ModelScope: 「Onward to the Next-Gen — Lightning-Fast」 | A |
| 公開予定 | 2026 年 8 月 26 日 23:00(UTC+8)= 8 月 27 日 0:00(日本時間) | A |
| 本体パラメータ | 125B | B |
| N-gram 埋め込み | 51B | B |
| トークンあたりアクティブ | 6B | B |
| 主な変更点 | Attention(QSA、GDN ハイブリッド)、Residual、Embedding、Optimization の各領域 | B |
| 訓練コスト | Qwen3.7-Plus 相当の能力を約 1/9 の訓練コストで達成し、コーディングと cowork ではより高性能(ベンダー主張) | B |
| ライセンス、コンテキスト長、注入層などの詳細 | 未公表 | ― |
Highlights の原文は NVIDIA Developer Forums にモデルカードからの転載として掲載されていますが、125B / 51B / 6B は Qwen 公式が明示した数値ではありません。ModelScope 側の原文はその後編集された形跡があるとの指摘(フォーラム参加者 1 名の観察で裏取りなし)もあり、数値の確度は高くありません。本記事では 125B / 51B / 6B を仮の値として採用します。
Flash-Next の位置づけを把握するために、系譜上の 2 モデルと並べておきます。本記事の KV キャッシュや層構成の仮定は、この表の Qwen3.8-27B の値を流用しています。
| モデル | 公開 | 層構成 | KV ヘッド × head_dim | コンテキスト長 | MTP | ライセンス | 区分 |
|---|---|---|---|---|---|---|---|
| Qwen3-Next-80B-A3B | 2025 年 9 月 | 48 層、Gated DeltaNet 3 : full attention 1(full 12 層)、MoE(512 エキスパート中 10 + 共有 1) | 2 × 256(attention ヘッド 16) | 262,144 | あり | Apache 2.0 | A |
| Qwen3.8-27B | 2026 年 8 月 14 日 | 64 層、Gated DeltaNet 3 : full attention 1(full 16 層)、dense | 4 × 256 | 262,144 | あり(1 層) | Apache 2.0 | A |
| Qwen3.8-Flash-Next | 2026 年 8 月 26 日予定 | 未公表(GDN ハイブリッド + QSA、MoE、N-gram 埋め込み 51B) | 未公表 | 未公表 | 未公表 | 未公表 | B |
N-gram 埋め込みとは何か
N-gram
N-gram はテキストを N 個の連続したトークンの並びとして切り出したものです。「私 は 犬 が 好き」をバイグラム(N=2)にすると「私 は」「は 犬」「犬 が」「が 好き」の 4 つになります。Transformer 以前の統計的言語モデルは、この N-gram の出現頻度から次のトークンの確率を推定していました。
学習済みの固定テーブル
Flash-Next の N-gram 埋め込みが Engram 型であれば、その実体は次のようなものです。Engram 論文(DeepSeek-AI と北京大学、2026 年 1 月、arXiv:2601.07372)の記述に基づきます(区分 A)。
| 要素 | 内容 |
|---|---|
| キー | 直前 N トークンのトークン ID をハッシュした値。N は複数(Engram-27B の参照構成では最大 3)、ハッシュは複数ヘッド(同 8) |
| 値 | 学習済みのベクトル。テーブルの各行が 1 ベクトル。Engram-27B の埋め込み次元は 1280 |
| 学習 | 事前学習中に、引かれた行だけが逆伝播で更新される疎な学習 |
| 推論 | 読み出し専用。実行時に生成・更新されることはない。論文自身が、アドレスが決定的であるためホストメモリからの先読みが可能でオーバーヘッドは無視できると述べている |
| 注入 | 引いたベクトルを、その層の hidden state から作るゲートで重み付けして残差ストリームに加算。Engram-27B では層 2 と層 15 の 2 箇所に注入 |
| 位置づけ | MoE の条件付き計算に対する「条件付き記憶(conditional memory)」。同一パラメータ数・同一計算量の MoE と比べて知識・推論系ベンチが向上したと報告 |
| 規模の参考 | Engram-27B は本体 27B に対して埋め込みモジュール 5.7B |
| 狙い | 熟語や多トークン語、コードの定型構文といった局所パターンの「丸暗記」を本体の外に出し、本体の初期層を静的な局所文脈の再構成から解放して、実効的にネットワークを深くする |
N-gram の組み合わせは語彙数の N 乗あるので、行を直接割り当てることはできません。ハッシュで固定サイズのテーブルに畳み込むため、行番号はテーブル全体に一様に散り、衝突は複数ヘッドで緩和します。「51B」はこの固定テーブルの容量であり、設計時に決めた値です。51B を仮に次元 4096 で割ると約 1,245 万行、Engram-27B と同じ 1280 なら約 3,980 万行になります(区分 C)。
図2 の左半分(N-gram の切り出し、ハッシュ、行番号の決定)はトークン ID だけで決まり、右下のゲートだけがその層の hidden state を必要とします。この分離が先読みを可能にします。MoE が「トークンごとに一部のエキスパートだけを計算する」条件付き計算だとすれば、N-gram テーブルは「計算せずに引くだけ」の条件付き記憶です。この違いが、以降のオフロードの議論の土台になります(後述の図11 も参照)。
なぜ SSD オフロードが成立しうるのか
仮定値
以降の概算で使う仮定値をまとめます(すべて区分 C)。単位は、行やページなどバイト単位の量を 2 進接頭辞(KiB = 1,024 バイト)で、モデルサイズ・KV・RAM 容量など GB 級の量を 10 進(GB = 10^9 バイト)で表記します。Mac の「128GB」は 128 GiB = 137.4 GB です。
| 項目 | 仮定値 | 備考 |
|---|---|---|
| テーブル総パラメータ | 51B | 噂値をそのまま採用 |
| 行の次元 | 4096 | 仮定。行数は約 1,245 万。Engram-27B の参照値は 1280(その場合 約 3,980 万行) |
| 1 行のサイズ | 4 KiB | 8 bit 量子化を仮定。4 bit なら 2 KiB。次元 1280 なら 8 bit で 1.25 KiB |
| 1 トークンあたりの参照数 | 8 回 | 基準値。Engram-27B の参照構成(N = 2〜3、ヘッド 8、注入 2 層)を機械的に当てはめると最大 32 回。感度は後述 |
| ページサイズ | 16 KiB(Apple Silicon)、4 KiB(Linux x86-64) | OS の仕様 |
| NVMe ランダム読み遅延 | 100 µs(QD1) | 保守側の仮定。デバイス実測は 20〜70 µs 程度。手持ちの XPG MARS 980 BLADE のレビュー実測は 38〜51 µs(Appendix A) |
| NVMe ランダム読み IOPS | 300K(16 KiB)、500K(4 KiB) | 保守側の仮定。PCIe 4.0 / 5.0 の NVMe には 4 KiB で 1M〜2M IOPS の製品もある。Apple 内蔵 SSD は小ブロックの QD1 が低めに出る傾向 |
| 一括発行時の完了時間 | 8 回で約 120 µs、32 回で 120〜300 µs | 並列発行が効くのは SSD の並列ユニット数(ダイ数 × プレーン数)まで。手持ちの 1TB モデルでは 8 回 約 75 µs、32 回 約 150 µs と見積もる(Appendix A) |
| デコード速度 | 50 tok/s(1 ステップ 20 ms) | M5 Max で 4 bit の MoE を動かす想定 |
| プリフィル速度 | 800 tok/s(M5 Max)、2,000 tok/s(RTX 5060 Ti × 2) | 仮定 |
| 本体のアクティブ重み | 6B × 4.5 bpw ≈ 3.4 GB/トークン | MLX 4 bit 相当 |
| full attention 層の数 | 64 層中 16 層 | Qwen3.8-27B の config.json(num_hidden_layers 64、full_attention_interval 4)と同じ構成を仮定 |
| KV ヘッド数と head_dim | 4 ヘッド × 256 | Qwen3.8-27B の config.json(num_key_value_heads 4、head_dim 256)と同じ値を仮定。KV は bf16 で 1 トークン 64 KiB(K と V の合計) |
| コンテキスト長 | 262,144 トークン | Qwen3-Next、Qwen3.8-27B とも max_position_embeddings は 262144 |
| KV 以外の作業領域 | 約 3 GB | GDN 再帰状態 約 0.05 GB、計算バッファ 約 2 GB、vision エンコーダ 約 1 GB の概算 |
1 トークンあたりの読み出し量
| 対象 | 1 トークンあたり読み出し量 | 計算 |
|---|---|---|
| N-gram 行 | 32 KiB | 8 行 × 4 KiB |
| N-gram ページ換算(Apple Silicon) | 128 KiB | 8 ページ × 16 KiB |
| N-gram ページ換算(Engram 参照構成の当てはめ) | 512 KiB | 32 ページ × 16 KiB |
| MoE アクティブ重み(Flash-Next 想定) | 約 3.4 GB | 6B × 4.5 bpw |
| dense モデル(Qwen3.8-27B Q4_K_M) | 約 16.4 GB | 27B × 4.85 bpw |
MoE アクティブ重みの 3.4 GB は、エキスパートをホスト RAM や SSD にオフロードした場合に 1 トークンで触れる重みの量であり、全エキスパートを VRAM に常駐させれば外部からの転送は発生しません。ここでは「疎に触る重み」同士の桁の比較として示しています。同じ「ランダムアクセス」でも、N-gram はアクティブ重みより 4 桁前後少ない量しか読みません。SSD が苦手なのはランダムかつ大量の読み出しであって、ランダムでも極少量なら遅延だけの問題になります。
帯域として見ると、次の通り NVMe の能力に対して 2〜3 桁の余裕があります。
| デコード速度 | 8 回/トークン(16 KiB ページ) | 32 回/トークン(同) |
|---|---|---|
| 50 tok/s | 6.6 MB/s | 26 MB/s |
| 100 tok/s | 13 MB/s | 52 MB/s |
| 200 tok/s | 26 MB/s | 105 MB/s |
| 参考: NVMe の 16 KiB ランダム読み(300K IOPS) | 約 4.9 GB/s | 同左 |
この見立ては先行研究とも整合します。Engram 論文はアドレスが決定的であることを根拠にホストメモリからの実行時先読みが可能だと述べており、Engram を CXL メモリにプールする研究(arXiv:2603.10087)は、Engram の参照を「記憶容量は大きいが計算は疎で、遅延に寛容なワークロード」と評価して下位メモリ階層へのオフロードに適するとしています(区分 A)。SSD はさらに下の階層ですが、遅延に寛容という性質は同じです。
デコード時の時間予算と先読み
必要になるまでの時間
N-gram の行番号は、新しいトークン ID が確定した瞬間に決まります。一方で、引いたベクトルが必要になるのは次のフォワードパスで注入層に到達した時点です。両者の間が先読みに使える猶予です。
| 時点 | 経過時間(概算) | 内容 |
|---|---|---|
| 0 | 0 | サンプリング完了。トークン ID 確定 |
| 1 | 約 20 µs | GPU から CPU へトークン ID を転送(PCIe の場合。ユニファイドメモリではほぼ 0) |
| 2 | 約 21 µs | ハッシュ計算 |
| 3 | 約 120 µs | NVMe への並列読み出し完了(8 行を同時発行。32 行は SSD の並列度次第で 120〜300 µs、Appendix A) |
| 4 | 約 200 µs | 次ステップ開始。注入層が層 0 付近ならここで必要になる |
| 5 | 約 300 µs | MTP ヘッドが次のドラフトトークンを出力 |
| 6 | 約 1.4 ms | 注入層が層 4 ならここで必要になる(1 層 ≈ 0.3 ms、64 層を仮定) |
| 7 | 20 ms | ステップ終了 |
注入層が入力側にある場合、猶予はステップ間のオーバーヘッド(0.1〜数 ms、エンジン依存)だけです。8 行の読み出し連鎖は約 120〜150 µs なので、最悪でもその程度フォワードパスが注入点で止まる計算になり、20 ms のステップに対して 1% 以下です。32 行を一括発行する場合は、SSD が同時に処理できるユニット数(ダイ数 × プレーン数)を超えた分がページ読み出し時間 tR 単位で待ち行列になるため、並列度の低い SSD では 300 µs 程度まで延びます。手持ちの XPG MARS 980 BLADE 1TB は 8 ダイ × 6 プレーンで約 48 ユニットあるので、32 行でも約 150 µs と見積もっています(Appendix A)。それでも 20 ms のステップに対して 1.5% 以下です。RAM 上のページキャッシュにヒットすれば 100 ns 級で、どの層に注入しても隠れます。
Engram 論文は、Engram が本体の初期層を静的な局所文脈の再構成から解放すると分析しており、27B の参照構成では層 2 と層 15 の 2 箇所に注入しています(区分 A)。Flash-Next も同様なら、最初の注入は浅い層にあると考えて、猶予は短い側(1 ms オーダー)を想定しておくのが安全です。注入が 2 箇所なら参照回数もその分増えますが、いずれもトークン ID だけで決まるので、まとめて先行発行できます。
隠せなかった場合の損失
先読みがまったく効かず、読み出し 1 回分の遅延がそのまま露出したとしても、損失はステップ時間に対する遅延の比率で決まります。デコードが速いほど、また SSD が遅いほど比率は上がります。
| デコード速度 | ステップ時間 | SSD 50 µs | SSD 100 µs | SSD 200 µs | SSD 500 µs |
|---|---|---|---|---|---|
| 50 tok/s | 20 ms | 0.25% | 0.5% | 1.0% | 2.5% |
| 100 tok/s | 10 ms | 0.5% | 1.0% | 2.0% | 5.0% |
| 200 tok/s | 5 ms | 1.0% | 2.0% | 4.0% | 10% |
本記事の想定(50 tok/s、100 µs)では 0.5% で、MoE が 200 tok/s 出るような環境でも 2% にとどまります。負荷でランダム読みが 500 µs まで悪化する SSD だと 1 割に達するので、SSD の実測(fio)が重要になります。
MTP による先読み
Qwen3-Next 系は Multi-Token Prediction(MTP)ヘッドを持ち、vLLM や SGLang では投機的デコードのドラフタとして使えます(区分 A、Qwen3-Next-80B-A3B のモデルカード)。MTP モジュールは 1 層で、Qwen3.8-27B の config.json でも mtp_num_hidden_layers は 1 です。Flash-Next も継承すると仮定すると、MTP は N-gram の先読みに 2 通りの使い方ができます。
| 方式 | 先読み窓 | 備考 |
|---|---|---|
| オンデマンド | 0(注入層到達まで待つ) | 注入点で最大約 120 µs が露出 |
| ステップ間で先行発行(MTP なし) | 0.1〜数 ms | サンプリング直後に発行。SSD の 120 µs はおおむね収まる |
| MTP を投機的デコードに使う(ドラフト k トークン) | 0.25〜1 ms | ドラフト生成中に順次発行し、検証パス開始までに k+1 位置分をそろえる。受理率が高いほどステップ数が減り、露出の機会も減る。32 回の一括読みが 300 µs 近くかかる SSD では、先に必要になる位置の行から順に発行する |
| MTP の予測を先読みヒントに使う(投機検証はしない) | 約 20 ms(1 ステップ) | 本体が t+1 を確定した直後に MTP が t+2 を予測するので、その行を 1 ステップ先に読んでおく。外れれば約 120 µs のオンデマンド読み |
投機的デコードでは、ドラフト位置の行番号はドラフトが出た瞬間に確定するので、検証パスが始まる前にまとめて発行できます。窓は 1 ms 以下ですが SSD の 120 µs は収まります。ヒントとして使う場合は窓が 1 ステップ分に広がる代わりに、MTP の的中率分しか効きません。どちらでも、ドラフトや予測が外れたときに捨てるのは先読みした行だけで、本体側の巻き戻し(Gated DeltaNet の再帰状態や KV の投機ステップ分)は推論エンジンの投機的デコード実装が担う部分です。
プリフィル時の挙動
プリフィルではプロンプトの全トークン ID が最初から分かっているので、全位置の行番号を一括計算して gather できます。各位置は自分を含む直前 N トークンだけを見る因果窓なので、未来のトークンへの依存はなく、計算量は位置数に線形です。
| プロンプト長 | 読み出し回数(8 回/トークン) | M5 Max: SSD 読み(16 KiB、300K IOPS) | M5 Max: 計算(800 tok/s) | RTX 5060 Ti × 2: SSD 読み(4 KiB、500K IOPS) | RTX 5060 Ti × 2: 計算(2,000 tok/s) |
|---|---|---|---|---|---|
| 8K | 65,536 | 0.22 s | 10.2 s | 0.13 s | 4.1 s |
| 32K | 262,144 | 0.87 s | 41 s | 0.52 s | 16.4 s |
| 128K | 1,048,576 | 3.5 s | 164 s | 2.1 s | 66 s |
読み出し時間と計算時間はどちらもプロンプト長に比例するので比率は一定で、ユニーク率 100% の場合、M5 Max で約 2.1%、Linux PC で約 3.2% の上乗せになります。参照数とユニーク率に対する感度は次の通りです。
| 参照数(回/トークン) | ユニーク率 | M5 Max | RTX 5060 Ti × 2 |
|---|---|---|---|
| 8 | 100% | 2.1% | 3.2% |
| 8 | 50% | 1.1% | 1.6% |
| 8 | 25% | 0.5% | 0.8% |
| 16 | 100% | 4.3% | 6.4% |
| 16 | 50% | 2.1% | 3.2% |
| 32(Engram 参照構成の当てはめ) | 100% | 8.5% | 12.8% |
| 32 | 50% | 4.3% | 6.4% |
| 32 | 25% | 2.1% | 3.2% |
参照数が 32 回/トークンでも上乗せは 1 割強にとどまります。コードは同じ N-gram の繰り返しが多く、ユニークな行だけ引けば読み出しはさらに減ります。チャンク化プリフィルであれば、現チャンクの計算中に次チャンクの行を発行して隠すこともできます。プリフィルは高キュー深度で読み出しを発行できるかどうかが鍵で、逐次発行では成立しません。
プレフィックスキャッシュとの関係は素直です。キャッシュが効く範囲は N-gram も再計算不要で、引いたベクトルの効果は後続層の KV キャッシュや Gated DeltaNet の再帰状態に畳み込まれています。N-gram 自体は追加の状態を持ちません。
参照の局所性とページキャッシュ
ハッシュにより空間的な局所性はありませんが、時間的な局所性はあります。自然言語やコードの N-gram 出現頻度は Zipf 的に偏るため、少数のホットな行が参照の大半を占めます。mmap で SSD 上のテーブルを開いておけば、OS のページキャッシュが触った行を RAM に溜め込み、明示的なキャッシュ管理なしにヒット率が上がります。
Zipf 分布を仮定した場合のカバー率を概算します(区分 C、約 1,245 万行、順位 k の参照確率が k の −s 乗に比例すると仮定)。
| RAM にキャッシュした行の割合 | RAM 使用量(8 bit) | s = 0.8 | s = 1.0 | s = 1.2 |
|---|---|---|---|---|
| 0.1% | 約 50 MB | 22% | 59% | 89% |
| 1% | 約 0.5 GB | 38% | 73% | 95% |
| 10% | 約 5 GB | 62% | 86% | 98% |
実際の分布は不明で、複数の N と複数のヘッドを混ぜるとなまる可能性もあります。ただし SystemVerilog や UVM のように定型句が多い領域では、ホット集合はテーブル全体よりはるかに小さいと期待できます。カバー率が 7 割程度でも、残り 3 割が SSD 行きになるだけで、前節の通り 1 回あたりの遅延は 100 µs 級です。
手持ちの環境でのメモリ試算
M5 Max 128GB
KV キャッシュはコンテキスト長に比例するので、先に KV 単独の試算を示します(区分 C、1 トークン 64 KiB)。
| コンテキスト長 | KV(bf16) | KV(q8_0) |
|---|---|---|
| 32K | 2.1 GB | 1.1 GB |
| 128K | 8.6 GB | 4.3 GB |
| 262K | 17.2 GB | 8.6 GB |
判定に使う閾値は次の 3 つです。
| 閾値 | 値 | 意味 |
|---|---|---|
| 既定の GPU wired 上限 | 96 GiB ≈ 103 GB | Metal の recommendedMaxWorkingSetSize。128GB 機で llama.cpp が報告する値 |
| 実用上限の目安 | 約 127 GB | 物理 137.4 GB から OS とその他のアプリ用に 10 GiB(約 10.7 GB)を残した値。sysctl iogpu.wired_limit_mb の引き上げが必要 |
| 物理メモリ | 128 GiB = 137.4 GB | ― |
以下は 262K コンテキストで、KV bf16 17.2 GB にその他の作業領域 3 GB を加えた 20.2 GB を「KV・活性」として計上した試算です。括弧内は KV を q8_0 にした場合(11.6 GB)の合計です。
| 構成 | 本体(GB) | テーブル(GB) | KV・活性(GB) | 合計(GB) | 判定 |
|---|---|---|---|---|---|
| 本体 Q4_K_M + テーブル Q4 常駐 | 75.8 | 30.9 | 20.2 | 126.9(118.3) | 辛うじて(OS の余裕 約 10 GB)。KV q8_0 なら wired 上限の引き上げで可 |
| 本体 Q4_K_M + テーブル SSD | 75.8 | 2(ホット集合) | 20.2 | 98.0(89.4) | 既定上限内で可 |
| 本体 Q5_K_M + テーブル Q4 常駐 | 89.1 | 30.9 | 20.2 | 140.2(131.6) | 不可(KV q8_0 でも OS の余裕 約 6 GB) |
| 本体 Q5_K_M + テーブル SSD | 89.1 | 2 | 20.2 | 111.2(102.7) | wired 上限の引き上げで可。KV q8_0 なら既定上限とほぼ同じ |
| 本体 Q6_K + テーブル SSD | 103.1 | 2 | 20.2 | 125.3(116.7) | wired 上限の引き上げで可(OS の余裕 約 12 GB、KV q8_0 なら約 21 GB) |
| 本体 Q8_0 + テーブル SSD | 132.8 | 2 | 20.2 | 155.0(146.4) | 不可 |
bpw は Q4_K_M 4.85、Q5_K_M 5.7、Q6_K 6.6、Q8_0 8.5 を仮定しています。
Metal は GPU が使える wired メモリの上限(recommendedMaxWorkingSetSize)を既定で物理メモリの 7 割台に設定しており、128GB 機では llama.cpp のログに 98,304 MiB = 96 GiB と報告されます(比率は機種で幅があり、M2 Max 32GB では 78% という報告もあります)。超える場合は sysctl の iogpu.wired_limit_mb を引き上げます。再起動不要ですが、再起動すると既定値に戻ります。テーブルを SSD に置く構成では、262K のフルコンテキストでも本体を Q6_K に上げられ、KV を q8_0 にすれば余裕も十分です。テーブルを RAM に常駐させる構成では、フルコンテキストでは本体 Q4 でも OS の余裕が 10 GB 前後まで削られます。コンテキストを 32K 程度に絞る運用なら KV は 2 GB 程度なので、上の表から約 15 GB を差し引いて読めます。
Linux PC(Ryzen 9 7950X、DDR5 128GB、RTX 5060 Ti 16GB × 2)
| 配置 | 内容 | サイズの目安 |
|---|---|---|
| VRAM 32GB | アテンション層、共有エキスパート、GPU キャッシュ分のエキスパート、KV キャッシュ | KV は 262K で bf16 約 17 GB、q8_0 約 9 GB。フルコンテキストでは VRAM の半分近くを占めるため、KV の量子化かコンテキストの制限が必要 |
| ホスト RAM 128GB | 本体のエキスパート | Q4 で最大 76 GB、Q6_K で 103 GB |
| SSD(XPG MARS 980 BLADE 1TB、PCIe 5.0) | N-gram テーブル | Q4 で 31 GB、Q8 で 51 GB。ページキャッシュがホット集合を保持。ドライブの内部並列性は Appendix A |
こちらは RAM に全部入る規模なので SSD オフロードは必須ではありませんが、テーブルを SSD に逃がした分のホスト RAM を本体の高精度化に回せます。前回の FreeToken 記事で試算した通り、DeepSeek-V4-Flash-0731 の FP4 エキスパートプールは約 140 GB でホスト RAM 128GB を超えました。「大きいが薄く触る」重みを SSD へ出せる設計は、この種の壁を越える方向として歓迎できます。
実装上の論点
| 論点 | 内容 | 区分 |
|---|---|---|
| テーブルを GPU バッファにしない | 1 トークン数十〜数百 KiB なので、CPU 側で gather してから小さなバッファで GPU に渡せば十分。Metal がバッファ全体を wired にする問題や、GPUDirect Storage の必要性を回避できる | C |
| 先読み(readahead)の抑止 | 空間的局所性がないので、Linux は madvise(MADV_RANDOM)、macOS は fcntl(F_RDAHEAD, 0) 相当で無駄なページインを避ける | C |
| 非同期 I/O | プリフィルでは数十万〜百万回の読み出しを高キュー深度で発行する必要がある。Linux は io_uring、macOS はスレッドプールと pread、または dispatch_io | C |
| SSD の並列度 | 一括発行が効くのは並列ユニット数(ダイ数 × プレーン数)の範囲まで。それを超えた分は tR 単位で待ち行列になる。1TB クラスの少ダイ品や独立プレーン読み非対応の NAND では 32 回で 300 µs 程度。手持ちの XPG MARS 980 BLADE 1TB は約 48 ユニット(Appendix A) | C |
| 行の物理配置 | 1 行が連続配置なら 1 読み出しで済む。ヘッドごとに行の一部を引く構成や、列分割・スケールの分離があると読み出し回数が増える | 未確認 |
| テーブルの量子化 | 埋め込みテーブルは低ビット量子化に強い傾向があるが、Flash-Next での品質影響は未確認 | 未確認 |
| ハッシュの計算場所 | トークン ID だけで決まるので CPU で計算できる。GPU 上でサンプリングする場合は ID の転送が 1 回入る | C |
| 推論エンジンの対応 | llama.cpp、MLX、vLLM、SGLang のいずれも新演算子の対応が必要。Qwen3-Next の Gated DeltaNet では llama.cpp の対応が遅れた前例がある。Unsloth は day-0 対応を「目指す」と表明しているが確約ではない | B |
MoE エキスパートのオフロードとの違い
| 項目 | MoE エキスパート | N-gram テーブル |
|---|---|---|
| 必要な重みが決まる時点 | 各層でルータが hidden state を計算した後 | トークン ID 確定時(フォワードパス前) |
| 1 トークンあたりの読み出し量 | GB 級 | 数十〜数百 KiB |
| 律速要因 | 帯域 | 遅延(並列化で隠蔽可能) |
| 現実的な置き場所 | VRAM とホスト RAM | SSD でも可(本記事の主張) |
| 先読み | 困難(ルーティングの予測が必要) | 容易(MTP でさらに延長できる) |
FreeToken がエキスパートをホスト RAM に置き、PCIe 転送とホスト処理の実測帯域の比で CPU 実行と GPU 転送を配分しているのは、エキスパートが帯域勝負だからです。N-gram テーブルは同じ「疎に触る大きな重み」でも律速要因が違うため、別の扱いが適しています。
リリース後に確認する項目
| 項目 | 確認方法 | 本記事の仮定 | 参考値(Engram-27B) |
|---|---|---|---|
| N-gram 埋め込みの機構 | モデルカード、技術レポート、推論コード | Engram 型のハッシュテーブル | ― |
| 注入層の位置と数 | config.json、モデリングコード | 初期層 1 箇所 | 層 2 と層 15 の 2 箇所 |
| 1 トークンあたりの参照数 | N の範囲 × ヘッド数 × 注入層数 | 8 回 | 最大 N = 3、ヘッド 8 |
| 行の次元とサイズ | config.json | 4096、4 KiB(8 bit) | 1280 |
| テーブルの物理配置 | safetensors のテンソル形状 | 行が連続 | ― |
| 実際のデコード速度 | MLX / llama.cpp での実測 | 50 tok/s | ― |
| SSD のランダム読み性能 | fio で 4 KiB / 16 KiB ランダム読みを QD1 / 8 / 32 で回し、完了遅延の p50 と p99 を取る(手順は Appendix A.6) | QD1 100 µs、8 回 120 µs、32 回 120〜300 µs、300K〜500K IOPS | ― |
| ホット集合の大きさ | SystemVerilog / UVM のプロンプトで参照行のユニーク数と再参照率を計測 | Zipf 的 | ― |
| 推論エンジンの対応状況 | llama.cpp、MLX、vLLM、SGLang の issue / PR | 未対応から開始 | ― |
注入が 3 層以上、または参照が 32 回/トークンを大きく超える場合は、プリフィルの上乗せが 1 割を超えてくるので、「デコードは隠せるがプリフィルは高キュー深度が必須」という但し書きが強くなります。逆に Engram-27B に近い構成(次元 1280、注入 2 層)なら、1 回あたりの読み出しが小さくなる分、デコードへの影響 1% 未満という結論はより強固になります。
まとめ
Flash-Next の N-gram 埋め込みが、学習済みの固定テーブルをハッシュで引く仕組みだと仮定すると、それは「ランダムアクセスだが極少量」という、MoE エキスパートとは逆の性質を持ちます。1 トークンあたり数十〜数百 KiB、行番号は前もって分かり、参照は偏る。この 3 点から得られた概算を一覧にします。
| 指標 | 概算 | 主な前提 |
|---|---|---|
| デコードへの影響(露出時の最悪値) | 0.5%(8 回)、最大 1.5%(32 回、並列度の低い SSD) | 50 tok/s、一括発行の完了時間 100〜300 µs(Appendix A) |
| デコードの帯域要求 | 30 MB/s 未満 | 32 回 × 16 KiB × 50 tok/s |
| プリフィルの上乗せ | 2〜3%(8 回)、9〜13%(32 回) | ユニーク率 100%、高キュー深度で発行 |
| ページキャッシュのカバー率 | 73%(テーブルの 1% ≈ 0.5 GB を常駐、Zipf s = 1.0) | 分布は仮定 |
| M5 Max 128GB での本体量子化 | Q6_K まで(262K、KV bf16 で余裕 約 12 GB) | テーブルを SSD に配置、wired 上限を引き上げ |
| Linux PC での効果 | ホスト RAM の 31〜51 GB を本体側に回せる | テーブルを SSD に配置 |
手持ちの M5 Max 128GB では 262K のフルコンテキストでも本体を Q6_K に上げる余地が生まれ(KV を q8_0 にすれば余裕は約 21 GB)、Linux PC ではホスト RAM を本体側に回せます。前提はすべて未確認です。リリース後にモデルカードで仮定を差し替え、改めて報告します。
Appendix A: SSD の内部並列性と手持ちの SSD での見積もり
本文では「8〜32 行を並列発行すれば 100 µs 台で完了する」と仮定しましたが、並列発行が効くのは SSD が同時に処理できるユニット数までです。ここではその仕組みを整理し、自分の Linux PC に載せている XPG MARS 980 BLADE 1TB(型番 SMAR-980B-1TCS-DP)で実際にどうなるかを見積もります。
A.1 ランダム読み 1 回の遅延の内訳
| 要素 | 典型値 | 区分 | 備考 |
|---|---|---|---|
| NAND のページ読み出し tR | TLC で 40〜56 µs(BiCS6 50、BiCS5 56、Samsung V7 40、V6 45、SK hynix V7 50) | B | 世代比較記事の値。QLC は参照電圧の段数が多く、さらに長い |
| チャネル転送(4 KiB) | 1.7〜2.6 µs | C | 2400 / 1600 MT/s からの計算 |
| ECC(LDPC)デコード | 数 µs | B | パイプライン化される |
| FTL の論理→物理変換 | 1〜2 µs | B | DRAM 搭載品で L2P テーブルが DRAM にある場合 |
| ホスト側(NVMe ドライバ、PCIe 往復) | 10〜20 µs | B | OS とドライバ経路で変わる |
| 合計(QD1 の実測レンジ) | 20〜70 µs | B | Optane 系は 10 µs 未満 |
tR が支配的で、残りは小さな固定費です。以降の見積もりでは tR 40 µs、固定費 10 µs、チャネル転送 2 µs を使います(区分 C)。
A.2 チャネル・ダイ・プレーン
SSD コントローラは複数の NAND チャネルを持ち、各チャネルに複数のダイ(チップ)がぶら下がります。ダイの内部はさらにプレーンに分かれています。ランダム読みの並列性を決めるのは次の三つです。
| 階層 | 並列性への効き方 | 区分 |
|---|---|---|
| チャネル | チャネル上で直列化されるのはデータ転送(4 KiB で約 2 µs)だけ。同じチャネル上の別ダイの tR は同時に進む(チャネルインターリーブ) | B |
| ダイ | 独立にページ読み出し(tR)を進められる単位。ドライブ容量 ÷ ダイ容量が総数で、1TB に 1 Tb ダイなら 8 個 | B |
| プレーン | 従来は同じダイの複数プレーンを同時に読むには同じページアドレスが必要だったが、独立プレーン読み出し(AIPR や独立マルチプレーン読み出しなど、メーカーごとに呼称が異なる)に対応した NAND では、各プレーンが別々のアドレスを同時に読める | A(特許 US12293085B2、Micron のプレスリリース) |
したがってランダム読みの同時処理数は、おおむね「ダイ数 × プレーン数(独立プレーン読み対応の場合)」で、IOPS の上限はそれを tR で割った値に近づきます。コンシューマ SSD が公称で 100 万 IOPS 超を謳えるのはこのためで、8 チャネルという数字だけでは決まりません。逆に 512 GB〜1 TB の少ダイ品、独立プレーン読み非対応の NAND、QLC、DRAM レス品では並列度が下がります。
A.3 一括発行と待ち行列
k 本の読み出しを一括発行すると、各読み出しはハッシュで決まる行に応じて S 個のユニットのどれかに落ちます。同じユニットに複数落ちた分は tR 単位で待ち行列になるので、一括の完了時間は「最も混んだユニットの負荷 × tR」で決まります。これは balls-into-bins と呼ばれる古典的な問題で、最大負荷の期待値をモンテカルロで求めると次の通りです(区分 C、各 4,000 試行)。
| 一括発行本数 k | S = 8 | S = 16 | S = 48 | S = 96 |
|---|---|---|---|---|
| 8 | 2.6 | 2.1 | 1.5 | 1.3 |
| 32 | 7.1 | 4.8 | 3.0 | 2.4 |
完了時間を「固定費 10 µs + tR 40 µs × ユニットの最大負荷 + チャネル転送 2 µs × チャネル(8 本)の最大負荷」として計算した結果が図13 です。
| 構成 | 8 回一括 | 32 回一括 |
|---|---|---|
| 8 ユニット(1TB、8 ダイ、独立プレーン読みなし) | 約 120 µs | 約 310 µs |
| 16 ユニット(2TB、16 ダイ、独立プレーン読みなし) | 約 100 µs | 約 220 µs |
| 48 ユニット(XPG 1TB: 8 ダイ × 6 プレーン) | 約 75 µs | 約 150 µs |
| 96 ユニット(XPG 2TB: 16 ダイ × 6 プレーン) | 約 65 µs | 約 120 µs |
本文の「32 回で 120〜300 µs」はこの表の幅です。8 回なら構成によらず 100 µs 前後に収まり、32 回では並列度で 2 倍以上の差が出ます。
A.4 手持ちの SSD: XPG MARS 980 BLADE 1TB
| 項目 | 内容 | 区分 | 出典 |
|---|---|---|---|
| 型番 | SMAR-980B-1TCS-DP。末尾の -DP はドスパラ限定モデルを示す流通用の記号で、中身は標準の SMAR-980B-1TCS と同一と見られる | B | ドスパラ、価格.com の表記 |
| インターフェース | PCIe 5.0 x4、NVMe | A | XPG 公式 |
| コントローラ | Silicon Motion SM2508。8 チャネル、最大 32 CE、3600 MT/s、Arm Cortex-R8 × 4、TSMC 6 nm、公称 2.5M IOPS | A / B | Silicon Motion 公式、AnandTech |
| NAND | Micron 232 層 3D TLC(B58R)。1 Tb ダイ、6 プレーンで各プレーン独立読み出し | A(NAND 仕様)/ B(搭載品の同定はレビュー) | Micron プレスリリース、レビュー各誌 |
| 1TB のダイ数 | 8(NAND パッケージ 2 個 × 4 ダイ) | C | 容量からの推定 |
| DRAM | 2 GB(Samsung K4A8G165WC-BCTD × 2)。DDR4 か LPDDR4 かはレビューで表記が揺れる | B | レビュー各誌 |
| 公称性能(1TB) | シーケンシャル読み 14,000 MB/s、書き 10,000 MB/s、4K ランダム読み 1,600K IOPS、書き 1,650K IOPS | A | XPG 公式(KitGuru 掲載) |
| 2TB / 4TB | 4K ランダム読み 2,000K / 1,950K IOPS。ダイ数が 16 / 32 に増えるため | A | XPG 公式 |
| TBW、保証 | 740 TB、5 年 | A | XPG 公式 |
| サーマル | ランダム読み主体では実害なし。連続書き込みでコントローラ 87 ℃ 到達の報告あり | B | レビュー各誌 |
実測レビューは次の通りです。いずれも 2TB モデルですが、QD1 の遅延は tR 律速で容量にほぼ依存しません。
| レビュー元 | ツール | 条件 | 値 |
|---|---|---|---|
| Tom's Hardware | 独自レイテンシ測定 | 4 KiB 読み QD1 | 38.47 µs |
| KitGuru | 独自 QD スイープ | 4 KiB 読み QD1、1 スレッド | 19,530 IOPS ≈ 51 µs |
| KitGuru | CrystalDiskMark 8 | RND4K Q1T1 読み | 81.37 MB/s ≈ 19,800 IOPS ≈ 50 µs |
QD1 の実測 38〜51 µs はホスト側を含む値なので、tR は 30〜45 µs 程度と逆算できます。A.3 のモデルに当てはめると、このドライブの 1TB モデルでは 8 回一括で約 75 µs、32 回一括で約 150 µs です。本文の 32 回の上限 300 µs よりかなり良く、8 ダイしかなくても 6 プレーンの独立読み出しが効いています。ただし 8 ダイ・6 プレーンは推定なので、A.6 の fio で確かめます。
補足として、2TB モデルはダイ数が 16 になるので 32 回一括が約 120 µs に縮み、公称 IOPS も 2,000K に上がります。N-gram テーブルは 8 bit でも 51 GB なので、容量面では 1TB で十分です。
A.5 Apple シリコン Mac の内蔵 SSD
M5 Max の内蔵 SSD はコントローラが SoC 内蔵で、NAND パッケージ数(Pro / Max で 4〜8)と ioreg の Controller Characteristics(dies-per-bus、bus-to-msp)から構成を推し量れるとされています。シーケンシャルは M5 世代で 6 GB/s 超の報告がありますが、4 KiB / 16 KiB ランダム読みの QD1 遅延と QD32 の IOPS を公開した実測はほとんど見つかりませんでした(区分 B、未確認)。tR 律速である以上 QD1 は 40〜60 µs 級と推定しますが、macOS の I/O 経路は Linux より重いので、A.6 の手順で実測するまでは本文の 100 µs を保守側の仮定として維持します。
A.6 fio による確認手順
Linux(Ryzen 9 7950X):
# 32 GB のテストファイルを用意(テーブルと同じ SSD 上に)
fio --name=prep --filename=/mnt/nvme/ngram_test.bin --size=32G --rw=write --bs=1M --direct=1
# QD1 / 8 / 32 の完了遅延(p50 / p99)
for qd in 1 8 32; do
fio --name=q$qd --filename=/mnt/nvme/ngram_test.bin --size=32G --rw=randread --bs=4k \
--direct=1 --ioengine=io_uring --iodepth=$qd \
--iodepth_batch_submit=$qd --iodepth_batch_complete_min=$qd \
--norandommap --randrepeat=0 --time_based --runtime=30 --lat_percentiles=1
done
iodepth_batch_submit と iodepth_batch_complete_min を QD と同じ値にすると、k 本を一括発行して全部そろうまで待つ動作になるので、clat の p99 が「一括の完了時間」に近づきます。判定の目安は次の通りです。
| 結果 | 読み方 |
|---|---|
| QD32 の p99 が 150 µs 以内 | A.4 の推定通り。32 回/トークンでも本文の結論に余裕がある |
| 150〜300 µs | 並列度が推定より低い。デコードは 1.5% 以下の露出で済むが、プリフィルは QD をさらに積む |
| 300 µs 超 | ダイ数かプレーン独立読みが想定と違う。ホスト RAM 128GB を活かしてテーブルを RAM 常駐に切り替えるか、2TB 以上のモデルを検討 |
macOS(M5 Max)は Homebrew の fio で同じ測定ができます。ioengine は posixaio、direct=1 は F_NOCACHE 相当、bs は 16k にします。












