RESEARCH · #008

DFlash-2: Benchmarking Z-Lab's Successor to DFlash for Accuracy and Throughput Gains

Z-Lab's inco.ai adds a Lightweight Path Selector and a Local Convolution layer to DFlash's diffusion-based draft model. We benchmark DFlash-2 against the original on Muse Glimmer 30B to see exactly where the gains show up.

2026.10.09 14 min read

A while back, we covered DFlash, a draft-token prediction technique that uses a diffusion model. At the time, we tested it on Gemma-4-12b-it-QAT, and the native Assistant model came out ahead — DFlash wasn't able to show a clear advantage.

Recently, though, a successor called "DFlash-2" surfaced, with a number of enhancements on top of the original design.

As of August 2026, only a handful of models support it. Using the base model alone, DFlash, and DFlash-2 in turn, we looked at where each one actually pays off, and what parameter settings get the most out of it.

What Is DFlash-2?

DFlash is a technique that predicts upcoming output tokens ahead of time to speed up generation, built by Z-Lab. Several DFlash models have been released for different LLM families.

[Input Token (N)] --> [Main Model] -- h_on ----------------------------------------> [Predicted: N+1]
                                       |                                             ^
                                       v                                             |
                                  [KVCache]                                          |
                                       |                                             |
+--------------------------------------+--------------------------------+            |
| DFlash Drafter                       v (KV data injection)            |            |
|                                 [KVCache]                             |            |
|                                      |                                |            |
|                              [Diffusion Model]                        |            |
|                                      |                                |            |
|                               [Token Decoder]                         |            |
|                                      |                                |            |
|                            +---------v--------+                       |            |
|                            | Predicted N+2    |                       |            |
|                            |       +          |                       |            |
|                            | Predicted N+3    |                       |            |
|                            |       +          |                       |            |
|                            | Predicted N+4    |                       |            |
|                            +---------+--------+                       |            |
+--------------------------------------+--------------------------------+            |
                                       |                                             |
+--------------------------------------+---------------------------------------------+-------+
| Processing inside Main Model         v                                             |       |
|                             * Uses causal attention to mask;                       |       |
|                               computes probs in parallel                           |       |
|                                      +------------------------------+              |       |
|                                      v                              v              |       |
|                         (Match found)                  (No match)                  |       |
|                         Include matching portion       Nothing included in output  |       |
|                         -> Predicted: N+2                                          |       |
|                         -> Predicted: N+3                                          |       |
+------------------------------------------------------------------------------------+-------+

Figure 1. The DFlash mechanism (this structure is unchanged in DFlash-2; reused from our earlier DFlash piece).

DFlash speeds up draft generation by using a non-causal model (the diffusion model shown above), aiming for better throughput than conventional autoregressive drafting.

The tradeoff is that the diffusion model also introduces some accuracy loss — in our earlier piece, it fell behind Gemma-4's Assistant model in a head-to-head comparison.

inco.ai has been working on fixing that. Details on the company are scarce, but the maintainer of inco.ai's page on Hugging Face is Zhijian Liu, who also heads Z-Lab — so it's likely a spinoff team or startup connected to the lab.

DFlash-2 adds two things on top of the original mechanism:

To address the ordering problem, DFlash-2 adds a very lightweight internal model that checks whether a candidate token sequence is "the most natural ordering" and filters out anything that isn't. That's the Lightweight Path Selector. It sits right after the Target LM Head layer inside the drafter model.

Put together, DFlash-2 is best described as an enhancement of DFlash that specifically improves the accuracy of its draft-token ordering.

Two models are currently available:

Both are published on the Z-Lab and inco.ai repositories, with GGUF builds available for llama.cpp.

We'd originally planned to run this on Gemma-4-12b-it-qat, but since that's the only pairing currently offered, and given the lighter inference footprint, we decided to apply it to Muse Glimmer 30B, the model Meta released, and evaluate it there instead.

How Muse Glimmer 30B connects to DFlash-2

Figure 2. How Muse Glimmer 30B connects to DFlash-2 (diagram labels are in Japanese; it illustrates the Path Selector / Local Convolution placement already described above, so it isn't required reading).

The reason for picking Muse Glimmer 30B is simple: it's recently become our own day-to-day model of choice, replacing Gemma-4-12b-qat-Assistant.

Running It in llama.cpp

Where does llama.cpp stand as of August 2026?

As of August 23, 2026, DFlash-2 support hasn't landed on llama.cpp's master branch yet (it did land shortly after, on August 28, 2026 — officially supported from version 0.3.0-dev, build 10658, commit b10f9ca onward; to stay consistent with the figures measured for this piece, we've kept the write-up based on the pre-release build used at test time). That said, Z-Lab has already submitted a pull request, and building from it gets you an inference engine with DFlash-2 support.

spec: add DFlash2 support (local convolution + candidate selector) — #27342
https://github.com/ggml-org/llama.cpp/pull/27342

Building llama.cpp from this PR gives you an inference engine that supports DFlash-2:

# Build llama.cpp with PR #27342 applied
git clone https://github.com/ggml-org/llama.cpp.git
cd llama.cpp
git fetch origin pull/27342/head:pr-27342
git switch pr-27342
# Build command for NVIDIA CUDA
cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_CUDA=ON
cmake --build build -j

From there, running it as follows gets you a working inference engine:

../dflash/llama.cpp/build/bin/llama-server \
--model ./models/Muse-Glimmer-30B-UD-Q2_K_XL.gguf \
-t 12 -np 1 --prio 2 --temp 1.0 --top-p 0.95 --top-k 64 \
--port 8001 --host 0.0.0.0 --fit off --no-warmup --no-cache-prompt \
-fa on --cache-ram 0 -c 131072 --reasoning on --log-verbosity 4 \
--model-draft ./models/Muse-Glimmer-30B-DFlash2-Q4_K_M.gguf \
--spec-type draft-dflash --spec-draft-n-max 4

A quick rundown of the arguments:

ArgumentRecommended valueWhat it does
--model-draftDFlash-2 GGUF filenameSpecifies the DFlash-2 model file
-smlayerUsed when multiple GPUs are present; layer-wise distribution is generally recommended
--spec-typedraft-dflashDFlash-2 models fall under draft-dflash
--spec-draft-n-max4 or 6Caps how many tokens ahead to predict; 4 or 6 is a reasonable starting point

Verification: Using DFlash-2 on Muse Glimmer

Test Environment

We ran the following simplified verification setup.

The setup connects through an access server over an SSH tunnel to reach the target instance (for more detail on this setup, see our earlier piece, Using GPUSOROBAN). llama.cpp's service port is relayed between localhost and the remote instance through port 8001 on both ends.

 Home                                 Highreso: GPUSOROBAN
+----------------+                  +------------------+      +--------------------+
| [>_]  8001/tcp |==(SSH tunnel)==> | [>_]  8001/tcp   |---->| [llama.cpp]        |
|    Client      |                  |  Access Server   |      |  8001/tcp          |
+----------------+                  +------------------+      |  Target Instance   |
                                                                +--------------------+

Figure 3. Connection setup via GPUSOROBAN.

Instance Used

We used an NVIDIA RTX A4000 GPU for this test. Full instance specs below.

ItemSpec
Instance types16-1-a-standard-ubs24-v
GPUNVIDIA RTX A4000
GPU memoryGDDR6 16GiB
GPU memory bandwidth448.0 GB/s
FP32 compute19.17 TFLOPS
BF16 compute38.34 TFLOPS
INT8 compute153.4 TOPS
INT4 compute306.7 TOPS
vCPU11 cores
System memory50 GiB
Storage100 GiB (persistent)
CUDA version13.2
NVIDIA driver580
OSUbuntu 24.04 Server

Table 1. GPUSOROBAN instance specs.

Model Files Used

Even at 4-bit quantization, Muse Glimmer's weights alone exceed 16GiB. Accounting for KV-cache overhead, we used the 2-bit quantized build optimized with Unsloth Dynamic 2.0.

We downloaded the following files from Unsloth's Muse Glimmer repository:

FileSizeDescription
Muse-Glimmer-30B-UD-Q2_K_XL.gguf12.4 GBUD 2.0 / 2-bit quantized main model
dflash-kquant.gguf1.63 GBQuantized DFlash draft model
Muse-Glimmer-30B-DFlash2-Q4_K_M.gguf1.65 GBQuantized DFlash-2 draft model

Table 2. Files applied to llama.cpp.

Test Cases

Memory Usage Comparison

Here's how memory usage came out. (Main-model-only is excluded from this comparison.)

Memory categoryDFlash CUDADFlash CPUDFlash-2 CUDADFlash-2 CPU
Weight data (UD-Q2_K_XL)10,803.141,052.0810,803.141,052.08
KV-cache data (f16)1,664.00—1,664.00—
Sliding-window KV cache97.50—97.50—
Compute buffer273.52156.52273.52156.52
MTP model weight data (Q4_K_M)1,543.170.771,556.950.77
MTP model KV-cache size (f16)50.00—50.00—
MTP model compute buffer407.6215.51462.6715.51
Total14,838.951,224.8814,907.781,224.88

Table 3. Memory usage comparison (MiB).

Aside from a modest increase in the MTP model's weight data and compute buffer, memory usage is essentially unchanged. The added layers (the selector and the convolution layers) account for the increase, but combined they add up to under 100MiB.

Token Throughput Comparison (Main / DFlash / DFlash-2)

Single-Turn, Japanese-Heavy Results

TurnRead tps: mainRead tps: dflashRead tps: dflash-2Gen tps: mainGen tps: dflashGen tps: dflash-2
Turn 1259.37169.68159.3322.5217.820.42

Table 4. Read and generation throughput for each configuration.

Here's how generation throughput moved over the course of the response:

Generation throughput over time by configuration (single-turn, Japanese-heavy)

Figure 4. Generation throughput over time by configuration.

Throughput started out relatively fast during the initial English portion, then dropped noticeably once the Japanese section kicked in. Even so, DFlash-2 stayed ahead of DFlash throughout.

For this single-turn, Japanese-heavy case at least, neither draft model contributed much.

Multi-Turn, Code-Heavy Results

This is where things get interesting — here's the multi-turn, code-heavy comparison.

TurnRead tps: mainRead tps: dflashRead tps: dflash-2Gen tps: mainGen tps: dflashGen tps: dflash-2
Turn 1273.02167.11267.9118.9729.9632.9
Turn 2658.39545.22605.0618.7231.230.57
Turn 3636.62616.53600.8917.9734.1137.07

Table 5. Read and generation throughput for each configuration.

Both DFlash and DFlash-2 posted strong throughput here. The upward trend across turns is characteristic of MTP in general. In a coding-agent-style workload, DFlash-2 delivers a substantial throughput gain.

Generation throughput over time by configuration (multi-turn, code-heavy)

Figure 5. Generation throughput over time by configuration.

This confirms something our earlier DFlash testing didn't cover: in the "multi-turn, code-heavy" scenario, DFlash is genuinely useful for models like Muse Glimmer that, unlike Gemma-4, don't ship with a purpose-built Assistant-style MTP model of their own.

On top of that, DFlash-2's new additions push acceptance even higher, which translates directly into faster output.

"Multi-turn, code-heavy" is also a reasonably good proxy for typical coding-agent usage, suggesting this setup is especially effective in workloads that generate large volumes of tokens.

Token Acceptance Rate Comparison

Let's look at the predicted-token acceptance rate. For each case, we read Acceptance and mean length off the llama.cpp logs.

Mean length is calculated as follows:

mean length = 1 + <number of accepted tokens> ÷ <number of verification rounds>

The "1" here represents the bonus token (the one token the target model itself is guaranteed to produce). So if acceptance were 0%, mean length would still be 1, which is its floor value.

One thing worth flagging: the value you set with --spec-draft-n-max does not include the bonus token. So with --spec-draft-n-max 4, the maximum possible mean length — bonus token included — is actually 5.0.

Single-Turn, Japanese-Heavy

Acceptance is fairly low here. DFlash in particular dips under 2, which would normally be read as "not worth using."

TurnAcceptance: mainAcceptance: dflashAcceptance: dflash-2Mean len: mainMean len: dflashMean len: dflash-2
Turn 1—15.73%31.36%—1.942.25

Table 6. Acceptance and mean-length values for each configuration.

Multi-Turn, Code-Heavy

Acceptance is markedly higher here. DFlash-2 in particular reaches a mean length of 4.12 by turn 3, a notably strong result.

Update (2026-10-13): corrected the description of this result and the mean-length definition above, after a reader comment flagged an ambiguity in how mean length is calculated.
TurnAcceptance: mainAcceptance: dflashAcceptance: dflash-2Mean len: mainMean len: dflashMean len: dflash-2
Turn 1—54.49%60.97%—3.183.44
Turn 2—56.78%57.34%—3.273.3
Turn 3—68.06%78.06%—3.724.12

Table 7. Acceptance and mean-length values for each configuration.

Higher acceptance means more predicted tokens get used, which drives throughput up — the two appear to move together.

In other words: the higher the acceptance rate, the more useful the predicted tokens become, and the faster generation gets.

Getting More Out of DFlash

Finding the Right Draft Length

We reran the multi-turn, code-heavy pattern with the predicted-token length set to 6. Results below.

TurnAcceptance: mainAcceptance: 4 tokensAcceptance: 6 tokensMean len: mainMean len: 4 tokensMean len: 6 tokens
Turn 1—60.97%46.38%—3.443.78
Turn 2—57.34%47.29%—3.33.84
Turn 3—78.06%58.13%—4.124.49

Table 8. Acceptance / mean-length comparison by draft length.

Acceptance drops at 6 tokens, and mean length does increase, but only by less than one token — not much of a net gain.

Let's look at how this affects throughput over time.

Generation throughput over time by draft length

Figure 6. Generation throughput over time by draft length.

Overall, the 6-token setting came out lower in throughput. There were a few stretches in turn 2 where the existing (4-token) setting briefly fell behind, but turns 1 and 3 clearly favored the 4-token setting.

This suggests mean length roughly tracks the probability that a given draft length "lands." So rather than pushing for a longer draft length, it looks better to pick the smallest draft-n-max setting where draft-n-max − (mean length − 1) stays greater than 0 — in other words, the smallest setting that still clears the average number of accepted draft tokens.

DFlash's internal model tries to generate predicted tokens all the way out to whatever maximum length you set. If the realistic prediction horizon is around 4 tokens, anything predicted beyond that is wasted work.

That said, mean length alone isn't enough to settle on the right draft length. In practice, actual throughput should be the primary signal, with mean length used as a rough guide for where to start.

Checking the Impact of KV-Cache Quantization

Next: how much does quantizing (or not quantizing) the KV cache — a meaningful factor in the speed/memory tradeoff — affect DFlash-2's performance?

4-bit quantization usually calls for caution even in ordinary inference, while 8-bit is generally considered to have "little practical impact." That said, it's reasonable to expect some impact when precision in token prediction specifically matters.

Here's what we found, looking at acceptance and mean length:

TurnAcceptance: f16Acceptance: q8Mean len: f16Mean len: q8
Turn 160.97%55.96%3.443.24
Turn 257.34%56.16%3.33.25
Turn 378.06%74.88%4.124

Table 9. Acceptance / mean-length comparison by KV-cache precision.

The difference isn't large. Let's turn to raw output speed next.

Generation throughput over time by KV-cache precision

Figure 7. Generation throughput over time by KV-cache precision.

A slight offset in where each turn starts — especially pronounced around turn 3 — makes the data around the 5,000-token mark a bit noisy. Early on the impact looks minor, but it appears to compound somewhat as the run goes on.

To check this more carefully, let's look at each turn individually.

Throughput distribution broken down by turn (Turn 1)
Throughput distribution broken down by turn (Turn 2)
Throughput distribution broken down by turn (Turn 3)

Figure 8. Throughput distribution broken down by turn.

There's a roughly 3-4 tps gap across the board.

Acceptance and mean length were both close between the two settings, but token and character counts can't be subdivided below whole numbers, which is likely what's driving that gap.

The takeaway: when using token prediction, it's best to keep the KV cache at f16 (the default) wherever possible — though since the gap doesn't appear to widen much turn over turn, it's worth weighing against the extra cache memory it costs.

Does It Hold Up for Everyday Use?

We've made the case that DFlash-2 is genuinely useful for coding-agent workloads — but is it actually "not worth enabling" for more ordinary, Deep-Research-style everyday use? We tried it out.

Here's a sample of the questions we actually asked over the course of one day, along with the relationship between token count and throughput.

We use Muse Glimmer to speed up research when writing articles — it digs into things diligently. Some representative examples:

A sample of everyday questions asked in one day

Table 10. A sample of everyday questions asked in one day.

These are fairly ordinary day-to-day questions. Some are research for an article; others are just things that came up in day-to-day life around that time.

Here's the relationship between token count and output speed for that session:

Distribution of token count vs. output speed (everyday use)

Figure 9. Distribution of token count vs. output speed (everyday use).

Short exchanges are noticeably fast, and speed tapers off as length increases — but it never dropped below the no-MTP baseline (roughly 12 tps, the red dashed line).

Since turn count isn't factored in here, the longer exchanges are more likely to be single-turn, so it's hard to draw a firm conclusion. Still, for everyday use it's clearly a net positive, and as of August 2026 DFlash-2 has become our main day-to-day setup (we also tried Qwen3.8-27B, but it tends to spend too long thinking, which held us back from using it as much day-to-day — even though its raw reasoning quality is excellent).

Conclusion

This time we covered DFlash-2, from the little-known startup inco.ai.

Through testing, we came away with the following:

Causal models still have real advantages — the act of linking tokens sequentially reinforces the direction of generation and helps keep output coherent and high-quality — so we expect them to remain the mainstream approach for the foreseeable future.

That makes techniques like this one, which speed up output while preserving that property, worth continuing to watch.

As AI practitioners, we think the job going forward is to keep tracking techniques like this with a full picture in view, not just the surface-level claims.

References

  1. DFlash 2: Keep Drafting Parallel — inco.ai — inco.ai/blog
  2. DFlash: Block Diffusion for Flash Speculative Decoding — Jian Chen, Yesheng Liang, Zhijian Liu — arXiv
  3. Accelerating Large Language Model Decoding with Speculative Sampling — DeepMind: Charlie Chen, Sebastian Borgeaud, Geoffrey Irving, Jean-Baptiste Lespiau, Laurent Sifre and John Jumper — arXiv
  4. DeepSeek-V4: Towards Highly Efficient Million-Token Context Intelligence — DeepSeek-AI — arXiv
  5. [Speculative decoding] feat: add DFlash support — GitHub (this PR thread also documents the steps for a DFlash implementation on the Qwen3.5 series, worth a look if you're interested)
C
Compute Cluster Research
RESEARCH #008 — October 9, 2026