generative_continuous / 22 · SD → SDXL → SD3 lesson 22 / 23

The production lineage: SD → SDXL → SD3

Lessons 16–21 built every part separately. Here they snap together into the actual product, and we trace what each generation changed and why — plus how DALL·E took a different road to the same goal.

Stable Diffusion = five lessons assembled

There is no new idea in SD v1.5 — it is the parts you already have, bolted together. That is worth seeing explicitly, because the stock “what is SD’s core optimization / how is SD trained” questions are just “name the parts.”

ComponentWhat it isLesson
VAE (encoder + decoder)compress 512×512×3 → 64×64×4 latent; diffuse there, decode once19
UNet denoiser (ε-prediction)the score estimator, with self- and cross-attention blocks2–3, 16
CLIP text encoder (frozen)prompt → per-token embeddings, fed as cross-attention K/V20
Classifier-free guidance10% caption dropout in training; w·(cond−uncond) at sampling18
Sampler (DDIM / DPM-Solver)integrate the PF-ODE in 20–50 steps17

The training loop (“how is SD trained?”) is lesson 3’s four-liner with two wrappers: encode the image to a latent first, and pass the CLIP text embedding into the UNet:

# one SD training step
z0   = vae.encode(image).sample() * 0.18215   # to latent, rescale to ~unit var
cap  = clip_text(prompt)                       # frozen; 10% of the time → NULL
t    = randint(0, T, (B,))
eps  = randn_like(z0)
zt   = sqrt(abar[t]) * z0 + sqrt(1-abar[t]) * eps          # forward, Eq. ⋆ (lesson 2)
eps_pred = unet(zt, t, cap)                                # cross-attn on cap
loss = ((eps - eps_pred) ** 2).mean()                      # L_simple (lesson 3)
promptCLIP enc (frozen) cross-attn K/V xT ~ N(0,I) UNet denoiser× K steps (CFG) latent z₀ VAE dec

SD vs. DALL·E: two roads, same destination

A classic interview question asks for the similarities and differences between SD and DALL·E. They differ in how the prompt becomes pixels:

Stable DiffusionDALL·E 2 (unCLIP)
Text → image bridgeCLIP text embedding → cross-attention, directly conditions diffusiona prior maps CLIP-text → CLIP-image embedding, then a diffusion decoder renders it
Where generation happenslatent diffusion (VAE space)diffusion decoder in pixel/upsampled space
DALL·E 1 (for contrast)fully autoregressive: a transformer predicts dVAE image tokens one at a time

So “SD vs DALL·E” spans both axes the series has drawn: latent diffusion vs. autoregressive tokens (Part A vs. Part B) and direct conditioning vs. a CLIP-embedding prior. DALL·E 3 later moved toward SD-style diffusion with a heavily-captioned training set and an LLM prompt-rewriter (lesson 15’s hybrid).

SDXL: scale the same recipe

SDXL (Podell et al. 2023) keeps the LDM recipe and pushes on engineering. The change-list is the usual interview fodder; here is the why for each:

Intuition · linear unpacking

Claim: conditioning on size and crop lets SDXL train on junk images without inheriting their junk.

  1. The bind. Web-scale data is messy — lots of tiny upscaled thumbnails and lazily off-center crops. Throw them away and you lose most of your data; keep them and the model learns that “an image” means blurry and half-cut.
  2. The move. Don’t hide the flaw — name it. Stamp each training example with its true resolution and crop offset and feed those numbers in alongside the timestep.
  3. Why that helps. Now the model doesn’t have to guess why an image is blurry or cropped; the label already says so. It learns “blurriness lives on the size knob, off-centering lives on the crop knob” instead of baking those defects into its idea of a normal picture.
  4. The payoff. At generation time you set the knobs to the ideal — full resolution, crop (0,0) — and the model gives you sharp, centered objects, even though it never saw many such images in training.

Central point. Telling the model what’s wrong with each training image turns a defect it would otherwise absorb into a dial you can turn off at inference.

SD3: switch the engine to rectified flow

SD3 (Esser et al. 2024) is where Part A’s “DDPM = flow matching” thread (lessons 5–7) pays off in a shipped model. Three changes:

Intuition · linear unpacking

Claim: training the model to walk a straight line from noise to data is what lets SD3 sample in few steps.

  1. What changed. DDPM’s path from clean image to noise is a curved, schedule-shaped detour. Rectified flow instead picks the simplest possible path: the straight segment xt = (1−t)x₀ + t·ε that connects the data point to the noise point.
  2. Straight means constant speed. On a straight line, the direction never changes — the velocity is the same vector ε − x₀ the whole way. So the network has an easy, well-behaved thing to predict: one steady heading, not a target that swings wildly near the endpoints.
  3. Why fewer steps. Sampling means numerically following that velocity field. Following a curve accurately needs many tiny steps (a big step cuts the corner and drifts off). Following a near-straight line, you can take a few big steps and still land close — this is the lesson-6 step-count payoff.

Central point. Straightening the noise-to-data path makes the thing the model must follow nearly a ruler line, and a ruler line can be traced in a handful of strides instead of fifty.

Read the lineage as a sentence
SD assembled latent diffusion + CLIP + CFG + UNet. SDXL scaled it and patched data-curation leaks with conditioning tricks. SD3 swapped the engine to rectified flow on an MM-DiT and added a real language model (T5) to the text stack. Every change traces to a limitation an earlier lesson named: step count (→ flow matching, lesson 6), UNet vs. transformer (→ DiT, lesson 8), CLIP’s syntax weakness (→ T5, lesson 20), brightness leak (→ schedule/offset, lesson 18).

Interactive · the SD inference pipeline, timed

Walk a prompt through the pipeline and watch where the wall-clock goes. Toggle latent vs. pixel diffusion (the lesson-19 speedup), change step count (lesson 17), and toggle CFG (which doubles UNet calls, lesson 18). The bar shows the dominant cost — and why “diffuse in latent space, distill the sampler” is the whole production-latency story.

Where the milliseconds go
Each stage is a rough relative cost. Latent diffusion shrinks the UNet stage ~48×; CFG doubles UNet calls; fewer steps scales it linearly. The numbers are illustrative ratios, not benchmarks.
UNet net calls
relative total cost
Punchline
Stable Diffusion is lessons 16–21 wired together: diffuse a VAE latent, condition with CLIP via cross-attention, steer with CFG, integrate with DDIM/DPM-Solver. SDXL scaled it and fixed data leaks with size/crop conditioning + a refiner; SD3 swapped in rectified flow on an MM-DiT with a T5 in the text stack. DALL·E reaches the same goal via a CLIP-embedding prior (v2) or pure autoregression (v1) — the two axes this whole series mapped.