Google DeepMind が 2026/6/10 に公開した DiffusionGemma(拡散でテキストを生成する実験的オープンモデル)を、llama.cpp + 4bit量子化(GGUF)で Colab の L4 上で実際に動かしてみました。
「動かせる」こと自体は Unsloth が手順を公開しています。本記事では実際に Colab L4 で動かし、速度と品質を測って 長けた点と課題 をまとめます。
先に結論を言うと——長所は「早く確信に達するタスクほど速い、という拡散ならではの動的な速さ」、課題は「(量子化+llama.cppでは)未マージで自前ビルドが要る運用の重さ」と「試した言葉遊びでの日本語の取りこぼし」でした。
ハイライト
長けた点(現状はほぼ速度)
- 早く確信に達しやすいタスクほど速い(拡散の適応停止=確信したら早期打ち切り)。L4/Q4 で実効 62〜132 tok/s(出力長を伸ばせば最大154)、事実質問(P1)132・数列(P5)122 が爆速。今回の計測では速度は出力長より denoising ステップ数に強く依存。
- 固定48ステップ(25.8 tok/s)比で最大5倍。今回の計測で速さに最も効いていたのは、256並列キャンバスより適応停止(早期打ち切り)でした。
- 同条件の自己回帰版 Gemma 4(約56 tok/s)と直接比較: 確信タスクで約2.4倍速、難タスクで拮抗。生成方式だけを変えたフェアな対照(同 P1-P6 / 同 Q4_K_M / 同 L4 / 同 llama.cpp)。
課題
-
量子化+llama.cpp 経路が未成熟: llama.cpp の diffusion 対応は未マージ(PR #24423)。pip wheel・Ollama になく、専用
llama-diffusion-cliの自前ビルド必須(筆者環境で約11分)。※大容量GPUがあれば vLLM/Transformers は公式に動く。 - 今回試した日本語の言葉遊び(P2)では自己回帰版より明確に弱い: 「すもも/もも/係助詞"も"の区別」を拡散はほぼ無回答、自己回帰版は正しく分解(P2の1タスクなので日本語全般の結論ではない)。品質は全般に本家 Gemma 4 より下。
- ※ 英語思考・冗長thinking・thinkingが予算を食う点は拡散固有ではなく Gemma 4 共通の癖(自己回帰版でも同じ)。同条件の対照実験で切り分け。
DiffusionGemma とは
ふつうの LLM はトークンを1個ずつ左から生成します(自己回帰)。DiffusionGemma は違って、256 トークンの「キャンバス」をノイズから一気に並列で denoise(ノイズ除去)して作る「離散拡散」方式です。
正確には ブロック拡散(block diffusion) と呼ばれる、拡散と自己回帰のハイブリッドです。文章を 256 トークンの「キャンバス(ブロック)」に区切り、各ブロックの中身は拡散で並列生成、ブロックの並べ方は自己回帰で進めます。画像生成のような“全体を一気に拡散”する純粋拡散とは違い、長文の安定性のために自己回帰を組み合わせた方式です。
- アーキは Gemma 4 の 26B A4B MoE(総 25.2B / アクティブ 3.8B、128エキスパート中8active+shared1)
- キャンバス長 256、コンテキスト最大 256K、テキスト+画像入力
- 1 forward pass で 15〜20 トークン生成、H100/FP8 では 1100 tok/s 超を主張(※L4ではそこまで出ません。後述)
- 品質は本家 Gemma 4 より低め(速度特化)
DiffusionGemma は encoder-decoder 構成です。プロンプトは自己回帰エンコーダが(ふつうの LLM と同じ因果的な読み方で)処理して KV キャッシュ化し、デコーダがキャンバスを 双方向 attention(前後を見渡す)でノイズ除去します。「左から1個ずつ」ではなく前後を見渡して一括で直せるのが、並列生成できる理由です。ちなみに“ノイズ”は [MASK] ではなく語彙からのランダムなトークンです。
生成の流れは、256トークンのキャンバスを1ブロックとして仕上げ、それを文脈(KVキャッシュ)に積んで次のブロックへ——と、ブロック単位で順に進みます。
そして1つのキャンバスは一発で決まるのではなく、ノイズ除去(denoise)を数回くり返して仕上げます。この反復回数が「denoising ステップ数」。十分に確信できたら最後まで回さず途中で打ち切るのが「適応停止」で、これが後で速度を大きく左右します。
環境構築でハマった点(ここが一番の山)
前提として、「llama.cpp + 量子化で動かせる」こと自体は Unsloth の公式ドキュメント が手順を公開しており、既知です。ただし PR #24423 は未マージで、公式リリース・pip wheel・Ollama(対応要望Issueがopen)には入っておらず、専用
llama-diffusion-cliの自前ビルドが必要な bleeding edge 段階です。以下、実際に動かして詰まった点をまとめます。
「60GB必須」の抜け道
Google の推論ノートブック(inference-diffusiongemma-with-hf)には「60GB超のメモリを持つ GPU が必要(NVIDIA G4またはNVIDIA H100)」という注記があり(原文: "requires a GPU which has more than 60GB of memory")、最初は「Colab Pro の A100(40GB) でも無理では」と思いました。でもこれは BF16(52GB) の話。量子化版を見ると要件はガラッと変わります。
補足: この「60GB超」は HF のモデルカード(モデルページ)には書かれておらず、推論ノートブック側の注記です。モデルカードは GPU メモリ要件を明記していません。
| 量子化 | 必要メモリ | L4(22.5GB) |
|---|---|---|
| 4-bit | 18GB | ✅ 余裕 |
| 5-bit | 20GB | ✅ |
| 6-bit | 24GB | ❌(A100) |
| 8-bit | 28GB | ❌(A100) |
| BF16 | 52GB | ❌ |
→ 4bitなら安いL4で動く。A100が不要でした。
(この必要メモリの目安は Unsloth のドキュメント より。表の「L4」は公称 24GB・実利用は約 22.5GB 枠で判定。)
llama.cpp の diffusion 対応は「未マージ+専用バイナリ」
ここが本番。普段 llama.cpp は pip install llama-cpp-python のプリビルト wheel で済ませていますが、今回はそれが一切使えません。
- diffusion 対応は llama.cpp 本体に未マージ(PR #24423、執筆時点レビュー中)→ どの wheel にも入っていない
- 通常の
llama-cli/llama-serverでは動かず、専用のllama-diffusion-cliが要る →llama-cpp-pythonの Python API にも存在しない - 見つかったコミュニティ製のプレビルト配布は sm_86(RTX30系)+glibc≥2.39 専用で、Colab(L4 sm_89 / Ubuntu22.04)では動かなかった
結局 Colab上でソースビルドするしかありません。ただし1ターゲットだけ+アーキを実機に絞れば、筆者環境のL4で約11分で済みました。
# PR #24423 を取得し、llama-diffusion-cli だけを L4(sm89) 向けにビルド
git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp
git fetch origin pull/24423/head:diff && git checkout diff
cmake -B build -DGGML_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES=89 -DLLAMA_CURL=OFF
cmake --build build -j --config Release --target llama-diffusion-cli
ビルド済みバイナリ(llama-diffusion-cli + *.so)を Google Drive に保存しておけば、次のセッションは数秒で復元・再ビルド不要です。「1セッション1条件で回してセッションを消す」運用と相性が良い。
地味にハマった: libcuda.so.1 cannot open
CLI を Python の subprocess で叩くとき、LD_LIBRARY_PATH をバイナリのディレクトリで丸ごと上書きしたら、Colab 既定の CUDA ドライバの場所(/usr/lib64-nvidia)が消えて error while loading shared libraries: libcuda.so.1 で落ちました。上書きせず追記で解決:
env = dict(os.environ)
env['LD_LIBRARY_PATH'] = ':'.join(p for p in [BIN_DIR, env.get('LD_LIBRARY_PATH',''), '/usr/lib64-nvidia'] if p)
計測方法
-
llama-diffusion-cliを subprocess で起動し、出力末尾のスループット行をパース -
クロック固定(
nvidia-smi -lgc/-lmcで最大に)→ 共有VMのガバナー変動を抑制。結果、cv 0.1〜0.3% と非常に安定 - 各条件 n=3〜5 試行の中央値、結果は Drive の CSV に追記
- モデルロードは毎回約16秒だが、計測する
eff_tok_sは生成のみのスループットなので影響なし
スループットには2種類ある(混同注意)
実機の出力はこうです:
throughput: 65.9 tok/s (256 tok in 3882.76ms),
in-step parallel 1187 tok/s (256-tok canvas x 18.0 steps/block)
18 steps over 1 block, time per step: 215.71ms
| 指標 | 値(L4/Q4) | 意味 |
|---|---|---|
| 実効スループット | 65.9 tok/s | 体感する「実際に出てくる速度」。本記事で使うのはこちら |
| in-step parallel | 1187 tok/s | 256位置×18ステップを並列処理した「計算量ベース」の数字 |
Google の「H100/FP8 で 1100 tok/s 超」は実効値の主張。L4 の in-step parallel(1187) がたまたま近いだけで別物です。L4 の実効は数十〜150 tok/s 台(本記事の測定範囲)。
使ったプロンプト(P1〜P6)
計測には、この検証シリーズで共通利用しているテスト用プロンプト(prompts.json)を使いました。以降の表・本文に出てくる P1〜P6 は次の通りです。
| ID | 内容 | ねらい |
|---|---|---|
| P1 | 「日本の首都はどこですか。一言で。」 | 短い事実質問 |
| P2 | 「すもももももももものうち」に果物名はいくつ? | 日本語のひっかけ(言葉遊び) |
| P3 | 早口言葉「woodchuck…」に果物名はいくつ?(英語) | 英語のひっかけ |
| P4 | 長文(4k/8kトークン)の日本語要約 | 長い入力の処理(※速度比較では未使用) |
| P5 | 「1〜200をカンマ区切りで」 | 長く・内容が決まりきった出力 |
| P6 | 天気取得APIの関数呼び出し | 構造化出力(tool use) |
結果A: 速度を決めるのは「出力長」ではなく「ステップ数」
上記のうち短い P1/P2/P3/P5/P6 を、同じ -n 256(-n は生成トークンの上限。256=1キャンバス分)で回しました。
| プロンプト | 実効 tok/s | denoising steps |
|---|---|---|
| P1 日本の首都は?(一言で) | 132.0 | 8 |
| P5 1〜200を順に書く | 122.1 | 9 |
| P3 早口言葉に果物名は何個(英語) | 81.0 | 14 |
| P6 関数呼び出し(tool use) | 77.1 | 14 |
| P2 「すもももももももものうち」の果物名は何個 | 61.7 | 19 |
全部 n=256 で出力長は同じなのに、速度が約2倍違う。理由はシンプルで:
- 1ステップの時間はほぼ一定(〜225ms = 256キャンバスを1回 denoise するコスト)
- 実効 tok/s ≒ 256 ÷ (steps × 0.225s) → ステップ数に反比例
- このEBサンプラー設定では、ステップ数は entropy/confidence 条件による早期停止に大きく左右される(適応停止)
事実質問(P1)や単純な数列(P5)は答えが確定的でエントロピーが低く、すぐ収束(8-9ステップ)。逆に P2「すもも」のような“ひっかけ”は最遅(19ステップ) —— モデルが確信に達しにくいほどステップが増えます。今回の測定では、速度は出力長よりも“モデルがどれだけ早く確信に達するか”に強く左右されました。自己回帰では(内容に依らず一定なので)見られない挙動です。
結果B: 出力長に対しては「山なり」
P5(1〜200をカンマ区切りで=決定的に長い出力)で -n を変えました。
| -n | tok/s | steps | blocks | n_tok |
|---|---|---|---|---|
| 256 | 122.2 | 9 | 1 | 256 |
| 512 | 154.3 | 14 | 2 | 512 |
| 1024 | 138.6 | 27 | 4 | 1024 |
- 512でピーク(154 tok/s)→ 1024で低下(139)。1ステップあたり確定トークン数は 28→37 と増えており、1ブロック目の固定オーバーヘッドが2ブロックで薄まるのが効いていそう。
- 長くなると1ステップ時間が伸びる(233→237→274ms)。ブロックを順に積み上げる方式なので、後ろのブロックほど長い文脈を見るためと思われる(attention コストは直接は未計測)。ただし上昇は緩やか(4ブロックで約17%)。
- P5 は数列なのでエントロピーが低く、1ブロックあたり 5〜9ステップと少ない(A の P2=19ステップと対照的)。長い出力でも“内容が確定的”なら高速を保てる好例。
結果C: 今回の計測で速さに最も効いていたのは「適応停止」
P2(すもも)で早期停止を無効化(--diffusion-eb-confidence 0.0)し、常に48ステップ回す設定と比較しました。
| tok/s | steps | |
|---|---|---|
| adaptive(早期停止あり) | 61.7 | 19 |
| fixed 48(早期停止なし) | 25.8 | 48 |
2.4倍速。1ステップ時間は同じ(〜210ms)なので、差は純粋にステップ数だけです。つまり 固定ステップにすると DiffusionGemma は 25.8 tok/s まで落ちる(後述の結果Eのとおり、同じ Gemma 4 の自己回帰版56 tok/s よりむしろ遅い)。「拡散だから速い」というより、今回の計測では“確信したら途中で止める”適応停止の寄与が最も大きく見えました(Google は並列デコードやブロック拡散自体も高速化の要因として挙げています。本記事で切り分けられたのは適応停止の効果まで)。
1ステップ時間が内容に依存しない(〜210ms一定)ので、固定48は全タスクで約25.8 tok/s になります。するとAの各タスクが適応停止で得ている倍率が出せます:
| タスク | 適応 tok/s | 固定48比 |
|---|---|---|
| P1 日本の首都 | 132.0 | 5.1倍 |
| P5 1〜200 | 122.1 | 4.7倍 |
| P3 早口言葉(英語) | 81.0 | 3.1倍 |
| P6 関数呼び出し | 77.1 | 3.0倍 |
| P2 すもも | 61.7 | 2.4倍 |
適応停止は、確信が持てるタスクほど効く(P1で5.1倍、迷うP2で2.4倍)。
結果D: 出力品質 —「Gemma 4 共通の癖」と「今回のタスクで見えた拡散側の弱点」を切り分ける
速度だけでなく実際の生成テキストも P1-P6 で取り、自己回帰版 Gemma 4 と同一プロンプトで見比べました。すると、当初「拡散の弱点」に見えたものの多くが、実は Gemma 4 ファミリー共通の癖だと分かりました。対照実験をやった甲斐がここに出ます。
Gemma 4 共通(自己回帰版でも同じ)
-
思考(thinking)が日本語プロンプトでも英語。拡散も自己回帰も英語で考え、最後だけ日本語に訳す:
[拡散] <|channel>thought * Question: "日本の首都..." ... <channel|>東京です [自己回帰] * Question: "日本の首都..." ... [End thinking] 東京 -
thinking が長くトークン予算を食う。両者とも P2/P3 では思考の再確認に
-nを使い切りがち(自己回帰版も 512 トークンで最終回答に届かないことがある)。
→ つまり「思考が英語」「冗長な思考」は拡散固有ではなく Gemma 4 全体の特性。
今回のタスクで見えた、拡散側の弱点(P2)
-
難しい日本語のひっかけ(P2「すもももももももものうち」)で拡散はほぼ無出力(
* Input sentence: 『すで停止)。一方、自己回帰版は すもも=Plum / もも=Peach と正しく分解できる:生成方式の違いが品質に出た一例です。ただし これは P2 という1タスクの観察で、「日本語全般が弱い」と一般化できる根拠(JA-MMLU 等のベンチ)は測っていません。[拡散] * Input sentence: 『す ← ほぼ何も出ない [自己回帰] すもも(Sumomo)=Plum / も=particle / もも(momo)=Peach / ... ← 正しく解析
構造化・短答は拡散も問題なし
- P1(東京)✅ / P6(正しい JSON 関数呼び出し)✅ / P3(英語の「0個」正解)✅ / P5(数列生成)✅。
→ まとめると、英語思考・冗長thinkingは Gemma 4 共通で拡散の弱点ではなく、今回の言葉遊び(P2)では拡散側だけが取りこぼした(自己回帰版は解けた)。本家 Gemma 4 の方が品質は上、という公式の位置づけとも整合します。用途を選べば(短答・構造化・英語)拡散も十分実用、というのが実機の感触です。
結果E: 自己回帰版 Gemma 4 26B A4B との直接対決
いちばん知りたかった比較です。DiffusionGemma の土台になった自己回帰版 Gemma 4 26B A4B(unsloth GGUF)を、同じ Q4_K_M・同じ L4・同じ llama.cpp ビルドで測りました(生成方式だけが違う対照実験)。
自己回帰版の decode は 約56 tok/s(同一P1-P6で 55.5〜56.8 とほぼ一定=内容に依らない)。prefill は速く、llama-bench の pp512 で 2509 tok/s。拡散と並べると:
| タスク | 拡散 tok/s | 自己回帰(約56 tok/s)比 |
|---|---|---|
| P1 首都 | 132 | 2.4倍速 |
| P5 1〜200 | 122 | 2.2倍速 |
| P3 早口言葉(英) | 81 | 1.4倍速 |
| P6 関数呼び出し | 77 | 1.4倍速 |
| P2 すもも(難) | 62 | 1.1倍(ほぼ拮抗) |
| 拡散・固定48ステップ | 26 | 0.46倍(逆に遅い) |
結論は明快です:
- 確信できるタスク(事実・数列)では拡散が自己回帰の2倍以上速い(P1で2.4倍)。
- 難しいタスク(P2)では拮抗(62 vs 56)。迷うほど拡散はステップが増え、優位が消える。
- 適応停止を切ると拡散は自己回帰より遅い(26 vs 56)。
つまり 拡散の速さは「適応停止が効く場面」限定。タスクを選べば確かに速いが、万能の高速化ではない——というのが同条件比較の答えでした。なお prefill(長い入力の読み込み)は自己回帰が 2509 tok/s と非常に速く、長文入力用途では自己回帰が依然強い領域です。
特徴と問題点(整理)
実機で触ってみて分かった、DiffusionGemma の特徴と問題点を整理します。
特徴(強み)
現状はっきり言える強みは、ほぼ速度に集約されます。
-
確信できるタスクでの動的な速さ: 適応停止により、モデルが早く確信に達するタスクほど少ステップで高速。同条件の自己回帰版 Gemma 4 比で最大 約2.4倍(P1、L4/Q4 で実効 62〜154 tok/s、公称は H100/FP8 で 1100+)。難しいタスクでは拮抗。
問題点(弱み・注意)
-
量子化+llama.cpp 経路が未成熟: llama.cpp の diffusion 対応は未マージ(PR #24423)。pip wheel・Ollama になく、専用
llama-diffusion-cliの自前ビルドが必須(筆者環境のL4で約11分)。通常のllama-cli/llama-server/llama-cpp-pythonでは動かない。※ 大容量GPUがあれば vLLM や Transformers は公式に動きます(公式デベロッパーガイド)。未成熟なのは「量子化してコンシューマGPUに載せる llama.cpp 経路」の話です。 - 今回試した日本語の言葉遊び(P2)で取りこぼし: 「すもも」を拡散はほぼ無回答、自己回帰版 Gemma 4 は正しく分解。生成方式差が出た一例(ただし P2 の1タスクで、日本語全般の結論ではない)。
- 品質は本家 Gemma 4 より低い: Google 自身が「最高品質には自己回帰 Gemma 4 を推奨」と位置づけ。速度とのトレードオフ。
-
(Gemma 4 共通の癖・拡散固有ではない): 思考が英語で行われる/thinking が長く
-nを大きく取らないと最終回答に届かない、は自己回帰版でも同様。対照実験で切り分け済み。 - 最適化の余地: 計測時点の PR #24423 では Flash Attention が有効になっていなかった(自動で CPU 割当→disabled)。有効化できれば速度が伸びる可能性。
-
環境の落とし穴が多い(bleeding edge):
libcuda.so.1の参照、versioned soname(.so.0)の取りこぼし、nvidia-smi -lgcの引数仕様など、動かすまでの罠が多い。 - BF16 は 52GB 必要: フル精度は A100 80GB / H100 クラス前提。実質、量子化が前提。
まとめ
- DiffusionGemma は Colab L4 + 4bit で動く。ただし量子化+llama.cpp で動かすなら diffusion 対応が未マージで、専用
llama-diffusion-cliのソースビルド(筆者環境で約11分)+Driveキャッシュが要る(大容量GPUなら vLLM/Transformers が公式に動く)。 - 今回の計測では、速度は出力長より denoising ステップ数に強く左右され、ステップ数は entropy/confidence 条件による早期停止で大きく変わった。事実質問(P1)132 tok/s vs ひっかけ(P2)62 tok/s。
- 今回の計測で速さに最も効いたのは適応停止(Google は並列デコードやブロック拡散も要因に挙げる)。固定48ステップなら25.8 tok/s(同 Gemma 4 の自己回帰版56より遅い)。適応で最大5倍。
- 同条件の自己回帰版 Gemma 4(約56 tok/s)と直接比較すると、確信タスクで約2.4倍速・難タスクで拮抗・適応停止を切ると逆に遅い。拡散の速さは「適応停止が効く場面」限定で、万能の高速化ではない。
- 出力長(P5)に対しては512付近がピーク。長くなるほど1ステップが少し重くなるが、内容が確定的なら長文でも高速を保つ。
- 品質: 英語思考・冗長thinkingは Gemma 4 共通の癖(自己回帰版も同じ)。今回の言葉遊び(P2)では拡散側が取りこぼし(自己回帰版は正解)——ただし P2 の1例で、日本語全般の結論ではない。短答・構造化・英語なら拡散も実用十分。
計測条件: Colab Pro / NVIDIA L4(24GB, sm89) / DiffusionGemma 26B A4B-it / unsloth GGUF Q4_K_M /
llama-diffusion-cli(llama.cpp PR #24423, commitは取得時点の最新)/ プロンプトは本シリーズ共通のprompts.json(P1-P6)/ EB sampler max_steps=48・entropy_bound=0.1・confidence=0.005(C のみ confidence=0.0)/ クロック固定(sm/mem最大)/ n=3〜5 中央値。※ 再現性: セッション内 cv は 0.1〜0.3%。別ランタイム(新セッション・trials=7・SMクロック固定)で主要点を測り直しても初回と数%以内で再現。L4 の自動クロックがこの負荷で既に最大付近に張り付いているため、クロック固定の有無で結果はほぼ変わらない。
※ H100/FP8 公称の 1100 tok/s 超は L4 では再現しない(ハード差)。また計測時点の PR #24423 では Flash Attention が有効になっていなかった(自動でCPU割当→disabled)ため、有効化できれば各数値はさらに伸びる余地がある。



