Add diffusion-gemma block-diffusion support - #24427
Conversation
|
Tried the latest i'm on Model from Unsloth loading fails with GGUF, inspection shows : but not: The runtime appears to expect: { LLM_TENSOR_SELF_COND_NORM, "self_cond_norm" }from I also checked the current branch and couldn't find any references to self_cond_pre_norm in the runtime: grep -R "self_cond_pre_norm" src/ -n returns nothing. Is this a naming mismatch? |
|
Nice, been waiting for this. For anyone building from this PR — heads up that Apple Silicon won't see the speedup. It's a compute-bound model, needs a high-CUDA-core GPU. Detailed GPU requirements here: https://diffrun.dev |
|
@Ajay9o9 Now this PR works for unsloth model. |
|
llama-diffusion-gemma-server don't appear in builds |
|
@mohamed-em2m they are building in my local and I also can see it in the CI logs. Are there any errors while building? |
|
Awesome job! I will have a look later at the code. Proposal: make the code modular with a clear fetcher, and builder(s). For the fetcher do something like this: git clone --depth 1 https://github.com/ggml-org/llama.cpp
cd llama.cpp
git fetch --depth 1 origin pull/24427/head:pr24427
git checkout pr24427While for the rest, something similar to how I did it here: EDIT: C:\Users\Admin\source>talk_to_gemma.cmd
warning: no usable GPU found, --gpu-layers option will be ignored
warning: one possible reason is that llama.cpp was compiled without GPU support
warning: consult docs/build.md for compilation instructions
0.00.000.889 I diffusion-gemma: GGML_CUDA_MMQ_MAX_X=64
0.01.195.906 W load: control-looking token: 50 '<|tool_response>' was not control-type; this is probably a bug in the model. its type will be overridden
0.01.196.466 W load: control-looking token: 212 '</s>' was not control-type; this is probably a bug in the model. its type will be overridden
0.01.252.519 W load: special_eog_ids contains '<|tool_response>', removing '</s>' token from EOG list
[SUCCESS] Done@echo off
setlocal
set "EXE=C:\Users\Admin\source\llama.cpp\build_cpu\bin\llama-diffusion-gemma-cli.exe"
set "MODEL=C:\Users\Admin\Documents\LLM Models\unsloth\diffusiongemma-26B-A4B-it-GGUF\diffusiongemma-26B-A4B-it-Q4_K_M.gguf"
if not exist "%EXE%" (
echo [ERROR] CLI not found: "%EXE%"
exit /b 1
)
if not exist "%MODEL%" (
echo [ERROR] Model not found: "%MODEL%"
exit /b 1
)
"%EXE%" ^
-m "%MODEL%" ^
-p "Answer in about 1000 words: explain block diffusion generation and CUDA sampling optimizations." ^
-n 1024 ^
-c 8096 ^
-ngl 999 ^
--diffusion-steps 48 ^
--diffusion-cuda-mmq-max-x 64
if errorlevel 1 (
echo [ERROR] Command failed
exit /b 1
)
echo [SUCCESS] Done
exit /b 0EDIT 2: trying on gpu with my builder and this directory: set "EXE=C:\Users\Admin\source\llama.cpp\build_gpu_cuda\bin\llama-diffusion-gemma-cli.exe"It did something: PS C:\Users\Admin\source> ./talk_to_gemma.cmd
ggml_cuda_init: found 1 CUDA devices (Total VRAM: 8191 MiB):
Device 0: NVIDIA GeForce GTX 1070 Ti, compute capability 6.1, VMM: yes, VRAM: 8191 MiB
0.00.000.655 I diffusion-gemma: GGML_CUDA_MMQ_MAX_X=64
0.01.348.419 W load: control-looking token: 50 '<|tool_response>' was not control-type; this is probably a bug in the model. its type will be overridden
0.01.349.167 W load: control-looking token: 212 '</s>' was not control-type; this is probably a bug in the model. its type will be overridden
0.01.434.171 W load: special_eog_ids contains '<|tool_response>', removing '</s>' token from EOG list
0.17.762.433 I formatted prompt: <|turn>system
<|think|>
<turn|>
<|turn>user
Answer in about 1000 words: explain block diffusion generation and CUDA sampling optimizations.<turn|>
<|turn>model
0.17.762.850 W llama_context: n_ctx_seq (8192) < n_ctx_train (262144) -- the full capacity of the model will not be utilized
0.17.763.676 W llama_kv_cache_iswa: using full-size SWA cache (ref: https://github.com/ggml-org/llama.cpp/pull/13194#issuecomment-2868343055)
0.18.941.717 I diffusion-gemma: prefix=34 canvas=256 max_canvases=4 steps=48 entropy_bound=0.100 temp=[0.40,0.80] n_ctx=8096 mm=0
0.18.941.728 I diffusion-gemma: gpu sampling: on | device self-cond: on | device loop: on
0.18.941.728 I diffusion-gemma: device early-stop interval=1
0.23.787.601 I prefill (encoder, no self-cond): 34 tokens in 4.846 s (7.0 tok/s) |
|
Latest benchmark numbers on RTX 5090 using my benchmark Server diffusion benchmarkready ms: 9080.63 Using aiperf (speedbench)
|
|
Google reported 700 tokens per second on RTX 5090, so I guess there is a lot of room for optimization here |
|
@theIvanR Can you try the CPU only build with -DGGML_CPU_REPACK=OFF %EXE% ^ |
|
@coder543 It depends mostly on the number of denoising steps needed for the canvas to converge. For coding prompts, model converges generally in around 20 steps while the above benchmark took on an average 34 steps to converge. |
it's appear now |
|
@lnigam Thanks for getting back, I will try it later when I get some time. In the mean time I would also suggest adding a verbose mode and or a debug one to filter out exactly these issues when launching, say with sensible fallbacks and try catch type blocks. |
|
How fast can it run if partial-offload? e.g. on 12gvram like 4070 |
I don't have a proper answer but probably really slow : This is a diffusion model, to be efficient the prompt/output tokens needs to go throught the different layers several times (I don't know how many for a proper answer, but it's ~20 according to gemini). So basically the tokens are going into all of the layers at the same time, the ones going in your gpu will be quick but the other one will goes throught your ram Which would slow down by a lot the answers. I'm not sure that even with a very good gpu doing some offloading on diffusion llm would be efficient. (On a 4070 I'ld recommend you to use qwen3.6 a3b in q4. I have a similar setup and it's what I use to code with Cline.) TLDR : I don't know how fast it would run but probably slow because the entire model needs to be loaded simultaneously. |
…g#24427) Port the mainline DRAFT DiffusionGemma arch (ggml-org#24427, lnigam/nvidia-diffusion-gemma, baseline head 201052a) onto the fork's gemma4 + diffusion scaffolding. A gemma4 MoE checkpoint run as a bidirectional block-diffusion denoiser. The transformer body is reused verbatim from gemma4 (dense shared MLP + routed MoE, dual head dims, iSWA, qk-norm, scale-less v-norm, final-logit softcap, per-layer layer_scalar). The only architectural addition is a self-conditioning gated MLP applied to the input embedding in the decoder (denoise) phase: soft = (probs @ token_embd^T) * sqrt(n_embd) (probs = prev step softmax, 0 on step 1) inpL = rms_norm(scaled_embed + sc_mlp(rms_norm(soft))) Phase is derived at graph-build time from cparams.causal_attn (the runner toggles it: encoder = causal prefill / canvas commit; decoder = bidirectional self-conditioned denoise). The unified iSWA KV cache holds the prompt / committed-canvas prefix; the in-flight canvas K/V is rolled back each step. This is the minimal generic (backend-agnostic) port: DENSE self-conditioning (full-vocab probs, embedding transposed in-graph). The CUDA fast-sampling kernels, sparse top-k gather, fused self-cond embedding, device denoise loop, separate encoder/decoder graphs and multimodal prefill from the PR are omitted (not needed for coherent ROCm/Vulkan/CPU generation). Components: - LLM_ARCH_DIFFUSION_GEMMA wired through llm_arch_is_diffusion(); self_cond + enc_layer_output_scale tensor names/infos (src/llama-arch.{h,cpp}). - llama_model_diffusion_gemma (subclass of gemma4) + self-conditioned graph (src/models/diffusion-gemma.cpp, src/models/models.h). - llama_diffusion_cond state + llama_set_diffusion_self_cond() C API threaded through llm_graph_params (src/llama-{graph,context}.{h,cpp}, include/llama.h). - llama-diffusion-gemma-cli: reference block-diffusion runner (entropy-bound sampler + stable/confident stopping + linear temp schedule, host full-softmax sampling, dense self-cond feedback) (examples/diffusion-gemma/). - gguf-py: MODEL_ARCH.DIFFUSION_GEMMA + self_cond / enc scale tensors + tensor_mapping + diffusion.canvas_length writer. Smoke (unsloth/diffusiongemma-26B-A4B-it Q4_K_M, gfx1150 ROCm, ngl 99): coherent block-diffusion generation, correct answer ("The capital of France is Paris.") with a coherent thought-channel block; converged in 29 denoising steps. Gap: convert_hf_to_gguf.py DiffusionGemmaModel class not added (the fork lacks the Gemma4Model HF-converter base it must subclass); gguf-py metadata is in place. Smoke uses unsloth's prebuilt GGUF. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Keep diffusion decoder input handling limited to Diffusion Gemma so other architectures use standard graph inputs. Assisted-by: Codex
…o be way higher compared to pytorch
77a9fb6 to
dd0cf04
Compare
Gaps found and fixed: - ADD DiffusionGemma row (Model architectures): lnigam/nvidia-diffusion-gemma PR ggml-org#24427 port — was entirely missing from the provenance map. - ADD IQ2_KS (slot 145) + IQ5_KS (slot 152) to IK KS row-meta: ported via 2fa2967 from ik_llama commits 67817fb / 90e53a0, were undocumented. - UPDATE TurboKV prefill row: D=128→D=128+256 — the D=256 extension (35c0611) landed on main, making the §-FLAG-DIM-256 "inert" note stale. - UPDATE InnerQ KV row: mark RETIRED (purged 7082ea4, slots 68-69 returned to reserve) — was still listed as VERIFIED despite subsystem removal. - UPDATE turboq5/turboq6 drift-watch entry: mark IN-TREE (merged from branch, FA matrix wired 393307e) — was incorrectly listed as branch-only. - ADD lnigam remote to remotes table. - Bump Last full re-verification date to 2026-06-28. Co-Authored-By: Claude <noreply@anthropic.com>
|
Thanks for all the development on this pull request, I compiled this branch on my hardware
These were my results on running a few tests while also testing out the server on Zed locally for refactoring some code with diffusiongemma-26B-A4B IQ4_XS quant llama-diffusion-gemma-cli -m model.gguf \
-n 512 \
--diffusion-steps 64 \
--temp 0.7 \
-p "Write a Python function to merge two sorted lists, include type hints, docstring, and a small test block."
What would be nicer would be to have the model integrated into the llama-server with similar api schema! |
…f04 (#279) Independent Opus design-gate (fourth 2026-08-06 run, ledger #225) resolves the line-120 acceptance gate: - (A) RESOLVED — pin = ggml-org/llama.cpp#24427 @ dd0cf04. Criterion 1 (frame-contract reachability, decisive) REACHED on #24427 (#277 Tier-0 frame stream, example-layer, ~0.11% tax, no kernel reach) vs #24423 argmax-only. Criterion 3's counterweight toward #24423 falsified as a disqualifier by the device-path mechanism probe (comment 5212022958: TOGGLEABLE, 16/16 gpuOFF early-stop vs 6/6 gpuON ceiling, zero crossover). - (B) CONFIRMED — Tier-0 DiffusionFrame emission in the example layer without kernel work (#277, ~0.11% tax). - (C) CONFIRMED — usable envelope, Q4_K_M/sm_75 fast path 30.4 tok/s. - (D) resolved as input to (A) (#278 disconfirmed self-cond width). Records the resolved OQs as decisions (Open Questions, Decision 2), adds the GPU-sampling coupling as a named non-disqualifying implementation-note (INV-5-consistent), and updates ARCHITECTURE.md's out-of-scope row to accepted. Operator-vetoable per the standing #131 gate. Adjudication: #131 (comment)
|
In the CLI that matters most at small inputs.add_generation_prompt = true;
+ inputs.enable_thinking = false;
return common_chat_templates_apply(tmpls.get(), inputs).prompt;With that, Happy to send this as a PR against your branch if that's easier. |




Overview
This PR adds initial diffusion-gemma support for Gemma 4 based block-diffusion checkpoints. This is just a draft PR to get feedback on multiple design aspects of diffusion model like block diffusion, approximation of soft embeddings, separate vs single encoder-decoder, prefix KV-cache reuse, diffusion server utility etc.
git clone https://github.com/ggml-org/llama.cpp cd llama.cpp gh pr checkout 24427 cmake -B build -DGGML_CUDA=ON cmake --build build -j --config Releasethen use a GGUF (any can work but for eg)
Diffusion Gemma benchmark commands
Benchmark scripts:
The optimized CUDA path uses the current binary defaults for fused full-softmax,
fused top-k sampling, fused self-conditioning embedding, final softcap fusion,
direct self-conditioning, and final token copy on stop.
The only extra tuning flag passed explicitly is:
--run-max-denoising-stepis not enabled. Top-k is not passed, so the defaultfull-softmax path is used (
top_k=0).CLI
Server
Example request:
Benchmark scripts
CLI benchmark:
Server benchmark:
The benchmark scripts default to:
--ctx-size 8096--diffusion-steps 48--diffusion-cuda-mmq-max-x 64top_k=0--ignore-eos, so EOS is respected by defaultAdditional information
Requirements