35 animated GIFs generated on a single Blackhole chip. Each cell in this grid is a Tensix compute node. The ones that glow ran the model.
The Lightning scheduler cuts denoising steps from 25 to 4–8 with no change to the model architecture. Each row below is the same prompt, same seed — original Blackhole output on the left, lightning mode on the right.
| Mode | Steps | s / frame | Total (8 frames) | vs Phase 3 |
|---|---|---|---|---|
| Phase 3 · MotionAdapter | 25 | ~101 s | ~806 s | 1× |
| Phase 2.5 cross-frame | 25 | ~12.5 s | ~100 s | 8× |
| Lightning cross-frame | 8 | ~12 s | ~96 s | ~8.4× |
Yuwei Guo, Chuanxia Zheng, Ruizhen Hu et al. The insight that motion priors can be injected into any SD UNet as a plug-and-play MotionAdapter — without retraining the base model. We just ran it faster.
arxiv 2307.04725 →
Robin Rombach, Andreas Blattmann, Dominik Lorenz, Patrick Esser, Björn Ommer (CompVis / Stability AI). The latent diffusion model that made high-quality generation accessible to everyone.
CompVis/stable-diffusion →
The Hugging Face team. The AnimateDiffPipeline and MotionAdapter abstractions gave us a verified CPU reference to build from and compare against.
huggingface/diffusers →
The Tenstorrent systems team. The SD 1.4 TTNN UNet kernel — built for Wormhole, adapted here for Blackhole — is what makes the hardware path possible. We wired the temporal loop around it.
tenstorrent/tt-metal →
We ported, adapted, debugged, and shipped — but the hard science and the hard systems work were done by these teams. This repo is gratitude in the form of running code.
Replaced the diffusers CPU UNet with the SD 1.4 TTNN UNet running natively on Blackhole silicon. ~12.5 s/frame on P300C (Phase 2.5, 25-step) vs ~2 min/frame on CPU.
Cross-frame self-attention at each PNDM step across all N frame latents simultaneously — a bridge toward full MotionAdapter integration in TTNN.
A clean, tested, documented repo anyone with Blackhole hardware can clone and run. Includes a ttsim path for development without silicon.
What runs on Blackhole silicon, what runs on CPU, and where this differs from standard AnimateDiff.
The TTNN UNet runs on Blackhole; everything else is CPU. Cross-frame attention is applied to the stacked noise predictions at each step — a Phase 2.5 approximation of the MotionAdapter's temporal transformer. Lightning mode switches to TtEulerScheduler (trailing, linear) with the same TTNN UNet — no distilled adapter loaded on Blackhole/sim; step count is still controlled by --steps. CPU Lightning loads ByteDance's distilled adapter (CFG=1.0) and requires 2/4/8 steps. --chain blends the frame-mean of the previous run's denoised latents (renormalized to unit std) into seed noise before the loop begins.
The original code applied mm_sd_v15_v2.ckpt motion weights (trained for SD 1.5 UNet, 320-dim features) to the SD 3.5 DiT (a Diffusion Transformer, 2432-dim). The shapes are incompatible — no temporal attention was actually running. The fix was switching to SD 1.4 whose UNet matches the motion weights exactly.
Two new additions since the initial release.
Lightning mode is available across all three backends, but works differently per mode. On CPU: loads ByteDance's distilled motion adapter (arXiv:2403.12706) — genuine 4-step distillation, CFG=1.0 baked in. On Blackhole/sim: switches to TtEulerScheduler (Euler, trailing, linear) with the base SD 1.4 TTNN UNet — no distilled adapter, CFG=7.5 retained, any step count. Enable with:
# Blackhole hardware — ~12 s/frame (warm, Phase 2.5) python examples/generate.py --lightning # CPU — ~20 s/frame, no hardware required python examples/generate.py --mode cpu --lightning
Full 10-prompt comparison in the gallery.
A browser-based interface for point-and-click generation — all three modes (Blackhole, ttsim, CPU) plus Lightning controls, live in the same window.
pip install -e ".[ui]" python app.py # → http://localhost:7860
Select mode → enter prompt → adjust frames/steps/seed → click Generate. Lightning checkbox is available in all modes. Output GIF displays inline.
Two independent prompts. One subject — retro 3D glasses — threaded between them by blending the first run's final denoised latents into the second run's seed noise. No explicit conditioning, no fine-tuning. Just hardware-resident state.
After each generation, --chain-save persists the final denoised latent tensors to a .pt file. The next run loads them with --chain-from and blends the normalised mean into the seed noise before denoising begins. Each step's solver then steers away from shared noise toward the new prompt — so the subject's form lingers in the structure while the context changes completely.
# Run 1 — save latents python examples/generate.py \ --prompt "retro 3D glasses, neon diner" \ --chain-save chain.pt # Run 2 — thread DNA from run 1 python examples/generate.py \ --prompt "retro 3D glasses, deep space" \ --chain-from chain.pt --chain-alpha 0.20 \ --chain-save chain.pt
Standard diffusion pipelines evict all intermediate tensors between calls. On Tenstorrent Blackhole, the denoised latent state lives in L1 between runs — the hardware makes persistent-state inference cheap. Chain threading is only practical at this cost because the latents never need to round-trip through host memory. It's a primitive that other architectures can't express efficiently without bespoke memory management. --chain-alpha (0–1) controls how strongly the previous run's identity bleeds through — lower values let the new prompt fully take over; higher values preserve more of the subject's structural fingerprint.
The Gradio UI exposes chain controls under the Chain continuity accordion — load a .pt from disk and chain runs interactively.
SD 1.4 at 512×512 with the TTNN UNet has a distinct personality. Knowing it gets you better results.
--temporal-alpha tuning0.0 | No cross-frame mixing — shared noise only |
0.2–0.3 | Subtle coherence, visible variation |
0.35 | Default — good for most subjects |
0.5–0.7 | Strong coherence, detail may flatten |
1.0 | Maximum blending, low motion |
Fast motion (fire, water): 0.2–0.35 · Slow drift (cosmos, aurora): 0.4–0.6
--stepsPNDM and Euler (Lightning): 25 is the sweet spot on silicon for both. Minimum ~4 for quick previews. With distilled weights, 4–8 steps produce comparable quality at 3–6× the speed.