How to Run Qwen-Image-2.1-Turbo Locally
The 8-step Qwen-Image-2.1 as GGUF for stable-diffusion.cpp, built from the published BF16 weights with our own importance matrix. The renders and measurements behind this card are public.
- Generate images locally in Atomic Chat. It runs stable-diffusion.cpp, the engine these files were built and checked with.
- Turbo drifts from the original picture faster than you might expect at 4 bits and below. Our
AD-Q4_Kstays 21% closer to the BF16 image than the plainQ4_K, for 150 MB more. - Turbo needs its own 8-step schedule at CFG 1. The exact settings are in Running it.
- Looking for uncensored? The open Qwen-Image pipeline has no content filter. Qwen-Image-2.1-Turbo-Uncensored-GGUF removes the refusal direction from its text encoder. On images that changed nothing we could measure, and the card shows why.
Qwen-Image-2.1-Turbo is Qwen's accelerated checkpoint of Qwen-Image-2.1: the same 7B image generator, distilled to 8 denoising steps at CFG 1, with its own fixed sampling schedule. This repo has the denoiser as GGUF for stable-diffusion.cpp. The text encoder (Qwen3-VL-8B) and the VAE are the same as in Qwen-Image-2.1, so the files you may already have for 2.1 work here.
Pick a file
Each file renders the same 48 prompts Γ 2 seeds from the same starting noise as the BF16 weights. We compare every image with the BF16 image of the same prompt and seed.
LPIPSis a perceptual distance: lower is closer to the original picture, 0 is identical.vs. new seedputs it on a scale. 100% is how far the BF16 weights move when only the seed changes, which gives an unrelated picture of the same prompt (LPIPS 0.499).text (zh)is the LPIPS on the eight prompts that put Chinese text into the image. Text breaks before photographs do.
| File | Size on disk | LPIPS [95% CI] | vs. new seed | SSIM | PSNR | text (zh) |
|---|---|---|---|---|---|---|
BF16 |
14.23 GB | 0 (identical) | 0% | 1.000 | β | 0 |
Q8_0 |
7.59 GB | 0.037 [0.030, 0.046] | 7% | 0.964 | 30.2 dB | 0.037 |
AD-Q6_K |
6.71 GB | 0.044 [0.035, 0.055] | 9% | 0.956 | 29.6 dB | 0.052 |
AD-Q5_K |
5.40 GB | 0.076 [0.064, 0.090] | 15% | 0.922 | 25.2 dB | 0.080 |
AD-Q4_K |
4.20 GB | 0.147 [0.128, 0.167] | 29% | 0.850 | 20.8 dB | 0.166 |
AD-Q3_K |
3.60 GB | 0.206 [0.182, 0.232] | 41% | 0.801 | 18.6 dB | 0.267 |
AD-Q2_K |
2.55 GB | 0.359 [0.328, 0.389] | 72% | 0.671 | 14.7 dB | 0.421 |
Q8_0is the closest to the original. Pick it if it fits.AD-Q6_Kis 0.88 GB smaller thanQ8_0and only slightly further from the original.AD-Q5_Kkeeps the composition. Details move.AD-Q4_Kis the pick at 4 bits.AD-Q3_Kdraws the same scene with visible shifts in layout, faces and lettering.AD-Q2_Kdraws a noticeably different picture from the same seed. It still follows the prompt and spells the text correctly in our spot checks. Use it only if nothing larger fits.- The BF16 weights render deterministically here: two BF16 runs give identical images, so every number above comes from quantization.
The same four prompts and seed, from left to right: BF16, Q8_0, AD-Q4_K, plain Q4_K, AD-Q2_K, plain Q2_K.
The plain files are the baseline, see below.
What AD- changes
AD- means Atomic Dynamic. The type is chosen per tensor instead of applied to every block, and the file is
quantized with an importance matrix from 32 Turbo renders that share no prompt with the evaluation set.
- The modulation shared by every block stays at Q8_0 (BF16 in
AD-Q6_K). The plain files quantize it to the base type, down to Q2_K. - The timestep embedding, the final norm and the output projection stay in BF16.
- Attention is one step above the base type: in every block for Q6, Q5 and Q3, and in the first and last four blocks for Q4 and Q2.
- In
AD-Q6_K,AD-Q5_KandAD-Q3_K, the MLP output of the first and last eight blocks is one step up as well.
How these compare with plain GGUFs
A plain GGUF is what sd-cli -M convert --type gives: every tensor at one type, no importance matrix. The first
Turbo GGUFs on the Hub, DogukanUrker's Q4_K and Q8_0, are exactly that. Their weights equal plain files we
built and measured the same way. They keep gate_layer and proj as two tensors, and those concatenate to our
gate_up exactly. Our Q8_0 is the plain one too.
We measured the plain rungs as the baseline and do not ship them here:
| Plain file | Size on disk | LPIPS [95% CI] | vs. new seed | Our file at about that size |
|---|---|---|---|---|
Q6_K |
5.88 GB | 0.072 [0.056, 0.090] | 14% | AD-Q5_K, 5.40 GB: 0.076 |
Q5_K |
4.94 GB | 0.115 [0.098, 0.133] | 23% | AD-Q5_K, 5.40 GB: 0.076 |
Q4_K |
4.05 GB | 0.187 [0.161, 0.214] | 37% | AD-Q4_K, 4.20 GB: 0.147 |
Q3_K |
3.11 GB | 0.293 [0.267, 0.321] | 59% | AD-Q3_K, 3.60 GB: 0.206 |
Q2_K |
2.39 GB | 0.475 [0.454, 0.496] | 95% | AD-Q2_K, 2.55 GB: 0.359 |
Paired over the 48 prompts, with a bootstrap interval on the difference in LPIPS:
| Comparison | Size | LPIPS difference [95% CI] | |
|---|---|---|---|
AD-Q4_K against plain Q4_K |
+150 MB | β0.039 [β0.056, β0.024] | 21% closer |
AD-Q3_K against plain Q3_K |
+490 MB | β0.087 [β0.105, β0.070] | 30% closer |
AD-Q2_K against plain Q2_K |
+160 MB | β0.117 [β0.141, β0.094] | 25% closer |
AD-Q5_K against plain Q6_K |
β480 MB | +0.005 [β0.008, +0.016] | the same within noise |
AD-Q6_K against Q8_0 |
β880 MB | +0.007 [+0.002, +0.013] | Q8_0 slightly closer |
At 4 bits we also separated the two levers at the exact size of plain Q4_K:
- The importance matrix alone makes the plain
Q4_K16% closer: β0.030 [β0.046, β0.015]. - The layout takes
AD-Q4_Kanother 6% on top.
Plain Q2_K draws a different picture from the same seed, as far from the BF16 image as a new seed is.
Running it
Turbo needs its own sampling schedule. Without --sigmas, stable-diffusion.cpp uses Qwen-Image-2.1's
default schedule, which the model was not distilled for, and the image comes out different.
sd-cli --diffusion-model Qwen-Image-2.1-Turbo-AD-Q4_K.gguf \
--vae qwen_image_2.1_vae_bf16.safetensors \
--llm Qwen3VL-8B-Instruct-Q8_0.gguf \
-p 'a neon sign that reads "OPEN LATE", rainy night' \
--steps 8 --cfg-scale 1.0 --sampling-method euler \
--sigmas 1.0,0.978453,0.95418,0.926626,0.89508,0.845148,0.704534,0.414568,0.0 \
-W 1024 -H 1024 --diffusion-fa -o out.png
The schedule is
sample_sigmasfrom the checkpoint'smodel_index.jsonplus the final0.0. The scheduler's shift is 1.0, so the values are used as they are.Through the server API, pass the same list as
sample_params.custom_sigmas.Use a stable-diffusion.cpp build from 6 October 2026 or newer (commit
c150a6bfixed custom sigma lists).The VAE is
vae/qwen_image_2.1_vae_bf16.safetensorsfrom Comfy-Org/Qwen-Image-2.1. Its tensors are identical to Turbo's own VAE. The text encoder is any GGUF of Qwen3-VL-8B-Instruct. For editing, add its mmproj as--llm_visionand the input image as-r.The encoder's quantization moves the pictures too, measured on the same 48 prompts:
- a Q8_0 encoder moves them by LPIPS 0.037 against the BF16 encoder;
- a plain Q4_K_M encoder by about 0.17, as much as our
AD-Q4_Kdenoiser does.
Use a Q8_0 encoder if it fits. Our encoder ladder has an
AD-Q4_Kat 5.29 GB that moves them by 0.087. The Q4_K_M number was measured on that (abliterated) build of the encoder.Qwen recommends about 2 megapixels (2048Γ2048 for 1:1). Our measurements are at 1024Γ1024.
How it was measured
- Engine: stable-diffusion.cpp at
36f1b1a(upstream0963357) on an NVIDIA A100 80 GB. - Settings: 1024Γ1024 with the settings in Running it,
--rng cpu, seeds 42 and 43. - Prompts: 48 evaluation prompts in six categories: photo, illustration, English text, Chinese text, several objects with attributes, and transparent RGBA.
- Held constant: the text encoder and the VAE stayed in BF16 for every render, so the denoiser file was the only thing that changed.
- Not measured: aesthetics or prompt adherence, editing with reference images, other step counts, resolutions or samplers, and runtimes other than stable-diffusion.cpp.
- In the metrics repo: every render, the prompts, the importance matrix, the per-tensor layout of every file and every log.
How these files were made
- Qwen's diffusers shards (revision
d65dbc9), checked against the Hub's sha256. - Written as one file in Comfy-Org's layout, the input stable-diffusion.cpp's rules expect. The only change is that
the MLP input is stored fused:
img_mlp.gate_up = cat(gate_layer, proj). That is a byte concatenation, so nothing is rounded.BF16is byte-identical to the published checkpoint, tensor by tensor, and renders the same image pixel for pixel. - Converted with
sd-cli -M convertfrom stable-diffusion.cpp at36f1b1a. TheAD-files add--tensor-type-rulesand--imat-in, with the exact command for each file in the metrics repo.
Changes
- 26.10.2026:
Q8_0re-uploaded.sd-cli -M converthad quantized its 64 one-dimensional QK-norm weights to Q8_0 as well, and ComfyUI-GGUF cannot load quantized norms. They are F32 now; every other tensor is byte-identical, and stable-diffusion.cpp renders the same image pixel for pixel. Thanks for the report and the fix in discussion #2.
- Downloads last month
- 240,887
2-bit
6-bit
8-bit
16-bit





