Conversation
Signed-off-by: Olivia Stoner <245287810+o-stoner@users.noreply.github.com>
Signed-off-by: Olivia Stoner <245287810+o-stoner@users.noreply.github.com>
…n test flakiness Signed-off-by: Olivia Stoner <245287810+o-stoner@users.noreply.github.com>
Signed-off-by: Olivia Stoner <245287810+o-stoner@users.noreply.github.com>
…lens Signed-off-by: Olivia Stoner <245287810+o-stoner@users.noreply.github.com>
…ention Signed-off-by: Olivia Stoner <245287810+o-stoner@users.noreply.github.com>
| @@ -589,6 +599,62 @@ def _reshape_gate(gate: torch.Tensor) -> torch.Tensor: | |||
| else: | |||
| return out.flatten(2) | |||
|
|
|||
| @staticmethod | |||
| def pack_ragged_kv( | |||
There was a problem hiding this comment.
For FA4, cu_seqlens_kv and max_seqlen_kv depend on the sequence lengths, so we could prepare them once per length layout and reuse them across layers/denoising steps
Could we follow the metadata preparation/cache pattern already used by the FlashInfer backend in #18174? Its batched prefill implementation uses shared attention_metadata_state to avoid rebuilding metadata and replanning on every compatible attention call. Or, with this attn_metadata refactor PR merged, it might be easier to update for FA4 backend.
There was a problem hiding this comment.
Added cu_seqlens_kv/max_seqlen_kv caching keyed on the length layout, stored in the same shared attention_metadata_state pattern as #18174 (get-or-compute-store instead of rebuilding on every call). pack_ragged_kv now takes that state as an optional param and reuses the cached tensors on a hit. Covered by TestPackRaggedKvMetadataCache and TestVarlenKvCacheSharedAcrossModel, but not yet hooked up into any model's forward pass since we don't use variable-length cross-attention by default anywhere yet
Signed-off-by: Olivia Stoner <245287810+o-stoner@users.noreply.github.com>
Signed-off-by: Olivia Stoner <245287810+o-stoner@users.noreply.github.com>
Signed-off-by: Olivia Stoner <245287810+o-stoner@users.noreply.github.com>
Signed-off-by: o-stoner <245287810+o-stoner@users.noreply.github.com>
@coderabbitai summary
Description
Adds cu_seqlens_kv based variable-length cross-attention to the FA4 VisualGen backend, so two CFG branches (conditional and unconditional) with unequal text lengths pack K/V into one flat, unpadded batch. Q stays padded (
cu_seqlens_q=None): it's always uniform-length across the CFG batch, so there's nothing to pack, and FA4 only uses its persistent-kernel scheduling whencu_seqlens_qis unset. The capability lives in the shared Attention/backend layer (tensorrt_llm/_torch/visual_gen/modules/attention.py,attention_backend/flash_attn4.py). It is not wired into Wan's model or pipeline: Wan's checkpoint was trained with unmasked padded cross-attention, so enabling packing there would silently change generation behavior. A downstream model owner can adopt this into their own model's attention calls.cu_seqlens_kv/max_seqlen_kvdepend only on the sequence-length layout (constant across every layer and denoising step of one request), so they're prepared once and cached in the sharedattention_metadata_statedict, the same pattern the TRTLLM backend already uses for its prepared-metadata cache, rather than rebuilt on every attention call.This adds support for packed K/V, but with no demonstrated speed advantage over
seqused_kfor the current padded-input workload.seqused_k(padded K/V plus internal masking) already supports padded and masked attention on the FA4 backend today: LTX2's shipped configs (examples/visual_gen/configs/ltx2-*.yaml) already run onbackend: FA4and exercise this path for audio padding. This PR adds the packed (cu_seqlens) variant as an additional option, not the only path to masking. Its value overseqused_kis narrower: K/V memory savings, sinceseqused_kstill allocates the full padded-size buffer whilecu_seqlensallocates only the packed size.Acceptance criteria
Attention.pack_ragged_kv+_attn_impl_varlen_kvAttention/WanBlockinstance, and the padded-Q/ragged-K FA4 kernel path directly (TestFA4PaddedQRaggedK)supports_varlen()per backend, raises on unsupported backendcu_seqlens_kv/max_seqlen_kvprepared once per length layout, reused across layers/denoising stepsattention_metadata_statedict (same pattern as the TRTLLM backend's prepared-metadata cache), not a process-global cacheseqused_konce metadata prep is excluded from both paths; real K/V memory savings; no measurable e2e effect. See belowMicrobenchmark, cross-attention op only
B200, bf16,
num_heads=40,head_dim=128,img_seq_len=75600(720p/81-frame),max_sequence_length=512,num_cfg_pairs=1, padded baseline also on FA4.For kernel perf, we exclude each arm's own prepare_metadata stage: not just
pack_ragged_kvforcu_seqlens, but alsoforward_with_lse's internalkey_padding_mask.sum(dim=1)toseqused_kconversion, which pays its own (smaller, but real) per-call cost. Both arms are reported two ways:_total(prep timed inside the loop, what a real caller pays today) and_kernel(prep precomputed once outside the loop, isolating the FA4 kernel call itself, the apples-to-apples comparison).Once each arm's own prepare-metadata stage is excluded,
seqused_k_kernelandcu_seqlens_kernelare statistically tied (within ~1%, run-to-run noise): the FA4 kernel itself shows no measurable advantage either way, confirming the framing above. The_totalnumbers showcu_seqlenstrailingseqused_kby a small, consistent margin, attributable topack_ragged_kv's K/V gather/cat, whichseqused_knever pays (its own prep, a mask-sum overO(B*S_kv)elements, is cheaper thanpack_ragged_kv'sO(total_kv_tokens*H*D)memcpy).K/V size (analytic, not measured, since Q dominates empirical peak memory at these shapes): padded K/V is a fixed 20.0 MB; packed K/V saves 50.7-90.0% depending on skew, though at this absolute scale (tens of MB) it's negligible next to the model's own footprint, see e2e memory below.
E2E, full 40-layer Wan2.2-14B-scale transformer forward
B200, 720p/81-frame, single-span timing around the whole forward.
Peak memory is identical across all three arms (51090.6 MB): the 14B-param model's weights and self-attention activations dominate so completely that cross-attention K/V is noise.
Bottom line: meets all acceptance criteria.
seqused_kalready handles padded and masked attention on the FA4 backend today (LTX2's shipped configs already run it); this PR addscu_seqlensas a packed alternative, not a new capability. At the kernel level,cu_seqlensshows no measurable speed advantage overseqused_konce both arms' metadata-prep stages are excluded. The only quantifiable win forcu_seqlensis K/V memory (50-90% depending on skew), real but small in absolute terms at production model scale. Neither mechanism moves e2e latency or memory, at least not for Wan: cross-attention isn't where Wan's time or memory goes at production scale.Test Coverage
tests/unittest/_torch/visual_gen/test_varlen_attention.pyTestFA4VarlenKvtests/unittest/_torch/visual_gen/test_varlen_attention.pyTestFA4PaddedQRaggedKtests/unittest/_torch/visual_gen/test_varlen_attention.pyTestAttnImplVarlenDispatch,test_backend_without_varlen_support_defaults_false,test_supports_varlen_checked_post_wraptests/unittest/_torch/visual_gen/test_varlen_attention.pyTestPackRaggedKvCachecu_seqlens_kv/max_seqlen_kvcache correctness under repeated/interleavedkv_lens, with and without a sharedmetadata_statetests/unittest/_torch/visual_gen/test_varlen_attention.pyTestVarlenKvCacheSharedAcrossModelcu_seqlens_kv/max_seqlen_kvprepared once per length layout and reused across multiple layers and denoising steps via sharedattention_metadata_state, matching howWanTransformer3DModelshares one config across all its blockstests/unittest/_torch/visual_gen/test_wan_transformer.pyTestWanBlockVarlenCrossAttn::test_varlen_matches_masked_padded_oracleAttention/WanBlockinstance, real projections and QK-normPR Checklist
Please review the following before submitting your PR:
PR description clearly explains what and why. If using CodeRabbit's summary, please make sure it makes sense.
PR Follows TRT-LLM CODING GUIDELINES to the best of your knowledge.
Test cases are provided for new code paths (see test instructions)
If PR introduces API changes, an appropriate PR label is added - either
api-compatibleorapi-breaking. Forapi-breaking, includeBREAKINGin the PR title.Any new dependencies have been scanned for license and vulnerabilities
CODEOWNERS updated if ownership changes
Documentation updated as needed
Update tava architecture diagram if there is a significant design change in PR.
The reviewers assigned automatically/manually are appropriate for the PR.
Please check this after reviewing the above items as appropriate for this PR.
GitHub Bot Help
To see a list of available CI bot commands, please comment
/bot help.