Skip to content

Cut WAN family time-to-ready 220-304s -> 33-51s: AOT executable cache, zero-exec warmup, converted-weights cache#443

Merged
copybara-service[bot] merged 1 commit into
AI-Hypercomputer:mainfrom
syhuang22:vace-load-compile
Jul 14, 2026
Merged

Cut WAN family time-to-ready 220-304s -> 33-51s: AOT executable cache, zero-exec warmup, converted-weights cache#443
copybara-service[bot] merged 1 commit into
AI-Hypercomputer:mainfrom
syhuang22:vace-load-compile

Conversation

@syhuang22

@syhuang22 syhuang22 commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Cut WAN family time-to-ready: AOT executable cache, zero-exec warmup, converted-weights cache

Serving-oriented startup optimizations for the whole WAN family (2.1 / 2.2 T2V, 2.2 I2V, VACE). A process restart previously re-paid tracing, XLA compilation (or persistent-cache lookup), a full torch->flax weight conversion, and two real denoise steps of warmup. All four are either memoized on disk or eliminated.

Mechanisms

  1. Per-shape AOT executable cache (aot_cache.py): cached_jit replaces jax.jit at definition sites (identical behavior until install()). After warmup the compiled executables are serialized (jax.experimental.serialize_executable); later processes deserialize on background threads — no trace, no lowering, no cache lookup. One file per input signature, so resolutions never collide. Wired into the transformer forward passes (base, CFG, cfg-cache, VACE) and VAE encode/decode.
  2. Zero-exec warmup (aot_cache.warmup_mode()): compilation only needs avals. During warmup, wrapped calls lower+compile (or reuse the deserialized executable) and return sharded zeros, so downstream executables (scheduler, VAE) still warm faithfully — without paying real 14B denoise steps.
  3. Converted-weights cache (wan_utils.py, converted_weights_dir): the torch->flax conversion (per-tensor transpose + scan-stack + dtype cast) is a pure function of the checkpoint; it is now saved once as per-tensor .npy + manifest and re-loaded with parallel reads. Self-validating against eval shapes and the cast policy (mismatch = silent reconvert).

Both caches are off by default (aot_cache_dir: '', converted_weights_dir: '').

Results (v7x-8, 720p/81f, 2D-ring recipe, same warm JAX persistent cache on both sides; only the two cache knobs differ)

Pipeline Load (off -> hit) Compile window (off -> hit) Time-to-ready (off -> hit)
WAN 2.1 T2V 14B 24.2s -> 25.0s 195.5s -> 8.3s (23.5x) 219.7s -> 33.3s
WAN 2.2 T2V A14B 29.6s -> 28.1s 55.9s -> 8.7s (6.4x) 85.5s -> 36.8s
WAN 2.2 I2V A14B 29.2s -> 27.9s 151.7s -> 16.3s (9.3x) 180.9s -> 44.2s
WAN 2.1 VACE 14B 29.7s -> 29.6s 274.6s -> 21.5s (12.8x) 304.3s -> 51.1s

First run per (model, shape) builds the caches and lands in between (compile 11-33s).

Highlights: VAE decode cold compile 144.9s -> 0.2s (2.1), I2V image VAE encode 89.5s -> 1.0s, VACE (unscanned, so all 40 blocks were traced every process) 274.6s -> 21.5s.

Load is flat in this A/B because both sides already include this PR's loader changes (fused cast, chunked staged put, threaded 2.1 component load) and the remaining critical path is the CPU text-encoder load; measured against the previous loader the transformer host path alone is 26.2s -> 8.5s, verified bitwise-equal on all 1095 params.

Correctness

  • Denoise step time identical across all variants (5.9s +-0.4 run noise); videos generated with all mechanisms on validated frame-exact (h264, 1280x720, 81 frames, zero decode errors on full decode) for all four pipelines.
  • Loader-path equivalence verified bitwise (1095/1095 params) between the fused-cast path and the historical two-pass path.
  • The AOT cache is keyed by a config fingerprint (model, attention, flash block sizes, mesh, dtypes, scan, jax version) plus a per-call input signature; unknown signatures fall back to plain jit and are serialized after the next warmup. Executables deserialize with mesh-ordered execution_devices.
  • Unit tests: aot_cache_test.py (9, incl. cross-process signature determinism and in-trace inlining) and converted_weights_cache_test.py (5, incl. bf16 bit-view round-trip and cache invalidation).

Example

end_to_end/tpu/run_wan_fast_inference.sh — end-to-end serving example (tuned v7 flag set + both caches): ./run_wan_fast_inference.sh 22 40 "a cat surfing".

@syhuang22 syhuang22 requested a review from entrpn as a code owner July 10, 2026 22:09
@syhuang22 syhuang22 requested review from eltsai and ninatu July 10, 2026 22:16
Comment thread end_to_end/tpu/run_wan_fast_inference.sh
@syhuang22 syhuang22 force-pushed the vace-load-compile branch from 5e2f716 to a843f4e Compare July 13, 2026 16:49
entrpn
entrpn previously approved these changes Jul 13, 2026
eltsai
eltsai previously approved these changes Jul 13, 2026

@eltsai eltsai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! I was able to reproduce the stats on v7x

Comment thread src/maxdiffusion/aot_cache.py
ninatu
ninatu previously approved these changes Jul 14, 2026
@syhuang22 syhuang22 dismissed stale reviews from ninatu, eltsai, and entrpn via 15a10be July 14, 2026 17:13
@syhuang22 syhuang22 force-pushed the vace-load-compile branch from a843f4e to 15a10be Compare July 14, 2026 17:13
…ecutable cache, zero-exec warmup, VACE/animate cast+staged-put reuse, VAE decode AOT, prompt embeds cache, threaded 2.1 TE warm
@syhuang22 syhuang22 force-pushed the vace-load-compile branch from 15a10be to 5a0b7c8 Compare July 14, 2026 17:23
@copybara-service copybara-service Bot merged commit d8ead5a into AI-Hypercomputer:main Jul 14, 2026
27 of 28 checks passed
@eltsai eltsai mentioned this pull request Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants