Repository navigation
[optimization] Added Wan 2.2 VAE encode optimizations - #8067
Conversation
Signed-off-by: Maciej Bala <mbala@nvidia.com>
…ecode bench_wan_vae_decode.py now runs under torchrun with --vae-patch-parallel-size and --vae-parallel-mode, loading DistributedAutoencoderKLWan, syncing every rank around each timed decode and reporting time, peak memory and exactness from rank 0. Tile-parallel decode already runs the fast path inside every tile, so this needs no decoder changes. Signed-off-by: Maciej Bala <mbala@nvidia.com>
Signed-off-by: Maciej Bala <mbala@nvidia.com>
Signed-off-by: MaciejBalaNV <mbala@nvidia.com>
Signed-off-by: Maciej Bala <mbala@nvidia.com>
Signed-off-by: Maciej Bala <mbala@nvidia.com>
Signed-off-by: Maciej Bala <mbala@nvidia.com>
…-omni into mbala/wan-vae-fastpath
# Conflicts: # vllm_omni/diffusion/distributed/autoencoders/autoencoder_kl_wan.py # vllm_omni/engine/async_omni_engine.py
Signed-off-by: Maciej Bala <mbala@nvidia.com>
Signed-off-by: Maciej Bala <mbala@nvidia.com>
Signed-off-by: Maciej Bala <mbala@nvidia.com>
# Conflicts: # tests/diffusion/test_diffusion_config_propagation.py # tests/entrypoints/test_serve.py
Signed-off-by: Maciej Bala <mbala@nvidia.com>
Signed-off-by: Maciej Bala <mbala@nvidia.com>
Signed-off-by: Maciej Bala <mbala@nvidia.com>
Signed-off-by: Maciej Bala <mbala@nvidia.com>
…-opt # Conflicts: # docs/user_guide/diffusion/vae_fast_path.md # tests/diffusion/distributed/test_wan_vae_fastpath_install.py # tests/diffusion/distributed/test_wan_vae_fastpath_kernels.py # tests/diffusion/test_diffusion_config_propagation.py # tests/entrypoints/test_serve.py # vllm_omni/config/omni_config.py # vllm_omni/config/stage_config.py # vllm_omni/diffusion/data.py # vllm_omni/diffusion/distributed/autoencoders/autoencoder_kl_wan.py # vllm_omni/diffusion/distributed/autoencoders/wan_vae_fastpath/__init__.py # vllm_omni/diffusion/distributed/autoencoders/wan_vae_fastpath/forwards.py # vllm_omni/diffusion/distributed/autoencoders/wan_vae_fastpath/install.py # vllm_omni/diffusion/distributed/autoencoders/wan_vae_fastpath/triton_data_movement.py # vllm_omni/diffusion/distributed/autoencoders/wan_vae_fastpath/triton_upsample.py # vllm_omni/diffusion/registry.py # vllm_omni/engine/arg_utils.py # vllm_omni/entrypoints/cli/serve.py
Signed-off-by: Maciej Bala <mbala@nvidia.com>
Signed-off-by: Maciej Bala <mbala@nvidia.com>
Signed-off-by: Maciej Bala <mbala@nvidia.com>
Signed-off-by: Maciej Bala <mbala@nvidia.com>
|
I also fixed additional edge-case where the Wan VAE encoder in channels_last mode would break the VAE decoder in lossless mode, since the latter would blindly accept the input as a non-channels last format. |
Omni ReviewBot attempt recordReview attempt ended as failed (InferMatrix Direct completion gate rejected: invalid or wrong-head finding recheck: 44bc455346f17674; missing finding recheck: 44bc455346f17674). |
vllm-omni-review-bot
left a comment
There was a problem hiding this comment.
Omni ReviewBot review
PR description
This PR adds an independent Wan 2.2 / Cosmos3 residual VAE encoder fast path beside the existing decoder path, with CLI/config --vae-encode-fast-path (off / lossless / channels_last, default lossless). On supported encoders it installs fused Triton assembly/norm/downsample forwards and an optional chunked encode_frames path; unsupported shapes or architectures keep the Diffusers reference encode. User-visible effect: faster encode by default when the residual patchified Wan encoder is present, with lossless aiming for bit-identical posteriors and channels_last trading a small numeric delta for more speed; a large encode benchmark and unit tests accompany the change.
Change flow
flowchart TD
A["[EXISTING] Cosmos3 / Wan encode callers"]:::existing --> B["[CHANGED] --vae-encode-fast-path<br/>config + CLI + registry install"]:::changed
B --> C["[NEW] Encoder fastpath kernels<br/>and encoder_forwards"]:::new
C --> D["[CHANGED] OmniAutoencoderKLWan._encode<br/>encode_frames when eligible"]:::changed
D --> E["[EXISTING] Reference encode / tiling fallback"]:::existing
B --> F["[NEW] bench_wan_vae_encode.py<br/>mode A/B + quality gates"]:::new
classDef existing fill:#e5e7eb,stroke:#6b7280,color:#111827
classDef changed fill:#fef3c7,stroke:#d97706,color:#451a03,stroke-width:2px
classDef new fill:#dcfce7,stroke:#16a34a,color:#052e16,stroke-width:2px
classDef removed fill:#fee2e2,stroke:#dc2626,color:#450a0a,stroke-width:2px
CI at
e2193b2b4cde(2026-10-01T20:02:18.876595+00:00): required check(s) blocking:buildkite/vllm-omni(missing).
Findings
- [P2] Non-test diff exceeds the 1000-line budget —
benchmarks/diffusion/bench_wan_vae_encode.py:3
Supplieddiff_sizeis 2270 non-test added lines against a 1000-line budget (19 counted files, 10 exempt). The PR body explains kernels, the independent flag, and the benchmark, but still gives no split plan or concrete exemption (vendored sync, generated code, etc.). Largest contributors:benchmarks/diffusion/bench_wan_vae_encode.py(969),wan_vae_fastpath/forwards.py(285),triton_norm_cache.py(260),triton_downsample.py(205),install.py(164). Please split the benchmark/docs follow-up from the install+kernel change, or record an explicit exemption for the largest file.
Existing thread: #8067 (comment)
🤖 This review was generated by InferMatrix Copilot, an open-source repo-maintenance agent for PR review, CI debugging and issue triage. Try it on your own repo, and ⭐ star it if it helped!
|
Reviewed head No additional high-confidence correctness findings from this static pass. I traced CLI/config propagation, independent encoder/decoder installation and rollback, temporal chunk/cache ownership, tiling/slicing fallbacks, the new kernels, and benchmark timing/quality reporting. The current head adds random-operand probes for the earlier degenerate-input/weight verdict cases, runtime checks for global and module hooks, and decoder layout regressions for channels-last encoder outputs. All 28 changed Python files pass static syntax parsing and the diff passes whitespace checks; reported CI is green. This was a static review of the fork snapshot: CPU tests, the earlier RTX 5090 reproductions, CUDA bitwise parity, distributed tiling, and GB200/H100 speedups were not rerun. The probes/regressions are present, but this review does not establish universal bitwise equivalence from a finite probe or independently verify the performance claims. |
|
Thanks @0z5a and @hsliuustc0106, can we merge this PR in this case? |
Signed-off-by: MaciejBalaNV <mbala@nvidia.com>
Omni ReviewBot attempt recordReview attempt ended as failed (InferMatrix Direct completion gate rejected: invalid or wrong-head finding recheck: 44bc455346f17674; missing finding recheck: 44bc455346f17674). |
Omni ReviewBot attempt recordReview attempt ended as failed (InferMatrix Direct completion gate rejected: invalid or wrong-head finding recheck: 44bc455346f17674; missing finding recheck: 44bc455346f17674). |
vllm-omni-review-bot
left a comment
There was a problem hiding this comment.
Omni ReviewBot review
Changes since the previous review
- 1 new inline finding(s); 0 finding(s) below.
- Still needs attention: Non-test diff exceeds the 1000-line budget —
benchmarks/diffusion/bench_wan_vae_encode.py
CI at
77f6f0266e60(2026-10-07T20:04:34.243786+00:00): required check(s) blocking:buildkite/vllm-omni(missing).
Full review analysis
PR description
This PR adds an independent Wan 2.2 / Cosmos3 residual VAE encoder fast path (off / lossless / channels_last), wired through --vae-encode-fast-path and OmniDiffusionConfig.vae_encode_fast_path (default lossless), separate from the existing decoder flag. Install-time Triton/ATen fusions cover RMSNorm epilogues, causal-conv assembly, norm-to-cache writes, residual bias folding, downsampling assembly, and chunked encode output; channels_last further converts encoder conv weights and uses tolerance-checked math. Untiled encoding can use a preallocated chunk schedule while tiling still rides the patched module forwards, with a dedicated encode benchmark and expanded unit coverage.
Change flow
flowchart TD
A["[EXISTING] serve CLI / OmniDiffusionConfig"]:::existing
B["[CHANGED] vae_encode_fast_path projection<br/>omni_config / data / registry"]:::changed
C["[NEW] install_wan_vae_encoder_fastpath<br/>+ encode_frames"]:::new
D["[CHANGED] wan_vae_fastpath forwards<br/>+ encoder Triton kernels"]:::changed
E["[CHANGED] OmniAutoencoderKLWan._encode"]:::changed
F["[NEW] bench_wan_vae_encode + encoder tests"]:::new
A --> B --> C --> D --> E
C --> F
classDef existing fill:#e5e7eb,stroke:#6b7280,color:#111827
classDef changed fill:#fef3c7,stroke:#d97706,color:#451a03,stroke-width:2px
classDef new fill:#dcfce7,stroke:#16a34a,color:#052e16,stroke-width:2px
classDef removed fill:#fee2e2,stroke:#dc2626,color:#450a0a,stroke-width:2px
See inline comments below.
🤖 This review was generated by InferMatrix Copilot, an open-source repo-maintenance agent for PR review, CI debugging and issue triage. Try it on your own repo, and ⭐ star it if it helped!
| @@ -0,0 +1,969 @@ | |||
| # SPDX-License-Identifier: Apache-2.0 | |||
| # SPDX-FileCopyrightText: Copyright contributors to the vLLM project | |||
| """Benchmark Cosmos3's Wan encoder against the reference on H100/GB200. | |||
There was a problem hiding this comment.
[P2] Non-test diff exceeds the 1000-line budget
Evidence and suggested fix
Supplied diff_size is 2270 non-test added lines against a 1000-line budget (19 counted files, 10 exempt). The PR body explains kernels, the independent flag, and the benchmark, but still gives no split plan or concrete exemption (vendored sync, generated code, etc.). Largest contributors: benchmarks/diffusion/bench_wan_vae_encode.py (969), wan_vae_fastpath/forwards.py (285), triton_norm_cache.py (260), triton_downsample.py (205), install.py (164). Please split the benchmark/docs follow-up from the install+kernel change, or record an explicit exemption for the largest file.
… memory, avoid per-resolution recompiles - Decoder channels_last RMSNorm keeps vllm-project#7056's fast math. Exact BF16 roundings are now an encoder-only switch (FastPathConfig.exact_bf16_norm, EXACT_BF16 constexpr); the fused norm-cache kernel always uses them. - Convolution verdicts are decided on seeded random operands only, before the real convolution runs once on the selected path. The probe input is regenerated per formulation and bits are compared without contiguous copies, so the first call for a new shape peaks no higher than main. - Encoder Triton kernels take spatial sizes and strides at runtime; only per-model values (channels, chunk frames, padding, factors) and layout stay constexpr. 2D/3D grids keep per-element index math to constant divisions, so throughput matches the specialized kernels. - Update encoder-norm tests to use the encoder config and the verdict tests to expect one comparison per new shape. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: princepride <wangzhipeng628@gmail.com>
… layout At the channels_last level the encoder runs channels-last and quant_conv's weights are converted, so latent_dist.parameters (and the channel slices mode() returns) carried channels-last strides on both the untiled and tiled paths. Bind quant_conv to a forward that returns a contiguous output, as the decoder's conv_out already does; already-contiguous lossless outputs are unchanged. The latent is small, so the copy is negligible. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: princepride <wangzhipeng628@gmail.com>
Omni ReviewBot: supersededThe CI failure noted on |
Signed-off-by: princepride <wangzhipeng628@gmail.com>
…tate The test's stand-in pipeline lacked ``sampling_dtype``, which ``_encode_conditioning_image_latent`` reads since vllm-project#7592, so it failed with AttributeError on every platform. Use the pipeline's class attribute. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: princepride <wangzhipeng628@gmail.com>
This PR optimizes Wan 2.2 VAE encode, mirroring #7056 which optimized decode. There are 2 new modes added:
losslessandchannels_last.losslessis bit-identical to the baseline.channels_lastcan have minimal differences.losslessachieves 1.76x speedup over the baseline whilechannels_lastis 2.39x faster than the baseline for GB200 GPU.Purpose
This PR adds VAE encoder optimizations for Cosmos3’s residual Wan2.2 architecture, building on the decoder optimizations in #7056.
The
losslessmode implements the following optimizations:The
channels_lastmode additionally converts convolution weights to channels-last memory formats to reduce runtime transposes. It uses single-pass RMSNorm+SiLU with the preceding conv1 bias folded in, and fuses AvgDown3D shortcut averaging with residual addition.These paths can change floating-point reduction order, so outputs are validated within tolerance rather than bitwise.
The encoder is configured independently from the decoder through
--vae-encode-fast-path, acceptingoff,losslessandchannels_last.losslessis the default for supported encoders. Unsupported architectures retain reference encoding.The change supports VAE tiling and tile parallelism and can coexist with spatially sharded decoding. Encoder spatial parallelism continues to use tiling.
A dedicated encoder benchmark compares all three modes, reporting startup and warmed latency, throughput, peak memory, posterior accuracy and optional reconstruction quality. It enforces bitwise equality for
losslessand numerical quality gates forchannels_last.Test Plan
Unit tests
This PR adds 55 new test functions which check for bit-identical outputs and correct shapes of the new Triton kernels.
Serving tests
We test the outputs of Cosmos3-Nano model following this notebook. All of the baseline and
losslessoutputs are bit-identical.vLLM Version:
0.30
vLLM-Omni Commit:
ToT
Test Result
Unit tests
All unit tests pass.
Serving tests
The
losslessandoffmodes are bit-identical in generated videos. Thechannels_lastexamples will be added soon.Performance tests
Gathered with this command:
python benchmarks/diffusion/bench_wan_vae_encode.py --model nvidia/Cosmos3-Nano --frames 93 --check-reconstruction --json encode-video.jsonGB200:
--vae-fast-pathoffofflosslesschannels_lastH100:
--vae-fast-pathoffofflosslesschannels_lastBEFORE SUBMITTING: read CONTRIBUTING.md and run the precheck-pr skill with the code agent for a self-check against project conventions.
(anything written below this line will be removed by GitHub Actions)