LTX-2.5 optimizations: add parallel VAE decoding and AITER RMSNorm - #759
Merged
avjves merged 2 commits intoAug 25, 2026
Merged
Conversation
kTorp
reviewed
Aug 25, 2026
Contributor
There was a problem hiding this comment.
nitpick but is it supposed to say "Triton" here? Other comments mentions tiled PyTorch SDPA as the fallback
Contributor
Author
There was a problem hiding this comment.
Good catch, I fixed the log message to use "tiled PyTorch SDPA".
kTorp
approved these changes
Aug 25, 2026
avjves
approved these changes
Aug 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
LTX-2.5 diffusion VAE decoder is parallelized on N-GPU runs when
--use_parallel_vaeis enabled, anddiffuser.models.normalization.RMSNormlayers are swapped to faster AITER's CK-Tilerms_normwhen available.Changes
1. Tile-parallel diffusion VAE decode (
--use_parallel_vae)New file:
xfuser/model_executor/layers/ltx2/diffusion_decoder.pyxFuserLTX2VideoDiffusionDecoderWrappersubclassesLTX2VideoDiffusionDecoderModeland overridestiled_decode. The decoder's existingtiled_decodealready decomposes the work into an independent (temporal × height × width) tile grid where each tile runsforward_stage_4+ denoise (8 neighborhood-attention blocks) with no cross-tile dependency during compute. The wrapper distributes those tiles across the SP group via round-robin ownership:forward_stages_1_to_3on the full volume (cheap; avoids communicating the intermediate feature tensor)all_reduce(SUM)of a[n_tiles, 3]shape-metadata tensor, then per-tilebroadcast(src=owner)to deliver every tile to all ranksFor the default 1024×1536×121 config this produces 12 tiles, adequate for 2/4/8 GPUs. Noise determinism: the shipping 1-step x0 path uses per-tile seeding (
base_seed XOR f(t,h,w)), which is rank-invariant without requiring non-owners to know tile shapes in advance. Multi-step paths draw a shared noise canvas identically on all ranks.Activated by
--use_parallel_vae. Automatically impliesenable_tiling()on the decoder (required fortiled_decodedispatch). Falls back to the stock single-GPUtiled_decodewhensp_world_size == 1or the tile count is less than 2.Note: PR #750's DistVAE tile-parallel mechanism does not cover LTX-2.5. The diffusion decoder uses pure
nn.Linear+ pixel-shuffle + 3D neighborhood-attention blocks, for which DistVAE has no adapter. This wrapper is the only viable multi-GPU path for this decoder.2. AITER block RMSNorm acceleration
New file:
xfuser/model_executor/layers/norms.pydiffusers.models.normalization.RMSNormis a Python implementation that up-casts to float32 before normalizing; AITER's CK-Tilerms_normkernel operates natively in bfloat16.norms.pyprovides:_aiter_rms_norm:torch.library.custom_opwrapper fixing a false mutation declaration in AITER's op schema (mutates_args=()) that would otherwise causetorch.compileto skip CUDA graph capture at every call site_AITERRMSNorm:nn.Moduledrop-in fordiffusers.models.normalization.RMSNorm; handles bothelementwise_affine=Trueand=False(ones buffer for the no-weight case)_replace_rms_norms_with_aiter(model): walks any model and replaces everydiffusers.models.normalization.RMSNorminstance with_AITERRMSNorm, leavingtorch.nn.RMSNorm(the C++ implementation, already faster than AITER) untouchedxFuserLTX2VideoTransformer3DWrapper.__init__beforemodel.to(device)so replacement buffers are placed correctly by the device move. LTX-2.5 has 384 such block norms (8 per block × 48 blocks), each an instance of the slow Python variant. (saves ~13ms/step)The utility is model-agnostic. Any future model using
diffusers.models.normalization.RMSNormfor block norms can call_replace_rms_norms_with_aiterdirectly.3. File reorganization
LTX-2.5-specific layer files moved under
xfuser/model_executor/layers/ltx2/:layers/ltx2_na3d_eager_attn.pyrenamed tolayers/ltx2/na3d_eager_attn.pylayers/ltx2/diffusion_decoder.pyTests
LTX-2.5 Output quality remains similar after parallel-vae or AITER RMSNorm.
Original 1-GPU (MI350)
ltx_2_5_distilled_video_u1r1_tc_True_1536x1024_i2v_mi350_aiter-varlen-attn.mp4
8-GPU (MI350) parallel-VAE, AITER RMS-Norm
mi350_ltx_2_5_distilled_video_u8r1_tc_True_1536x1024_i2v_aiter-RMSNorm-pvae.mp4