Skip to content

[https://nvbugs/6572800][fix] Added _use_fused_ln(fp4_scale) and gated each of the three norm sites on its… - #17509

Closed
trtllm-agent wants to merge 1 commit into
NVIDIA:mainfrom
tensorrt-cicd:repair-bot-bug6572800
Closed

[https://nvbugs/6572800][fix] Added _use_fused_ln(fp4_scale) and gated each of the three norm sites on its…#17509
trtllm-agent wants to merge 1 commit into
NVIDIA:mainfrom
tensorrt-cicd:repair-bot-bug6572800

Conversation

@trtllm-agent

@trtllm-agent trtllm-agent commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Root cause: The Wan LN+shiftscale+quant fusion gated only on hidden_size == 5120, so Wan2.2 took the fused op with no NVFP4 quantize to fold in and fell through to a dense path whose in-kernel LayerNorm statistics are not bit-exact with F.layer_norm, which the pre-fusion goldens encode.
  • Fix: Added _use_fused_ln(fp4_scale) and gated each of the three norm sites on its own fp4 scale, mirroring the sibling gates in flux/attention.py; eager where there is nothing to fuse, fused where there is.
  • Original test: pytest tests/integration/defs/examples/visual_gen/test_visual_gen_wan.py::test_wan_feature_accuracy_against_golden -v
  • Automated fix generated by repair-bot

Test plan

  • Verify fix on the same GPU type as the original failure
  • Check for regressions in related tests

Links

Dev Engineer Review

  • Added _use_fused_ln(fp4_scale) to require a supported hidden size and an available FP4 input scale.
  • Updated all three Wan LayerNorm fusion sites to use this predicate.
  • Preserved eager F.layer_norm behavior for unquantized layers and layers without FP4 scales.
  • Removed four obsolete Wan test waivers.
  • No public API changes were introduced.
  • No configuration or test-list format issues were identified.

QA Engineer Review

  • Added test_fused_layernorm_requires_its_quantize.
  • Updated _make_model_config to support skip_create_weights.
  • The test verifies that unquantized norms do not use fusion and that supported hidden sizes use fusion only when an FP4 scale exists.
  • The test is covered by the Wan integration test-list changes through removal of obsolete waivers.
  • Verdict: sufficient.

@coderabbitai

coderabbitai Bot commented Aug 11, 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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 6f3e4b35-94c1-42c2-a687-18e6f732d0ff

📥 Commits

Reviewing files that changed from the base of the PR and between 8a6b8be and 8d34156.

📒 Files selected for processing (1)
  • tests/integration/test_lists/waives.txt
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/integration/test_lists/waives.txt

Walkthrough

Wan fused LayerNorm selection now requires supported hidden dimensions and downstream FP4 scales. Norm paths preserve standard LayerNorm when fusion does not apply. Unit tests cover the new conditions, and obsolete Wan accuracy waivers are removed.

Changes

Wan fused LayerNorm gating

Layer / File(s) Summary
Gate fused LayerNorm execution
tensorrt_llm/_torch/visual_gen/models/wan/transformer_wan.py
WanBlock uses _use_fused_ln() to require shape support and an applicable FP4 scale for Norm1, Norm2, and Norm3.
Validate fused LayerNorm selection
tests/unittest/_torch/visual_gen/test_wan_transformer.py, tests/integration/test_lists/waives.txt
Tests cover supported and unsupported hidden sizes with and without FP4 scales. Four obsolete Wan accuracy waivers are removed.

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

Mergeability Score: ⚪ Minimal · up to 8d341

This is a localized Wan normalization-path fix intended to restore the correct eager or fused behavior per quantization scale; no actionable merge-blocking risk remains beyond normal checks and review.

Suggested reviewers: zhenhuaw-me, bowenfu, zhanruisunch

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the bug fix and the main change to gate Wan LayerNorm fusion on FP4 scale availability.
Description check ✅ Passed The description explains the root cause, fix, affected tests, validation plan, and bug reference, although it uses headings different from the template.
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.
✨ 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.

🧹 Nitpick comments (1)
tests/unittest/_torch/visual_gen/test_wan_transformer.py (1)

349-374: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Cover the fused LayerNorm branches.

The new test covers only _use_fused_ln(). Existing tests cover WanBlock.forward() and post_load_weights(), but no test supplies NVFP4 scales to exercise fused Norm1, Norm2, or Norm3.

Add focused tests or mocks for the fused and eager paths. The test is already listed in tests/integration/test_lists/test-db/l0_b200.yml. Run pytest tests/unittest/.

Coverage verdict: insufficient.

🤖 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_transformer.py` around lines 349 -
374, Add focused tests in the WanBlock test suite that provide NVFP4 scales and
exercise fused and eager LayerNorm execution for Norm1, Norm2, and Norm3 through
WanBlock.forward(), including the no-scale eager path. Reuse existing
block/config fixtures and mocks, and assert each norm path is selected or
invoked as expected while preserving existing post_load_weights coverage.

Source: Path instructions

🤖 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.

Nitpick comments:
In `@tests/unittest/_torch/visual_gen/test_wan_transformer.py`:
- Around line 349-374: Add focused tests in the WanBlock test suite that provide
NVFP4 scales and exercise fused and eager LayerNorm execution for Norm1, Norm2,
and Norm3 through WanBlock.forward(), including the no-scale eager path. Reuse
existing block/config fixtures and mocks, and assert each norm path is selected
or invoked as expected while preserving existing post_load_weights coverage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c16ad821-56d4-4eb3-9a28-638ea7fb48f2

📥 Commits

Reviewing files that changed from the base of the PR and between fea23ff and c9b961d.

📒 Files selected for processing (3)
  • tensorrt_llm/_torch/visual_gen/models/wan/transformer_wan.py
  • tests/integration/test_lists/waives.txt
  • tests/unittest/_torch/visual_gen/test_wan_transformer.py
💤 Files with no reviewable changes (1)
  • tests/integration/test_lists/waives.txt

@trtllm-agent
trtllm-agent force-pushed the repair-bot-bug6572800 branch from c9b961d to 2136687 Compare August 11, 2026 20:06

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

The gate itself looks right, and matching get_nvfp4_input_scale's own conditions (dynamic quant / AWQ pre-quant-scale / group size) with the fusion gate is the correct fix for the wan22 profiles.

Two things before merge:

  1. wan21-nvfp4 waiver removal is not explained by this change. wan21 is Wan2.1-T2V-1.3B-Diffusers — hidden size 12×128 = 1536, so _fused_ln_shape_supported was already False and all three norm sites already ran eager. This patch changes nothing for that case, so either its golden failure has a separate root cause (and the waiver should stay), or the failure was environmental. Please post the passing run for wan_feature_accuracy_against_golden[wan21-nvfp4] on the same GPU type, or restore that line.

  2. Nothing now asserts the fused path is still taken anywhere. After this change it requires hidden 5120 and a statically calibrated NVFP4 checkpoint; every profile in test_wan_feature_accuracy_against_golden quantizes at runtime, so all of them take the eager branch. A future change that makes get_nvfp4_input_scale return None unconditionally would silently disable the kernel with green CI. Consider a positive assertion on a static-NVFP4-checkpoint config (e.g. the A14B NVFP4 path).

Note the bug also covers qwen_image, cosmos3, flux2 and fastwan goldens, whose waivers stay — worth saying in the description that this fixes only the wan slice.

@@ -139,10 +139,6 @@ examples/visual_gen/test_visual_gen_qwen_image.py::test_qwenimage_feature_accura
examples/visual_gen/test_visual_gen_qwen_image.py::test_qwenimage_feature_accuracy_against_golden[nvfp4] SKIP (https://nvbugs/6572800)
examples/visual_gen/test_visual_gen_wan.py::test_fastwan_lpips_against_golden SKIP (https://nvbugs/6572800)
examples/visual_gen/test_visual_gen_wan.py::test_wan22_t2v_lpips_against_golden SKIP (https://nvbugs/6535765)

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.

The [wan21-nvfp4] waiver was removed here, but wan21 maps to Wan2.1-T2V-1.3B-Diffusers (12 heads x 128 = hidden 1536). That never satisfied the old hidden_size == 5120 gate, so it already ran the eager F.layer_norm path and this patch does not change its numerics at all. Either its golden failure has a different cause and the waiver should stay, or please attach the passing run that justifies removing it.

we would pay that difference for nothing -- on Wan 2.2 T2V it alone
moved LPIPS from 0.040 to 0.225 (nvbugs/6535765).
"""
return self._fused_ln_shape_supported and fp4_scale is not None

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.

With this gate, the fused kernel is reached only when hidden==5120 and the checkpoint carries a static NVFP4 input_scale (get_nvfp4_input_scale returns None for dynamic quant, AWQ pre-quant-scale, and group size != 16). None of the test_wan_feature_accuracy_against_golden profiles meet that — they all quantize at runtime — so the fused path is now unexercised by the tests this PR un-waives, and a future regression that turns the gate permanently off would not be caught. Worth adding a positive check on a statically-quantized NVFP4 Wan2.2 checkpoint that the fused path is actually taken.


torch.testing.assert_close(trt_out, hf_out, atol=0.4, rtol=0.4)

@pytest.mark.parametrize("num_heads,shape_supported", [(40, True), (12, False)])

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 test only exercises the predicate, not forward, yet it sits in TestWanUnit, which is marked @pytest.mark.integration/wan_t2v and builds a full WanBlock. It would give more value (and run in plain unit CI) as a check that a block with _norm2_fp4_scale = None produces output equal to F.layer_norm-based eager math — that is the property the goldens actually encode.

@trtllm-agent
trtllm-agent force-pushed the repair-bot-bug6572800 branch 11 times, most recently from 8d6bffe to 4826e78 Compare August 15, 2026 02:02
@trtllm-agent
trtllm-agent force-pushed the repair-bot-bug6572800 branch 5 times, most recently from 0c0c347 to cbd07e0 Compare August 17, 2026 02:43
@trtllm-agent
trtllm-agent force-pushed the repair-bot-bug6572800 branch 8 times, most recently from ae44b63 to 1911042 Compare August 19, 2026 08:02
The Wan 2.2 LayerNorm+shiftscale+quant fusion (NVIDIA#15762) gates itself on
``_fused_ln_supported = hidden_size == 5120`` -- a pure shape predicate that
never consults the fp4 input scales, despite the adjacent comment stating
"fusion is skipped when None". So on an unquantized checkpoint all three norm
sites take the fused op with nothing to fold in: with ``fp4_input_scale`` None,
``apply_fused_layernorm_*`` falls through to the dense bf16 path, which
re-derives the LayerNorm statistics in the kernel instead of calling ATen's.

That fall-through is not bit-exact with ``F.layer_norm``, and the goldens are
pre-fusion self-goldens that admit almost no deviation, so wan22-fp8-blockwise
scored 0.359163 and wan22-cuda-graph 0.242206 against a 0.05 threshold.

Three things pin the diagnosis. The golden media in
visual_gen_lpips_golden_media.zip is dated 2026-07-23 while the fusion landed
2026-07-28, so every wan22 feature golden encodes the pre-fusion eager numerics.
hidden_size is num_attention_heads * attention_head_dim, so Wan2.1-T2V-1.3B is
1536 and never matched the predicate -- which is why its three cases pass and
serve as the control -- while Wan2.2-T2V-A14B is exactly 5120. And all three
wan22 profiles fail together rather than just a quantized one because the tests
request dynamic quantization, and ``get_nvfp4_input_scale`` returns None when
``force_dynamic_quantization`` is set, so fp8-blockwise, cuda-graph and nvfp4
alike reach the fused op with no scale.

Gate each site on its own fp4 scale, mirroring the sibling fusions in
``flux/attention.py``, which already require ``has_nvfp4 and input_scale is not
None and pre_quant_scale is None and not force_dynamic_quantization``. Restoring
the eager path is necessary rather than cosmetic: no reformulation of the
kernel's arithmetic recovers the score -- fp32 params give 0.2268 and exact fp64
statistics 0.2351 -- because only ATen's own reduction is bit-exact with the
reference the golden encodes.

Verified on B200 (umb-b200-041): all 6
test_wan_feature_accuracy_against_golden cases pass at LPIPS 0.000000, exit 0,
including the three unwaived wan21 controls (unchanged) and wan22-nvfp4, where
the scales are present and the fusion stays engaged. test_wan_transformer.py
TestWanUnit is 5/5 with two added tests pinning the predicate in both
directions.

Removes the four wan feature waivers this change is measured against. The
remaining 6572800 waivers are deliberately retained: fastwan (hidden 3072, never
matched the predicate) and the flux/ltx2/qwenimage/cosmos3 NVFP4 cases, which
fail with "generator exited with code 1" from a spawn-child import error rather
than an accuracy delta -- a separate defect that does not reproduce here.

Signed-off-by: trtllm-agent <296075020+trtllm-agent@users.noreply.github.com>
@trtllm-agent
trtllm-agent force-pushed the repair-bot-bug6572800 branch from 1911042 to 1d8497d Compare August 19, 2026 12:03
@yibinl-nvidia

Copy link
Copy Markdown
Collaborator

Clos this in favor of #17933

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.

4 participants