Skip to content

[TRTLLM-14798][perf] Fuse Wan DupUp3D output mapping - #17003

Open
taianz-nv wants to merge 8 commits into
NVIDIA:mainfrom
taianz-nv:user/taianz/TRTLLM-13767-fused-dup-up3d
Open

[TRTLLM-14798][perf] Fuse Wan DupUp3D output mapping#17003
taianz-nv wants to merge 8 commits into
NVIDIA:mainfrom
taianz-nv:user/taianz/TRTLLM-13767-fused-dup-up3d

Conversation

@taianz-nv

@taianz-nv taianz-nv commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Dev Engineer Review

  • Implemented a Triton-fused Wan DupUp3D output mapping in tensorrt_llm/_torch/visual_gen/models/wan/dup_up3d.py that performs channel repetition + temporal/spatial pixel-shuffle and writes directly to a torch.channels_last_3d (NTHWC) output using masked tl.load/tl.store.
  • Added can_implement_dup_up3d(...) -> bool to validate the internal DupUp3D contract, compute the fused output shape (including first_chunk temporal cropping), and ensure the fused output element count fits Triton’s signed 32-bit indexing limit (_MAX_TRITON_INDEXED_ELEMENTS = 1<<31). For oversized outputs it emits a one-time warning (key="wan_dup_up3d_int32_index_fallback") and returns False.
  • Updated dup_up3d(...) to assert can_implement_dup_up3d(...) before allocating/launching, removing any oversized-output None return path (now returns torch.Tensor).
  • Updated DupUp3D.forward in tensorrt_llm/_torch/visual_gen/models/wan/wan_vae.py to only take the CUDA fused path when can_implement_dup_up3d(...) is True; otherwise it falls back to the existing eager tensor implementation.
  • Indexing/dispatch safety and correctness are handled by: (1) early dispatch rejection for non-CUDA and empty tensors (0 in x.shape), and (2) kernel-side masked offset handling (mask = offsets < output_elements).

QA Engineer Review

  • Modified tests in tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py:
    • test_fused_dup_up3d_matches_eager (expanded): parameterized across input_layout (contiguous, channels_last_3d, strided), first_chunk, and multiple (in_channels, out_channels, factor_t) configurations; asserts exact parity vs eager CPU and enforces channels_last_3d contiguity.
    • Added test_fused_dup_up3d_empty_input_uses_eager: verifies empty CUDA inputs bypass fused dup_up3d by monkeypatching the fused entrypoint to fail if launched.
    • test_fused_dup_up3d_int32_index_limit: validates _supports_triton_indexing at the (1<<31) boundary.
    • test_fused_dup_up3d_falls_back_above_index_limit: forces non-Triton dispatch by monkeypatching _MAX_TRITON_INDEXED_ELEMENTS and checks exact equality with eager CPU.
  • CI/coverage registration: updated tests/integration/test_lists/test-db/l0_b200.yml to include unittest/_torch/visual_gen/test_wan_dup_up3d.py.
  • Verdict: sufficient.

Description

Jira: TRTLLM-14798 (Task under epic TRTLLM-12775)

Wan 2.2's residual upsampling shortcut uses DupUp3D to repeat input channels,
reshape and permute them into temporal/spatial pixel-shuffle positions,
materialize the permuted tensor, and optionally crop the first temporal chunk.
The eager path writes large repeated and permuted intermediates even though the
operation only rearranges values.

This PR adds one Triton kernel that maps each element of the final
channels-last output directly to its source input index. It fuses the channel
repeat, temporal/spatial pixel shuffle, final layout, and first-chunk temporal
crop without intermediate tensors.

The implementation:

  • supports arbitrary input strides and both row-major and channels-last input;
  • preserves the original first-versus-later temporal-chunk behavior;
  • writes the final tensor directly as channels_last_3d;
  • runs automatically for eligible CUDA tensors;
  • emits a one-time warning and falls back to the eager implementation when the
    output exceeds the Triton kernel's signed 32-bit indexing range
    (2^31 elements); and
  • retains the eager CPU/non-CUDA fallback.

This is a shared VAE activation kernel, not an FP4 kernel. Native BF16 and FP4
Conv paths feed it the same BF16 activations and execute the same Triton source.

Performance

Matched four-GPU NSC A/B measurements show gains on both paths:

VAE path Eager DupUp3D Fused DupUp3D Saving Speedup
Native BF16, chunk 4 634.365 ms 598.571 ms 35.794 ms 1.060x
FP4 campaign baseline 436.712 ms 407.400 ms 29.312 ms 1.072x

A later selected-stack FP4 campaign independently measured
368.843 -> 337.792 ms, a 31.052 ms reduction.

Test Coverage

  • Added CUDA bit-exact comparison against the eager implementation for
    row-major, channels-last, and genuinely strided inputs, first/later chunks, temporal/spatial
    factors, and production repeat counts 8, 4, and 2.
  • Added exact-boundary coverage for the 2^31 signed-index limit and a forced
    CUDA dispatch test that verifies oversized outputs take the eager fallback.
  • The result is required to retain channels_last_3d.
  • Wan2.2 360p checkpoint decode parity against Diffusers passes with the fused
    path selected automatically.
  • NSC array job 1553978 task 4 passed 20 kernel matrix cases and the
    checkpoint parity case.
  • NSC job 1560274 passed all 36 focused CUDA tests, including strided
    addressing and empty N/T/H/W eager-dispatch coverage.
  • Repository pre-commit hooks and git diff --check pass.

PR Checklist

  • The kernel is independent of FP4 and shared by BF16 and FP4 paths.
  • CUDA output is bit-exact with the eager mapping.
  • Oversized outputs and CPU/non-CUDA inputs retain eager behavior.
  • No public API, dependency, CODEOWNERS, or architecture-diagram changes.

FP4 integration report

This precision-independent optimization composes with the FP4 Wan VAE integration in #17262. The consolidated performance/accuracy report and dependency map are maintained there.

@taianz-nv
taianz-nv force-pushed the user/taianz/TRTLLM-13767-fused-dup-up3d branch from 09933d5 to 9aacc3e Compare July 29, 2026 12:27
@taianz-nv
taianz-nv marked this pull request as ready for review July 30, 2026 05:41
@taianz-nv
taianz-nv requested a review from a team as a code owner July 30, 2026 05:41
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a validated Triton fused implementation for Wan’s DupUp3D, conditionally dispatches supported CUDA inputs, preserves eager fallback for unsupported or empty inputs, and expands CUDA coverage across layouts and indexing boundaries.

Changes

Wan DupUp3D acceleration

Layer / File(s) Summary
Fused kernel and launch wrapper
tensorrt_llm/_torch/visual_gen/models/wan/dup_up3d.py
Adds contract and output-shape validation, exposes can_implement_dup_up3d, maps fused output coordinates in Triton, and returns a channels-last-3d tensor.
CUDA dispatch and eager fallback
tensorrt_llm/_torch/visual_gen/models/wan/wan_vae.py
Uses the fused path only when the helper confirms CUDA, non-empty, and int32-indexable input; otherwise runs the eager duplication path.
Fused path validation and test registration
tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py, tests/integration/test_lists/test-db/l0_b200.yml
Tests contiguous, channels-last, and strided inputs, empty-input fallback, indexing boundaries, forced fallback, and B200 test registration.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested reviewers: stanleysun639, qijune

Sequence Diagram(s)

sequenceDiagram
  participant Input as CUDA input
  participant DupUp3D
  participant can_implement_dup_up3d
  participant TritonKernel
  participant EagerPath
  Input->>DupUp3D: call forward
  DupUp3D->>can_implement_dup_up3d: validate fused support
  alt supported non-empty output
    DupUp3D->>TritonKernel: launch fused mapping
    TritonKernel-->>DupUp3D: channels-last-3d output
  else unsupported or empty input
    DupUp3D->>EagerPath: run repeat and reshape fallback
    EagerPath-->>DupUp3D: eager output
  end
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the ticket, performance change, and fused Wan DupUp3D output mapping.
Description check ✅ Passed The description explains the problem, implementation, performance results, test coverage, fallback behavior, and checklist status.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py (1)

1-80: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add the new visual-gen unit test to the test-db list

  • tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py is not listed in the integration test sets; add it to tests/integration/test_lists/test-db/l0_b200.yml so CI runs it.
  • Coverage summary: test_fused_dup_up3d_matches_eager, test_fused_dup_up3d_int32_index_limit, and test_fused_dup_up3d_falls_back_above_index_limit cover eager parity, the int32 indexing boundary, and the fallback path.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py` around lines 1 - 80,
Add tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py to the appropriate
test list in l0_b200.yml so CI includes all three DupUp3D tests:
test_fused_dup_up3d_matches_eager, test_fused_dup_up3d_int32_index_limit, and
test_fused_dup_up3d_falls_back_above_index_limit.

Source: Path instructions

🧹 Nitpick comments (1)
tensorrt_llm/_torch/visual_gen/models/wan/dup_up3d.py (1)

80-96: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add Args docs to the public dup_up3d docstring.

The one-line docstring doesn't document parameters (x, output_channels, repeats, factor_t, factor_s, first_chunk) or return semantics beyond the summary. As per coding guidelines, "Prefer docstrings for external interfaces, use Google-style docstrings, document public function arguments, and include tensor dimensions and constrained dtypes where applicable."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tensorrt_llm/_torch/visual_gen/models/wan/dup_up3d.py` around lines 80 - 96,
Expand the public dup_up3d docstring with Google-style Args entries for x,
output_channels, repeats, factor_t, factor_s, and first_chunk, including tensor
dimensions and applicable dtype constraints. Retain the existing summary and
document the return behavior, including when None is returned because Triton
cannot index the output.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tensorrt_llm/_torch/visual_gen/models/wan/dup_up3d.py`:
- Around line 29-42: Remove tl.constexpr annotations from the shape, factor,
crop, and stride parameters in the kernel signature, including output_channels
through stride_xw, so they remain runtime values and do not expand
specialization. Retain tl.constexpr only for block_size.

---

Outside diff comments:
In `@tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py`:
- Around line 1-80: Add tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py to
the appropriate test list in l0_b200.yml so CI includes all three DupUp3D tests:
test_fused_dup_up3d_matches_eager, test_fused_dup_up3d_int32_index_limit, and
test_fused_dup_up3d_falls_back_above_index_limit.

---

Nitpick comments:
In `@tensorrt_llm/_torch/visual_gen/models/wan/dup_up3d.py`:
- Around line 80-96: Expand the public dup_up3d docstring with Google-style Args
entries for x, output_channels, repeats, factor_t, factor_s, and first_chunk,
including tensor dimensions and applicable dtype constraints. Retain the
existing summary and document the return behavior, including when None is
returned because Triton cannot index the output.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 892296c3-9a85-487b-8fb9-63fefea33f4c

📥 Commits

Reviewing files that changed from the base of the PR and between af64dff and df42a33.

📒 Files selected for processing (3)
  • tensorrt_llm/_torch/visual_gen/models/wan/dup_up3d.py
  • tensorrt_llm/_torch/visual_gen/models/wan/wan_vae.py
  • tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py

Comment thread tensorrt_llm/_torch/visual_gen/models/wan/dup_up3d.py
Signed-off-by: Taian Zhang <taianz@nvidia.com>
Signed-off-by: Taian Zhang <taianz@nvidia.com>
Signed-off-by: Taian Zhang <taianz@nvidia.com>
Signed-off-by: Taian Zhang <taianz@nvidia.com>
@taianz-nv
taianz-nv force-pushed the user/taianz/TRTLLM-13767-fused-dup-up3d branch from 6c3f1fe to b07d588 Compare July 30, 2026 09:33
@taianz-nv taianz-nv changed the title [TRTLLM-13767][perf] Fuse Wan DupUp3D output mapping [TRTLLM-14798][perf] Fuse Wan DupUp3D output mapping Jul 30, 2026

@zhenhuaw-me zhenhuaw-me left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not part of the PR: Considering the Wan VAE is also used by Cosmos, maybe we can move the Wan VAE code to https://github.com/NVIDIA/TensorRT-LLM/tree/main/tensorrt_llm/_torch/visual_gen/modules/vae

self.repeats = out_channels * self.factor // in_channels

def forward(self, x: torch.Tensor, first_chunk: bool = False) -> torch.Tensor:
if x.is_cuda:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why this check?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Added comments

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Sorry, I didn't get it. I'm not sure why in eager pass, the tensor will be on CPU side. I was thinking that The tensor will rarely be on CPU side in the pipeilne forward function.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Sorry, I misunderstood your question earlier. You're right that the pipeline input is expected to be on CUDA, and the CPU eager path was only retained as a test reference. Since can_implement_dup_up3d() already checks x.is_cuda, I'll remove this redundant outer check and rely on the capability check for the fallback.

Comment thread tensorrt_llm/_torch/visual_gen/models/wan/dup_up3d.py Outdated
Comment thread tensorrt_llm/_torch/visual_gen/models/wan/dup_up3d.py Outdated
Comment thread tensorrt_llm/_torch/visual_gen/models/wan/dup_up3d.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tensorrt_llm/_torch/visual_gen/models/wan/dup_up3d.py`:
- Around line 124-170: Update the output-shape and launch logic in the fused
DupUp3D path around _supports_triton_indexing and _dup_up3d_kernel so empty
inputs preserve eager behavior: avoid negative output_frames when input_frames
is zero with first_chunk enabled, and return None for any zero-sized batch or
spatial/temporal dimension before allocating or launching Triton. Keep normal
non-empty shape calculation and kernel execution unchanged.

In `@tensorrt_llm/_torch/visual_gen/models/wan/wan_vae.py`:
- Around line 266-278: The fused dup_up3d dispatch in WanVAE must be skipped
when autograd is enabled and x.requires_grad is true; update the CUDA guard
around dup_up3d to preserve the eager differentiable path, while retaining fused
execution for inference or non-gradient inputs. In
tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py lines 13-50, add a CUDA
regression test that runs module(x).sum().backward() and verifies x.grad is
populated.

In `@tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py`:
- Around line 35-50: Add a genuinely non-contiguous, non-overlapping CUDA input
view in the DupUp3D test, such as a spatially sliced tensor with non-unit
strides, while preserving the existing dtype, device, and shape. Use this
strided input for both the eager CPU reference and CUDA execution, then retain
the exact output comparison and channels-last-contiguous assertion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d4004206-7dc3-4c78-8b74-8fb70731aec4

📥 Commits

Reviewing files that changed from the base of the PR and between 6c3f1fe and b07d588.

📒 Files selected for processing (4)
  • tensorrt_llm/_torch/visual_gen/models/wan/dup_up3d.py
  • tensorrt_llm/_torch/visual_gen/models/wan/wan_vae.py
  • tests/integration/test_lists/test-db/l0_b200.yml
  • tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py

Comment thread tensorrt_llm/_torch/visual_gen/models/wan/dup_up3d.py
Comment thread tensorrt_llm/_torch/visual_gen/models/wan/wan_vae.py Outdated
Comment thread tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py
Signed-off-by: Taian Zhang <taianz@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tensorrt_llm/_torch/visual_gen/models/wan/wan_vae.py`:
- Around line 267-285: Guard the fused dispatch in the Wan VAE upsampling path
around can_implement_dup_up3d and dup_up3d so it runs only when gradients are
not required: require not (torch.is_grad_enabled() and x.requires_grad),
preserving the eager path for autograd. In
tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py lines 25-56, add a CUDA
regression that calls module(x).sum().backward() and verifies x.grad is
populated.

In `@tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py`:
- Around line 80-81: Annotate the monkeypatched fail_if_launched function with
explicit parameter and return types, while preserving its existing pytest.fail
behavior and *args/**kwargs interface.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 7c8b85e6-0c92-4bdd-882c-5e5d564b05c3

📥 Commits

Reviewing files that changed from the base of the PR and between b07d588 and 1b26bbf.

📒 Files selected for processing (3)
  • tensorrt_llm/_torch/visual_gen/models/wan/dup_up3d.py
  • tensorrt_llm/_torch/visual_gen/models/wan/wan_vae.py
  • tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py

Comment thread tensorrt_llm/_torch/visual_gen/models/wan/wan_vae.py Outdated
Comment thread tests/unittest/_torch/visual_gen/test_wan_dup_up3d.py Outdated
Signed-off-by: Taian Zhang <taianz@nvidia.com>
@taianz-nv

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #62961 [ run ] triggered by Bot. Commit: 0ed526a Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #62961 [ run ] completed with state ABORTED. Commit: 0ed526a

Link to invocation

@taianz-nv

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63620 [ run ] triggered by Bot. Commit: 0ed526a Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63620 [ run ] completed with state SUCCESS. Commit: 0ed526a
/LLM/main/L0_MergeRequest_PR pipeline #51576 completed with status: 'SUCCESS'

CI Report

Link to invocation

Signed-off-by: Taian Zhang <taianz@nvidia.com>
@taianz-nv

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64299 [ run ] triggered by Bot. Commit: e13d524 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64299 [ run ] completed with state SUCCESS. Commit: e13d524
/LLM/main/L0_MergeRequest_PR pipeline #52198 completed with status: 'SUCCESS'

CI Report

Link to invocation

@brnguyen2 brnguyen2 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.

Approving — the comments below are optional touch-ups, not blockers.

Verified the kernel's inverse mapping against the eager path (repeat_interleave decomposition, permute(0,1,5,2,6,3,7,4) inversion, first-chunk crop) — it matches, and the inclusive <= 2^31 boundary is exactly right since the max linear offset is N−1. Test coverage is thorough. Comments below are touch-ups: a logger formatting bug in the fallback warning, one gap in the int32 guard for exotic strided inputs, and a small test-matrix addition. One heads-up, not a blocker: shapes and strides are all tl.constexpr, so each unique (shape, stride) combination triggers a Triton recompile — fine for fixed-resolution chunked VAE decode, but worth remembering if input shapes ever become dynamic per request.

output_elements = math.prod(output_shape)
supported = _supports_triton_indexing(output_elements)
if not supported:
logger.warning_once(

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.

Logger.log joins *msg with spaces (" ".join(map(str, msg))) — it does not do printf-style interpolation, so this prints a literal %d with the count appended after it. Use an f-string:

logger.warning_once(
    f"Fused DupUp3D output has {output_elements} elements, exceeding the Triton "
    "signed 32-bit indexing limit; falling back to the eager implementation.",
    key="wan_dup_up3d_int32_index_fallback",
)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed in 7651709. The warning now uses a single f-string, so the element counts are rendered correctly.

first_chunk,
)
output_elements = math.prod(output_shape)
supported = _supports_triton_indexing(output_elements)

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.

This bounds only the output offsets, but the kernel also computes input_offset in 32-bit arithmetic from arbitrary strides. A strided view into a base tensor larger than 2^31 elements (e.g. big[..., ::2]) can pass this check while its max input linear offset sum((s - 1) * st for s, st in zip(x.shape, x.stride())) exceeds INT32_MAX, silently gathering from wrapped offsets. Unlikely in the VAE path (conv outputs are contiguous), but the docstring promises arbitrary strides — worth adding the input-extent bound to the same check.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agreed and fixed in 7651709. The eligibility check now bounds both the output size and the maximum relative input span, falling back before signed 32-bit indexing can overflow; a host-side regression test covers the large-stride case.

A logical NCTHW tensor stored in PyTorch ``channels_last_3d`` physical
order, which corresponds to NTHWC.
"""
assert can_implement_dup_up3d(

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.

This re-runs the full eligibility check the caller just performed (including the shape math), disappears under python -O, and hides a warning_once side effect inside an assert expression. Since forward already gates on can_implement_dup_up3d, consider dropping this to a cheap contract assert (or an explicit raise if you want direct callers protected under -O).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agreed and fixed in 7651709. The repeated full eligibility assert is replaced by the cheap internal contract validation; DupUp3D.forward remains the capability gate.

@pytest.mark.parametrize(
("in_channels", "out_channels", "factor_t"),
[
pytest.param(4, 4, 2, id="temporal-repeat-8"),

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.

All parity configs have repeats > 1, so eager's repeats == 1 branch (which skips repeat_interleave entirely, wan_vae.py:284) is never compared against the kernel's uniform // repeats path. Add one param where out_channels * factor == in_channels, e.g. pytest.param(32, 4, 2, id="repeats-1").

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Added the repeats == 1 parity configuration in 7651709.

Signed-off-by: Taian Zhang <taianz@nvidia.com>
@taianz-nv

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64493 [ run ] triggered by Bot. Commit: 7651709 Link to invocation

self.repeats = out_channels * self.factor // in_channels

def forward(self, x: torch.Tensor, first_chunk: bool = False) -> torch.Tensor:
from .dup_up3d import can_implement_dup_up3d, dup_up3d

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

maybe check if the code base has a convention about file/kernel/function naming of the triton kernels?

def forward(self, x: torch.Tensor, first_chunk: bool = False) -> torch.Tensor:
from .dup_up3d import can_implement_dup_up3d, dup_up3d

if can_implement_dup_up3d(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

maybe use_xyz()?

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #64493 [ run ] completed with state SUCCESS. Commit: 7651709
/LLM/main/L0_MergeRequest_PR pipeline #52363 completed with status: 'SUCCESS'

CI Report

Link to invocation

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