How Meta Animates AI-Generated Images at Scale

How Meta combined guidance distillation, step distillation, and regional traffic routing to cut a video diffusion model from 96 U-Net passes to 8 — then fixed the latency that model optimization alone couldn't.

How Meta Animates AI-Generated Images at Scale

Optimizing a diffusion model is the obvious problem. Meta’s animate feature solved that well — then discovered that perfectly tuned inference still delivered bad end-to-end latency, because the network cost of routing requests across continents had never been modeled.

Source

How Meta animates AI-generated images at scale

By: Gaurav Sharma (Meta)
Published: August 14, 2024
Type: Engineering article

Saved because it documents both the model optimization and the deployment failure that followed — two nearly separate problems that the same team had to solve in sequence, and the second one only became visible once the first was solved.

From 96 U-Net passes to 8, then the routing surprise

The animate feature needed to generate a short animation from an AI image in a few seconds, for billions of potential users across Meta’s family of apps. The team started with the model, where the math is most tractable.

A video diffusion model generates motion by running a denoising process across a sequence of frames. Each denoising step is a forward pass through a U-Net, and the standard technique for high-quality results — classifier-free guidance (CFG) — requires multiple passes per step. The original model used three: an unconditional pass, an image-conditional pass, and a full text-plus-image-conditional pass. At 32 denoising steps, that was 96 U-Net calls per animation. The optimization work was largely a campaign to compress that number.

The first move was precision reduction: converting the model from float32 to bfloat16. bfloat16 preserves float32’s exponent range — which matters for numerical stability — while halving the mantissa to 7 bits. The result is a model that fits in half the memory and executes faster per operation. This change compounds everything that follows, since every subsequent forward pass is cheaper.

The second move addressed temporal-attention expansion. Video models attend across the time axis, which requires replicating context tensors to match the number of frames. Previously that replication happened before the cross-attention linear projection, meaning the expensive matrix multiplication operated on already-expanded tensors. Moving the replication to after the projection keeps tensors compact through the costly operation and expands them only once the per-frame cost is already sunk. The principle is identical to predicate pushdown in a query planner: apply expensive transformations to the smallest possible input.

The third move introduced DPM-Solver with a linear-in-log SNR time schedule. DPM-Solver treats the denoising process as a differential equation and takes numerically larger steps by exploiting the equation’s structure, rather than accumulating the error that simpler solvers would accumulate. The log SNR schedule spaces steps evenly in information content rather than wall time, which keeps those larger steps stable. This reduced required sampling steps to 15.

The fourth move is where the real compression happened: training guidance distillation and step distillation simultaneously. Guidance distillation trains a student to replicate CFG’s result in one forward pass — eliminating the unconditional and conditional branch runs entirely. Step distillation trains a student to replicate multiple consecutive teacher steps in a single step. Training both objectives together produces a student that simultaneously eliminates the multi-branch guidance overhead and collapses the step sequence. The final model: 8 student steps, one U-Net pass each. That’s 8 total U-Net calls, down from 96 — a 12x reduction. The model runs fewer steps than even a naive 8-step diffusion model because there is no CFG overhead left.

After TorchScript graph optimizations and a later migration to torch.compile for component-level granularity, the model was fast. Load testing began, and end-to-end latency came back worse than expected — not slightly, but by seconds.

The inference time hadn’t changed. The problem was routing: traffic was being dispatched across regions, and cross-continental network overhead was larger than the latency budget the model work had recovered. A request originating in Europe might hit a GPU in the US, and the round-trip cost swallowed every optimization made on the compute side.

The fix was a traffic management system that computes routing tables from live load metrics. The primary objective is regional locality — serve requests from GPUs in the same region as the requester. Load thresholds determine when a region is running hot enough to spill traffic to neighbors, and tiered routing rings define which neighbors become eligible at which load levels. Light load: stay local. Approaching capacity: nearest region. Near ceiling: farther regions unlock. The result was that most requests stayed in-region and latency dropped to what the model benchmarks predicted.

With locality enforced, a cascade failure emerged in the retry layer. Each GPU handles exactly one request at a time — the animation fully saturates it, so queuing adds only wait, not throughput. When capacity is full, the server rejects new requests. Without backoff, those rejections trigger immediate retries, and a brief saturation spike becomes a self-sustaining cascade. The fix was exponential backoff combined with scheduling jitter: a fraction of jobs receive a small execution delay at scheduling time, breaking the synchrony that makes bursts amplify rather than absorb.

My take

The distillation combination is worth holding precisely. Guidance distillation and step distillation solve different inefficiencies — redundant branches and redundant time steps — but they’re compatible training objectives because both ask the student to approximate a more expensive teacher trajectory. Training jointly produces a trajectory that is simultaneously guidance-free and temporally compressed. That’s why the result is 8 passes rather than two separate improvements each dividing by a smaller factor.

The routing surprise is the more broadly applicable lesson. Inference benchmarks measure model execution within a data center. End-to-end user latency includes serialization, network transit, queue wait, and response delivery. At global scale, the network term can dominate — and it almost always gets modeled as near-zero in benchmark environments because benchmarks run inside a single facility. The symptom here (load tests revealing latency “higher than expected”) is a signal that the benchmark environment was missing a major cost term.

The cascade retry failure is a standard distributed systems bug that stays invisible until the system operates near capacity. Below saturation, retries complete quickly and the missing backoff is never noticed. At saturation, missing backoff turns isolated failures into correlated failures across the fleet. Systems that are never stress-tested near their capacity ceiling almost always carry this dormant.

Where this is useful

  • Deploying multi-step generative models where you need to account for the total U-Net call budget and understand which distillation techniques can stack.
  • Capacity planning for GPU inference serving global traffic — regional routing belongs in the latency model from the start, not discovered in load testing.
  • Retry design for any service with hard per-host concurrency limits; exponential backoff with jitter is the correct default when synchronized request bursts are possible.
  • Less applicable if requests don’t fully saturate the serving unit — the cascade problem is specific to the no-queue, single-request-per-GPU model Meta was running.

Apply this: Before shipping an inference optimization, write down every network hop a real user request makes and estimate the latency at each hop. If the inference improvement is smaller than the variance in network transit, fix the routing layer first — the model work won’t be visible to users otherwise.

What I want to remember

Remember: Guidance distillation and step distillation stack multiplicatively when trained jointly — 96 U-Net passes to 8 — and the limiting factor after that is usually not the model.