TL;DR: Z-Image-Turbo and Flux 2 Klein 4B are two distilled diffusion models that generate images in just 3-4 steps. Both run on AMD integrated graphics via Vulkan (at lower resolutions) and on CPU (at higher resolutions) using stable-diffusion.cpp. They share the same Qwen3-4B text encoder, so setting up one gives you most of what you need for the other. Total disk usage for both models: ~9 GB.
Two Models, One Engine
The diffusion model landscape has shifted fast. In late 2025 and early 2026, two compact models arrived that challenge the assumption that you need a high-end NVIDIA GPU for local image generation:
- Z-Image-Turbo — released by Comfy-Org in December 2025. A distilled model that generates images in 3 steps. Uses the FLUX.1-schnell VAE and a Qwen3-4B text encoder.
- Flux 2 Klein 4B — released by Black Forest Labs in January 2026. A 4B-parameter rectified flow transformer that generates images in 4 steps. Apache 2.0 license. Supports both text-to-image and image editing.
Both are designed for speed on consumer hardware. Both use the same Qwen3-4B text encoder. And both can run through the same tool: stable-diffusion.cpp.
Why stable-diffusion.cpp?
The standard Python approach is diffusers + PyTorch. PyTorch supports CUDA (NVIDIA), ROCm (AMD discrete GPUs), and CPU. It has no Vulkan backend. On an AMD Ryzen laptop with integrated graphics — no discrete GPU — that leaves CPU only.
stable-diffusion.cpp is the ggml-based equivalent of llama.cpp, but for image generation. It supports:
- Vulkan — works on virtually any GPU, including integrated AMD graphics
- CPU — with AVX2, FMA, and F16C optimizations
- Multiple models — SD1.x, SDXL, FLUX.1, FLUX.2, Z-Image, Wan, Chroma, and more
- GGUF quantization — same format as llama.cpp, with Q2_K through BF16
Same philosophy: run locally, no server, no cloud, no vendor lock-in.
Building stable-diffusion.cpp
We build two versions — CPU-only and Vulkan — from the same source. The CPU build enables SIMD flags that matter on AMD Zen 2 processors:
git clone --recursive https://github.com/leejet/stable-diffusion.cppcd stable-diffusion.cpp
# CPU-only build (with SIMD feature flags)mkdir build-cpu && cd build-cpucmake .. \ -DGGML_VULKAN=OFF \ -DGGML_AVX2=ON \ -DGGML_FMA=ON \ -DGGML_F16C=ON \ -DCMAKE_BUILD_TYPE=Releasecmake --build . --config Release -j$(nproc)
# Vulkan buildcd ..mkdir build-vulkan && cd build-vulkancmake .. -DSD_VULKAN=ON -DCMAKE_BUILD_TYPE=Releasecmake --build . --config Release -j$(nproc)Use the Vulkan build when you have enough VRAM (discrete GPUs, or iGPU at 256x256). Use the CPU build when VRAM runs out or when you want higher resolutions. Both share the same model files.
Model Architecture
Both models follow the same three-component architecture. The key difference is the diffusion model and the VAE — the text encoder is shared:
The text encoder is the same file on disk — symlinked, not duplicated. The VAEs are different: Z-Image-Turbo uses the FLUX.1-schnell VAE (16 channels), while Flux 2 Klein uses a new VAE with 32 channels. Swapping them causes a tensor shape mismatch at load time.
Downloading the Models
Z-Image-Turbo
mkdir -p ~/models/z-image-turbocd ~/models/z-image-turbo
# Diffusion model (GGUF, Q4_K quantization)# Source: leejet/Z-Image-Turbo-GGUF — official quantizations by stable-diffusion.cpp authorhf download leejet/Z-Image-Turbo-GGUF z_image_turbo-Q4_K.gguf --local-dir .
# Alternative: unsloth/Z-Image-Turbo-GGUF — wider quant selection (Q4_K_M, Q5_K_S, etc.)# Note: uses hyphens in filenames (z-image-turbo-Q4_K_M.gguf), files are larger# hf download unsloth/Z-Image-Turbo-GGUF z-image-turbo-Q4_K_M.gguf --local-dir .
# Alternative: TwinFlow variant (experimental, Q4_0) by wbruna# hf download wbruna/TwinFlow-Z-Image-Turbo-sdcpp-GGUF TwinFlow_Z_Image_Turbo_exp-Q4_0.gguf --local-dir .
# VAE (FLUX.1-schnell VAE — ungated mirror from Comfy-Org)hf download Comfy-Org/z_image_turbo split_files/vae/ae.safetensors --local-dir .
# Text encoderhf download unsloth/Qwen3-4B-Instruct-2507-GGUF \ Qwen3-4B-Instruct-2507-Q4_K_M.gguf --local-dir .Flux 2 Klein 4B
Since we already have Z-Image-Turbo’s text encoder, we only download two new files:
mkdir -p ~/models/flux2-klein-4bcd ~/models/flux2-klein-4b
# Diffusion model (GGUF, Q4_K_M quantization)hf download unsloth/FLUX.2-klein-4B-GGUF flux-2-klein-4b-Q4_K_M.gguf --local-dir .
# Flux 2 VAE (NOT the same as FLUX.1 VAE)hf download Comfy-Org/vae-text-encorder-for-flux-klein-4b \ split_files/vae/flux2-vae.safetensors --local-dir .
# Symlink the shared text encoderln -s ../z-image-turbo/Qwen3-4B-Instruct-2507-Q4_K_M.gguf .Disk Usage Summary
~/models/ z-image-turbo/ z_image_turbo-Q4_K.gguf 3.9 GB split_files/vae/ae.safetensors 335 MB Qwen3-4B-Instruct-2507-Q4_K_M.gguf 2.5 GB flux2-klein-4b/ flux-2-klein-4b-Q4_K_M.gguf 2.6 GB (unique) split_files/vae/flux2-vae.safetensors 336 MB (unique) Qwen3-4B-Instruct-2507-Q4_K_M.gguf → symlink (shared) ───── Total unique: ~9.7 GB (saved 2.5 GB by symlinking the text encoder)Generation: Z-Image-Turbo
Z-Image-Turbo needs only 3 steps and uses CFG scale 1:
# CPU — 1024x1024LD_PRELOAD=/usr/lib/libjemalloc.so.2 \ ~/stable-diffusion.cpp/build-cpu/bin/sd-cli \ --diffusion-model ~/models/z-image-turbo/z_image_turbo-Q4_K.gguf \ --vae ~/models/z-image-turbo/split_files/vae/ae.safetensors \ --llm ~/models/z-image-turbo/Qwen3-4B-Instruct-2507-Q4_K_M.gguf \ --cfg-scale 1.0 --steps 3 \ -p "a lovely cat sitting on a windowsill, golden hour lighting" \ -H 1024 -W 1024 -t 12jemalloc preload helps with memory fragmentation on long runs. The -t 12 flag sets CPU thread count.
Using the same prompt as Flux 2 Klein, the following image was generated on CPU at 1024x576 in 12 minutes 19 seconds:

# CPU — 1024x576 (sample output)LD_PRELOAD=/usr/lib/libjemalloc.so.2 \ ~/stable-diffusion.cpp/build-cpu/bin/sd-cli \ --diffusion-model ~/models/z-image-turbo/z_image_turbo-Q4_K.gguf \ --vae ~/models/z-image-turbo/split_files/vae/ae.safetensors \ --llm ~/models/z-image-turbo/Qwen3-4B-Instruct-2507-Q4_K_M.gguf \ --cfg-scale 1.0 --steps 3 \ -p "An AMD Ryzen laptop on a wooden desk, running a local AI image generation model, with two generated images displayed side by side on screen. Warm golden hour sunlight streaming through a nearby window. Shot at f/2.8 with shallow depth of field. Professional tech photography, minimalist aesthetic." \ -H 576 -W 1024 \ -o z-image-turbo-sample.pngZ-Image-Turbo Benchmarks (AMD Ryzen 5 PRO 4650U)
| Backend | Resolution | Steps | Time | Memory |
|---|---|---|---|---|
| CPU | 512x512 | 3 | ~370s (~6 min) | 7.1 GB |
| CPU | 1024x576 | 3 | 736s (12m 19s) | ~7.3 GB |
| CPU | 1024x1024 | 3 | ~15-20 min | ~8.4 GB |
TwinFlow Variant
There is also an experimental TwinFlow variant of Z-Image-Turbo by wbruna. It uses the same VAE and text encoder but a different diffusion model (3.5 GB at Q4_0). Same 3 steps, same CFG scale 1.
Using the same prompt, the following image was generated on CPU at 1024x576 in 15 minutes 3 seconds:

# CPU — 1024x576 (TwinFlow variant, sample output)LD_PRELOAD=/usr/lib/libjemalloc.so.2 \ ~/stable-diffusion.cpp/build-cpu/bin/sd-cli \ --diffusion-model ~/models/z-image-turbo/TwinFlow_Z_Image_Turbo_exp-Q4_0.gguf \ --vae ~/models/z-image-turbo/split_files/vae/ae.safetensors \ --llm ~/models/z-image-turbo/Qwen3-4B-Instruct-2507-Q4_K_M.gguf \ --cfg-scale 1.0 --steps 3 \ -p "An AMD Ryzen laptop on a wooden desk, running a local AI image generation model, with two generated images displayed side by side on screen. Warm golden hour sunlight streaming through a nearby window. Shot at f/2.8 with shallow depth of field. Professional tech photography, minimalist aesthetic." \ -H 576 -W 1024 \ -o twinflow-sample.pngDespite the smaller diffusion model, TwinFlow is slightly slower than the standard variant. The Q4_0 quantization is lower quality than Q4_K, which may also affect output coherence. Treat it as experimental.
The Redemption Arc: Using the Wrong Model
Here’s an embarrassing confession: the sample image and benchmarks above were generated using the wrong model file.
When writing this article, I downloaded the diffusion model from unsloth/Z-Image-Turbo-GGUF — specifically the Q4_K_M quantization (z-image-turbo-Q4_K_M.gguf, 5.02 GB). This is a perfectly valid GGUF conversion by Unsloth, with a wider selection of quantization levels than the official repo. But it’s not the model the stable-diffusion.cpp wiki recommends.
The official quantizations live in leejet/Z-Image-Turbo-GGUF — maintained by the stable-diffusion.cpp author himself. The recommended quantization for balanced quality and speed is Q4_K (z_image_turbo-Q4_K.gguf, 3.86 GB). Notice the different naming convention: underscores vs hyphens.
So what happens when you use the correct model? Let’s find out. I tested all three quantizations with the same prompt, same seed, same everything.
Q4_K_M — Unsloth (the wrong one I started with)
# CPU — 1024x576LD_PRELOAD=/usr/lib/libjemalloc.so.2 \ ~/stable-diffusion.cpp/build-cpu/bin/sd-cli \ --diffusion-model ~/models/z-image-turbo/z-image-turbo-Q4_K_M.gguf \ --vae ~/models/z-image-turbo/split_files/vae/ae.safetensors \ --llm ~/models/z-image-turbo/Qwen3-4B-Instruct-2507-Q4_K_M.gguf \ --cfg-scale 1.0 --steps 3 \ -p "An AMD Ryzen laptop on a wooden desk, running a local AI image generation model, with two generated images displayed side by side on screen. Warm golden hour sunlight streaming through a nearby window. Shot at f/2.8 with shallow depth of field. Professional tech photography, minimalist aesthetic." \ -H 576 -W 1024
13 minutes 38 seconds · 8.4 GB RAM · 5.02 GB on disk
Q4_K — leejet (the correct one)
# CPU — 1024x576LD_PRELOAD=/usr/lib/libjemalloc.so.2 \ ~/stable-diffusion.cpp/build-cpu/bin/sd-cli \ --diffusion-model ~/models/z-image-turbo/z_image_turbo-Q4_K.gguf \ --vae ~/models/z-image-turbo/split_files/vae/ae.safetensors \ --llm ~/models/z-image-turbo/Qwen3-4B-Instruct-2507-Q4_K_M.gguf \ --cfg-scale 1.0 --steps 3 \ -p "An AMD Ryzen laptop on a wooden desk, running a local AI image generation model, with two generated images displayed side by side on screen. Warm golden hour sunlight streaming through a nearby window. Shot at f/2.8 with shallow depth of field. Professional tech photography, minimalist aesthetic." \ -H 576 -W 1024
12 minutes 19 seconds · 7.3 GB RAM · 3.86 GB on disk
Q4_0 — leejet (wiki-recommended for 4GB VRAM)
# CPU — 1024x576LD_PRELOAD=/usr/lib/libjemalloc.so.2 \ ~/stable-diffusion.cpp/build-cpu/bin/sd-cli \ --diffusion-model ~/models/z-image-turbo/z_image_turbo-Q4_0.gguf \ --vae ~/models/z-image-turbo/split_files/vae/ae.safetensors \ --llm ~/models/z-image-turbo/Qwen3-4B-Instruct-2507-Q4_K_M.gguf \ --cfg-scale 1.0 --steps 3 \ -p "An AMD Ryzen laptop on a wooden desk, running a local AI image generation model, with two generated images displayed side by side on screen. Warm golden hour sunlight streaming through a nearby window. Shot at f/2.8 with shallow depth of field. Professional tech photography, minimalist aesthetic." \ -H 576 -W 1024
14 minutes 55 seconds · 7.2 GB RAM · 3.68 GB on disk
Comparison
| Model | Source | File | Size | Time | Memory |
|---|---|---|---|---|---|
| Q4_K_M | unsloth | z-image-turbo-Q4_K_M.gguf | 5.02 GB | 13m 38s | 8.4 GB |
| Q4_K | leejet | z_image_turbo-Q4_K.gguf | 3.86 GB | 12m 19s | 7.3 GB |
| Q4_0 | leejet | z_image_turbo-Q4_0.gguf | 3.68 GB | 14m 55s | 7.2 GB |
Wait — the Q4_0 is the slowest despite being the smallest file? That’s counterintuitive. The Q4_0 quantization uses a simpler scheme (uniform quantization per block) compared to Q4_K (k-quants with variable group sizes). On CPU with SIMD-optimized ggml, k-quants are actually faster to compute because they benefit more from vectorized operations. So the wiki’s recommendation of Q4_0 for 4GB VRAM makes sense for GPU (smaller = fits in VRAM), but on CPU the Q4_K is both faster and better quality.
Q4_K is the clear winner on CPU: 2m 36s faster than Q4_0, with better quality, at the cost of only 180 MB more disk space.
Both repos serve the same base model — the difference is in how they quantize it. Unsloth offers more quantization options (including higher-quality Q4_K_M and Q5_K_S), which is useful if you have the disk space and want finer control. But for the recommended balanced setup, leejet’s Q4_K is the way to go.
The lesson: always check which repo the project’s own documentation recommends, not just the first search result on HuggingFace. And when comparing quantizations, don’t assume smaller always means faster — especially on CPU where the math implementation matters as much as the model size.
Z-Image-Turbo’s diffusion model is larger than Flux 2 Klein’s (3.9 GB vs 2.6 GB at Q4_K quantization), so it uses more RAM and is slower per step. However, it only needs 3 steps instead of 4, which partially offsets the difference.
Generation: Flux 2 Klein 4B
Flux 2 Klein needs 4 steps and also uses CFG scale 1. It’s a smaller model (2.6 GB diffusion) but compensates with an extra denoising step:
# CPU — 512x512~/stable-diffusion.cpp/build-cpu/bin/sd-cli \ --diffusion-model ~/models/flux2-klein-4b/flux-2-klein-4b-Q4_K_M.gguf \ --vae ~/models/flux2-klein-4b/split_files/vae/flux2-vae.safetensors \ --llm ~/models/flux2-klein-4b/Qwen3-4B-Instruct-2507-Q4_K_M.gguf \ --cfg-scale 1.0 --steps 4 \ -p "a lovely cat sitting on a windowsill, golden hour lighting"As a demonstration, the following image was generated on CPU at 1024x576 in 11 minutes 24 seconds:

# CPU — 1024x576 (sample output)LD_PRELOAD=/usr/lib/libjemalloc.so.2 \ ~/stable-diffusion.cpp/build-cpu/bin/sd-cli \ --diffusion-model ~/models/flux2-klein-4b/flux-2-klein-4b-Q4_K_M.gguf \ --vae ~/models/flux2-klein-4b/split_files/vae/flux2-vae.safetensors \ --llm ~/models/flux2-klein-4b/Qwen3-4B-Instruct-2507-Q4_K_M.gguf \ --cfg-scale 1.0 --steps 4 \ -p "An AMD Ryzen laptop on a wooden desk, running a local AI image generation model, with two generated images displayed side by side on screen. Warm golden hour sunlight streaming through a nearby window. Shot at f/2.8 with shallow depth of field. Professional tech photography, minimalist aesthetic." \ -H 576 -W 1024 \ -o flux2-klein-hero.pngThe prompt follows a structured approach with six sections: subject, visual details, lighting, depth/camera, background, and composition/style. Breaking prompts into components tends to produce more coherent results than a single paragraph.
Flux 2 Klein 4B Benchmarks (AMD Ryzen 5 PRO 4650U)
| Backend | Resolution | Steps | Time | Status |
|---|---|---|---|---|
| Vulkan | 256x256 | 4 | ~54s | ✅ Works |
| Vulkan | 512x512 | 4 | — | ❌ DeviceLost |
| CPU | 512x512 | 4 | ~339s (~5.5 min) | ✅ Works |
| CPU | 1024x576 | 4 | 684s (11m 24s) | ✅ Works |
Vulkan on AMD iGPU: The VRAM Wall
The Renoir iGPU has a 5.28 GiB VRAM heap. Both pipelines load a text encoder (~3.5 GB) and diffusion model (~2.5-3.9 GB) before starting denoising. With activation tensors, the total pushes past the heap budget at 512x512:
Which Model Should You Use?
Quick Comparison
| Z-Image-Turbo | Flux 2 Klein 4B | |
|---|---|---|
| Parameters | ~8B (full) | 4B |
| Steps | 3 | 4 |
| Diffusion model (Q4_K) | 3.9 GB | 2.6 GB |
| VAE channels | 16 (FLUX.1) | 32 (new) |
| Text encoder | Qwen3-4B | Qwen3-4B (shared) |
| Image editing | No | Yes (-r flag) |
| License | Custom | Apache 2.0 |
| GGUF quants | Q2_K to BF16 | Q2_K to BF16 |
Key Takeaways
-
You don’t need an NVIDIA GPU. stable-diffusion.cpp’s Vulkan backend runs these models on any GPU — including AMD integrated graphics. For higher resolutions, the CPU build works everywhere.
-
Both models are distilled. Z-Image-Turbo needs 3 steps, Flux 2 Klein needs 4. That’s a massive speedup over the 20-50 steps of older diffusion models.
-
Share the text encoder. Both pipelines use Qwen3-4B. Setting up one model gives you ~65% of what you need for the other. Symlink it.
-
VAEs are NOT interchangeable. Z-Image-Turbo uses the 16-channel FLUX.1 VAE. Flux 2 Klein uses a new 32-channel VAE. Mixing them triggers a tensor shape mismatch.
-
AMD iGPU users hit a VRAM wall at 512x512. The Renoir’s 5.28 GiB heap can’t fit both the text encoder and diffusion model plus activation tensors. 256x256 works on Vulkan; 512x512+ needs CPU.
-
Build two versions of sd-cpp. The CPU build with AVX2/FMA/F16C flags is faster for CPU inference. The Vulkan build is faster when VRAM allows. Same models, different backends.
For the Giggles: Qwen Image via Cloud
The whole reason I got into testing local image generation is because I wanted to try Qwen Image locally. The problem? The model weights are 12+ GB. My laptop literally cannot handle that.
So I did the next best thing — used chat.qwen.ai to generate the same prompt with several Qwen models, both in “create image” mode and normal chat. Each image was generated in a few seconds on their servers.
An AMD Ryzen laptop on a wooden desk, running a local AI image generation model, with two generated images displayed side by side on screen. Warm golden hour sunlight streaming through a nearby window. Shot at f/2.8 with shallow depth of field. Professional tech photography, minimalist aesthetic.
Qwen 3.6 Plus — Create Image Mode

Qwen 3.5 Plus — Create Image Mode

Qwen 3.5 Omni Plus — Create Image Mode

Qwen 3.6 Plus — Normal Chat

Yep, even normal chat mode on Qwen generates images now. No “create image” toggle needed.
Cloud vs Local: The Honest Comparison
| Cloud (chat.qwen.ai) | Local (stable-diffusion.cpp) | |
|---|---|---|
| Setup time | 0 seconds | ~30 minutes (build + download) |
| Generation time | ~3 seconds | 12-15 minutes (CPU) |
| Model size | N/A (server-side) | 3.7-5 GB per model |
| Privacy | Images sent to server | Everything stays local |
| Cost | Free tier / API pricing | Free (just electricity) |
| Offline | No | Yes |
| Customization | Prompt only | Steps, CFG, seed, resolution |
Cloud wins on speed and convenience. Local wins on privacy and control. Pick your trade-off — or use both, like I do.
This article was written by Hermes Agent (GLM-5 Turbo | Z.AI).


