You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 87c36b2
Browse filesBrowse the repository at this point in the historyBrowse files
feat(wan): fast inference optimizations (fused cross-attention, token patch embed, shard-major A2A, lane padding)
All four switches default off ("xla" / "conv" / "flat" / "off") in the Wan
YAMLs and in wan_runtime_options. They are plain config keys, plumbed to
FlaxWanAttention / WanModel through `attention_config_entries(config)` (the
#488 mechanism) and resolved once at module build; nothing is read from the
environment at trace time. The unconditional pyconfig default for
`wan_cross_attn_cpu_interpret` was removed (it is an attention_config entry,
default False, used only by CPU tests).
- Short-KV text cross-attention Pallas kernel (wan_cross_attn_kernel="pallas"):
kernels/cross_attention_pallas.py keeps a head block's whole 512-token text
KV resident in VMEM and computes an exact single-pass softmax per query tile
(full-row max, exp2, one numerator/denominator, normalised after PV; no
running max / online rescaling). It replaces only what would otherwise be
the unmasked XLA dot-product fallback. FlaxWanAttention falls back to XLA
(logging the reason once) when the inputs or sharding don't fit, and now also
when the VMEM budget is not validated or too small: 64 MiB is requested only
when every mesh TPU is v6e or tpu7x (otherwise Mosaic's default), and
`estimate_vmem_bytes` (Q/out/K/V double buffers + one head's FP32 scores) is
checked against it (~42 MiB at the Wan shard shape; MAX_KV_LEN KV does not
fit and falls back rather than failing to compile). The estimate has only
been checked against real compiles at Wan's KV length (512). The kernel
itself raises a ValueError for an over-budget working set only when a budget
resolves (an explicit vmem_limit_bytes, or the v6e/tpu7x default); under
Mosaic's default it does no check of its own, and callers that can fall back
use `vmem_unusable_reason`. The two fallback reasons (unusable inputs, VMEM)
log under separate warn-once keys.
- Token-sharded patch embedding (wan_patch_embed_mode="tokens"): the Conv3d
patch embedding becomes a patchify + matmul on the token-sharded layout,
avoiding the activation all-gather.
- Shard-major Ulysses A2A (wan_ulysses_out_a2a="chunked" / "shard_major"): a
single layout-preserving all_to_all over a reshaped (num_shards, chunk)
leading axis (not chunked compute/comm overlap), so XLA no longer inserts
relayout copies around the collective. With the custom splash kernel (and
S_local % block_q == 0, D == 128, heads_per_tile == 1) the forward Q
exchange also stays shard-major (4-D q) and the kernel writes the
shard-major output directly (out_num_shards), on both the 1D Ulysses path
(v6e) and the 2D Ulysses+Ring path (tpu7x).
- Lane sequence padding (wan_seq_pad="lane"): pads video tokens at the tail to
a per-shard multiple of 128 (75,600 -> 75,776 at 720p/CP=4) so Ulysses
reshapes are copy-free; TokenPadding masks the pad keys in the custom
ulysses / ulysses_ring_custom kernels, and fixed-m metadata now also
excludes pad query rows from the Q-norm bound. Every configuration that
disables it logs why, once per cause. Behaviour change: if padding is
active, the paths that cannot mask it (flash and non-custom ulysses via
_tpu_flash_attention, ulysses_ring, dot_product, cudnn_flash_te,
head_local_svg) raise NotImplementedError via
`_reject_active_token_padding` instead of silently attending to pads.
- run_wan_fast_inference.sh: the v6e and v7 profiles set
WAN_CROSS_ATTN_KERNEL=pallas, WAN_PATCH_EMBED_MODE=tokens,
WAN_ULYSSES_OUT_A2A=chunked, WAN_SEQ_PAD=lane (all overridable); the
generic profile sets tokens only. The fused RMSNorm+RoPE kernel from #488
stays on in the v6e and v7 profiles and off in the generic one.
LIBTPU: v6e now disables
--xla_tpu_enable_ici_ag_pipelining / --xla_tpu_enable_ag_backward_pipelining,
v7 enables them and adds --xla_tpu_enable_offloading_copy_to_sparsecore=false
and BQ=4736. These two flags moved out of COMMON_LIBTPU, so the generic
(non-v6e/v7) profile no longer sets them at all.
Performance, measured at the stack tip (Wan 2.2 T2V-A14B, 720p/81f/40 steps,
warm AOT, DVFS unpinned unless noted; CP=4, DP=2, launcher defaults including
the fused RoPE kernel):
v6e-8: denoise 125.9s, generate 128.05s
tpu7x-8: denoise 105.1s, generate 107.6s
tpu7x-8, DVFS pinned (PIN_DVFS_P_STATE=true), fused RoPE kernel off:
denoise 93.6s, generate 96.1s (pinned with it on was not measured)
Per-feature deltas were not measured separately and are omitted. In
isolation the cross-attention kernel is 0.51 ms vs 3.94 ms (v6e) and
0.49 ms vs 1.81 ms (tpu7x) per call for the XLA path inside the model.
The launcher's reference-benchmark comment now carries these numbers.
Tests:
- cross_attention_pallas_test.py: golden parity (row/tile max, mxu/vpu sum,
ragged tiles, k_prescaled, batch), guards, VMEM budget resolution /
working-set estimate / fallback reasons, and FlaxWanAttention dispatch
(CPU interpret integration, fallbacks, I2V text-vs-image split). The three
tests that expect the kernel to be used skip on TPUs outside the validated
kinds (there FlaxWanAttention falls back by design); that fallback is
covered by test_falls_back_to_xla_on_unvalidated_tpu_kind.
- wan_seq_pad_test.py: padding plan and per-cause disable logging, pad-key
masking for ulysses custom (unaligned and aligned real_len, flat and
shard-major out A2A, every fixed-m mode) and ulysses_ring_custom (k-centring
on/off; and the tpu7x production path scaled down: U=2 x R=2, aligned
real_len, chunked out A2A, asserting the shard-major layout was taken;
needs >= 4 devices), fixed-m metadata ignoring pad query rows, and the
NotImplementedError guards.
- wan_patch_embed_test.py, ulysses_out_a2a_test.py: tokens vs conv parity and
config-driven mode; flat vs chunked vs shard_major parity.
- wan_runtime_options_test.py: the new switches' YAML defaults and enums.
- CI: 29 tests skip in GitHub Actions: kernel parity and the Pallas-active
dispatch / unaligned-KV fallback tests in cross_attention_pallas_test
(19 of 39), the three kernel bit-exact tests in ulysses_out_a2a_test, the
two WanModel patch-embed parity tests and the five masking / end-to-end
tests in wan_seq_pad_test. Guards, VMEM budget logic, the remaining XLA
fallback dispatch tests (including the unvalidated-TPU fallback),
padding-plan logic and runtime options run in CI.
- end_to_end/tpu/run_wan_stack_tests.sh: adds this PR's four test files.
Verified (final tree):
- TPU v6e-8 (jax 0.11.2, end_to_end/tpu/run_wan_stack_tests.sh): 350 passed, 1 skipped (off-TPU fallback only), 259 subtests passed.
- TPU v6e-8 with GITHUB_ACTIONS=true (all 17 stack test files): 231 passed, 120 skipped, 202 subtests passed.
- Emulated unvalidated TPU (device_kind="TPU v4", rope_accum_is_measured=False): 0 failures across all 17 stack test files.
0 commit comments