Skip to content

[TRTLLM-12720][feat] Support nvfp4 w4a16 on sm120 - #16511

Open
pamelap-nvidia wants to merge 23 commits into
NVIDIA:mainfrom
pamelap-nvidia:qwen3_6_nvfp4_w4a16
Open

[TRTLLM-12720][feat] Support nvfp4 w4a16 on sm120#16511
pamelap-nvidia wants to merge 23 commits into
NVIDIA:mainfrom
pamelap-nvidia:qwen3_6_nvfp4_w4a16

Conversation

@pamelap-nvidia

@pamelap-nvidia pamelap-nvidia commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Dev Engineer Review

The changes add SM120/121 PyTorch support for W4A16 NVFP4 inference across dense linear, LM-head, and MoE paths.

  • Adds CUDA-core, Triton, Marlin, CUTLASS, and CuteDSL backend support.
  • Updates Marlin build and runtime guards for SM90 and SM120.
  • Adds compressed-tensors and ModelOpt configuration handling.
  • Adds checkpoint mapping for packed weights and global scales.
  • Adds backend-specific derived-state caching and Marlin weight transformation.
  • Updates MoE backend selection and W4A16 NVFP4 scale handling.
  • Restricts ReLU2 fusion to eligible static NVFP4 activation inputs.
  • Clarifies NVFP4 activation-quantization checks in DeepSeek models.
  • Adds SM12x support to Marlin GEMM test gating.

The reported local validation passes 74 merge-focused tests and 69 W4A16/model regression tests. Six CI runs failed or had L0 pipeline failures. Failure analysis and a new NVIDIA-triggered run are required.

QA Engineer Review

The PR adds test functions and coverage for:

  • Nemotron H MoE, MTP, and checkpoint mapping.
  • CuteDSL B12x W4A16 NVFP4 backend selection and scale transformation.
  • W4A16 NVFP4 linear, Marlin, Triton, LM-head, fusion, shape, and quantization behavior.
  • Model configuration and compressed-tensors parsing.
  • Marlin SM90/SM12x GEMM gating.
  • MoE activation-quantization behavior.

No files under tests/integration/test_lists/, test-db/, qa/, or waives.txt were modified. Coverage registration for the added test functions is not shown.

Verdict: needs follow-up.

Summary

Adds end-to-end support for W4A16 NVFP4 checkpoints (packed FP4 weights + per-group FP8
scales, high-precision activations) in the PyTorch backend, targeting Qwen3.5/3.6 and
Nemotron-H NVFP4 exports on SM120/121 (RTX 5090/6000, GB10) and Hopper.

The core problem this solves: TRT-LLM previously conflated "has NVFP4 weights" with
"quantizes activations to NVFP4". W4A16 breaks that assumption — it has FP4 weights but
consumes BF16/FP16 activations and has no calibrated input_scale. Every FP4 fusion site
keyed on has_nvfp4 would therefore feed an Fp4QuantizedTensor into a layer that can't
consume one, or read a None activation scale.

Changes

Checkpoint parsing

  • quant_config_utils.py: compressed-tensors configs with input_activations: null +
    format: nvfp4-pack-quantized + 4-bit float weights at group_size=16 now resolve to
    QuantAlgo.W4A16_NVFP4 instead of raising.
  • model_config.py / llm_utils.py: when hf_quant_config.json declares NVFP4 but the
    inline config.json compressed-tensors block says weight-only, the inline activation
    semantics win. Guarded so it doesn't re-enter the config.json global-quant fallback.
  • nemotron_h_weight_mapper.py: canonicalizes compressed-tensors key names
    (weight_packed -> weight, weight_global_scale -> weight_scale_2 with reciprocal
    conversion).

Activation-quantization capability, made explicit

  • New LinearMethodBase.quantizes_nvfp4_activations ClassVar, surfaced as
    Linear.has_nvfp4_activation_quantization and MoE.has_nvfp4_activation_quantization.
  • Every NVFP4 fusion gate now keys on that instead of has_nvfp4: RMSNorm folding
    (is_static_nvfp4_input_eligible), attention FP4 output, fused ReLU2/GELU/SwiGLU
    epilogues, GEMM-allreduce fusion, and the POST_MOE_FUSION paths in DeepSeek V3/V4, GLM,
    EXAONE and Qwen3-MoE.

Linear

  • W4A16NVFP4LinearMethod: on-the-fly Triton weight dequant. Leaves input_scale /
    inv_input_scale / alpha as None from create_weights onward; the parent
    process_weights_after_loading_* now skip scales whose destination was never allocated.
  • MarlinNVFP4LinearMethod: Marlin-backed W4A16, selected by default for BF16 on
    SM90/120/121. Handles its own K->64 / N->128 padding.
  • Per-block scales stay in swizzled layout; the unswizzled view is a derived non-persistent
    buffer, which also makes the GMS cache_derived_state refresh idempotent (the previous
    in-place unswizzle would double-apply on re-materialization).

MoE

  • CuteDslB12xFusedMoE accepts W4A16_NVFP4 and stays on the b12x path for both prefill
    and decode (quant_mode="w4a16"); falls back to CUTLASS for EP / attention-DP or
    non-SM120/121.
  • W4A16NVFP4CutlassFusedMoEMethod on the CUTLASS path; shared per-layer quant-config
    lookup so mixed-precision checkpoints resolve expert configs correctly.
  • Nemotron-H: promotes experts to W4A4 NVFP4 on non-CuteDSL backends, and routes BF16 MTP
    body sublayers to CUTLASS.

C++

  • Build the dense Marlin NVFP4 GEMM/repack kernels for 120f in addition to 90; relax the
    runtime SM asserts to 9.x || 12.x. No kernel logic changes.

No LLM API surface changellm_args.py is untouched, so no golden-manifest
regeneration.

Behavior changes for existing users

  • Hopper NVFP4 BF16 linears now use the Marlin GEMM backend by default (previously opt-in
    via nvfp4_gemm_config.allowed_backends: [..., marlin]). Attention FP4 output and the
    torch.compile inplace op are disabled on those layers as a consequence.
  • MoE backend AUTO resolves to CUTEDSL for W4A16 NVFP4 on SM120/121.

Test coverage

test_w4a16_nvfp4_linear.py (new) covers method selection across SM90/100/120/121 and dtype,
the Marlin-vs-Triton numerical match on GPU (including K/N padding shapes), scale-cache buffer
semantics, the mixed-precision use_fused_gemm_allreduce rebind, and every fusion gate that
changed. Plus new checkpoint-parsing tests (test_model_config.py,
test_quant_config_utils.py, test_kv_cache_dtype_override.py), Nemotron-H MoE/MTP config
tests, the weight-mapper tests, and W4A16 cases added to the b12x MoE backend suite.

PR 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-compatible or api-breaking. For api-breaking, include BREAKING in 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.

Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
@pamelap-nvidia
pamelap-nvidia marked this pull request as ready for review July 21, 2026 04:50
@pamelap-nvidia
pamelap-nvidia requested review from a team as code owners July 21, 2026 04:50
@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #60774 [ run ] completed with state FAILURE. Commit: 897d554
/LLM/main/L0_MergeRequest_PR pipeline #49055 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>

# Conflicts:
#	tensorrt_llm/_torch/models/checkpoints/hf/nemotron_h_weight_mapper.py
#	tensorrt_llm/_torch/modules/mlp.py
Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
@pamelap-nvidia
pamelap-nvidia requested a review from a team as a code owner August 3, 2026 05:40
@pamelap-nvidia

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63362 [ run ] triggered by Bot. Commit: 4e8170a Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63362 [ run ] completed with state FAILURE. Commit: 4e8170a

Link to invocation

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

Caution

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

⚠️ Outside diff range comments (1)
tensorrt_llm/_torch/models/modeling_deepseekv3.py (1)

755-756: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add the NVIDIA copyright header to tensorrt_llm/_torch/models/modeling_deepseekv3.py. Keep the DeepSeek 2023 notice and add the 2026 NVIDIA SPDX header used in tensorrt_llm/_torch/models/modeling_deepseekv4.py.

🤖 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/models/modeling_deepseekv3.py` around lines 755 - 756,
Add the 2026 NVIDIA SPDX copyright header to modeling_deepseekv3.py while
preserving its existing DeepSeek 2023 notice; use modeling_deepseekv4.py as the
reference for the exact header format. The referenced line in
modeling_deepseekv4.py requires no direct change.

Source: Coding guidelines

🧹 Nitpick comments (1)
tensorrt_llm/_torch/models/modeling_deepseekv3.py (1)

755-756: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the Python 3.10 annotation form for all new aux_stream_dict parameters.

The same new parameter uses Optional[Dict[...]] in both files. Apply dict[...] | None at each site.

  • tensorrt_llm/_torch/models/modeling_deepseekv3.py#L755-L756: update DeepseekV3Attention.aux_stream_dict.
  • tensorrt_llm/_torch/models/modeling_deepseekv3.py#L805-L806: update DeepseekV32Attention.aux_stream_dict.
  • tensorrt_llm/_torch/models/modeling_deepseekv4.py#L1319-L1319: update DeepseekV4Attention.aux_stream_dict.

As per coding guidelines, prefer built-in generic types and | for Python 3.10+ annotations.

🤖 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/models/modeling_deepseekv3.py` around lines 755 - 756,
Replace the Optional[Dict[...]] annotation with the Python 3.10 dict[...] | None
form for aux_stream_dict in DeepseekV3Attention and DeepseekV32Attention in
tensorrt_llm/_torch/models/modeling_deepseekv3.py at lines 755-756 and 805-806,
and in DeepseekV4Attention in tensorrt_llm/_torch/models/modeling_deepseekv4.py
at line 1319. Use built-in generic types consistently at all three sites.

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.

Outside diff comments:
In `@tensorrt_llm/_torch/models/modeling_deepseekv3.py`:
- Around line 755-756: Add the 2026 NVIDIA SPDX copyright header to
modeling_deepseekv3.py while preserving its existing DeepSeek 2023 notice; use
modeling_deepseekv4.py as the reference for the exact header format. The
referenced line in modeling_deepseekv4.py requires no direct change.

---

Nitpick comments:
In `@tensorrt_llm/_torch/models/modeling_deepseekv3.py`:
- Around line 755-756: Replace the Optional[Dict[...]] annotation with the
Python 3.10 dict[...] | None form for aux_stream_dict in DeepseekV3Attention and
DeepseekV32Attention in tensorrt_llm/_torch/models/modeling_deepseekv3.py at
lines 755-756 and 805-806, and in DeepseekV4Attention in
tensorrt_llm/_torch/models/modeling_deepseekv4.py at line 1319. Use built-in
generic types consistently at all three sites.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 60d3f155-b180-4cb0-a174-45b6cd94b449

📥 Commits

Reviewing files that changed from the base of the PR and between 4e8170a and 49f8ebc.

📒 Files selected for processing (4)
  • cpp/tensorrt_llm/common/attentionOp.cpp
  • tensorrt_llm/_torch/models/modeling_deepseekv3.py
  • tensorrt_llm/_torch/models/modeling_deepseekv4.py
  • tests/integration/defs/accuracy/test_llm_api_pytorch.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • cpp/tensorrt_llm/common/attentionOp.cpp
  • tests/integration/defs/accuracy/test_llm_api_pytorch.py

Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
@pamelap-nvidia

Copy link
Copy Markdown
Collaborator Author

/bot run

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63492 [ run ] triggered by Bot. Commit: 137b965 Link to invocation

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

Caution

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

⚠️ Outside diff range comments (2)
tensorrt_llm/_torch/modules/fused_moe/create_moe.py (2)

133-150: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Return CutlassFusedMoE when FlashInfer is unavailable on SM120/SM121.

For standard NVFP4, this branch returns CuteDslFusedMoE, but CuteDslFusedMoE.can_implement() rejects SM120/SM121. CutlassFusedMoE supports NVFP4 on both architectures.

🤖 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/modules/fused_moe/create_moe.py` around lines 133 - 150,
Update the standard NVFP4 fallback in the surrounding MoE selection logic to
return CutlassFusedMoE when FlashInfer is unavailable on SM120 or SM121.
Preserve the existing CuteDslFusedMoE selection for architectures it supports,
and align this path with the can_implement behavior of CuteDslFusedMoE and
CutlassFusedMoE.

79-81: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Resolve the per-layer quantization configuration before backend selection. Qwen3MoE passes layer_idx but no override_quant_config, so both functions use the global model_config.quant_config and ignore quant_config_dict. This selects the wrong backend for mixed-precision experts. Resolve model.layers.{layer_idx}.mlp.experts in both functions, or pass it from every caller.

🤖 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/modules/fused_moe/create_moe.py` around lines 79 - 81,
The quantization setup currently ignores layer-specific entries in
quant_config_dict when override_quant_config is absent. Update both affected
functions to resolve model.layers.{layer_idx}.mlp.experts before backend
selection, while preserving override_quant_config precedence; alternatively
ensure every caller, including Qwen3MoE, passes the resolved per-layer
configuration.
🧹 Nitpick comments (1)
tests/unittest/_torch/modules/moe/test_moe_backend.py (1)

330-334: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add CI coverage for the new capability test and fallback paths.

test_moe_nvfp4_activation_quantization_capability is not selected by the existing test_moe_backend entries in the applicable test-db files. Add an explicit entry and cover W4A16 NVFP4 selection, missing FlashInfer, and unsupported SM fallback.

Test coverage summary — needs follow-up. Added: test_moe_nvfp4_activation_quantization_capability. Removed test: function name not determinable.

🤖 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/modules/moe/test_moe_backend.py` around lines 330 -
334, Add explicit test-db entries for
test_moe_nvfp4_activation_quantization_capability and the related W4A16 NVFP4
selection, missing FlashInfer, and unsupported-SM fallback tests, ensuring the
applicable test_moe_backend suites select them in CI. Preserve existing test-db
conventions and include every relevant fallback-path test.

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.

Outside diff comments:
In `@tensorrt_llm/_torch/modules/fused_moe/create_moe.py`:
- Around line 133-150: Update the standard NVFP4 fallback in the surrounding MoE
selection logic to return CutlassFusedMoE when FlashInfer is unavailable on
SM120 or SM121. Preserve the existing CuteDslFusedMoE selection for
architectures it supports, and align this path with the can_implement behavior
of CuteDslFusedMoE and CutlassFusedMoE.
- Around line 79-81: The quantization setup currently ignores layer-specific
entries in quant_config_dict when override_quant_config is absent. Update both
affected functions to resolve model.layers.{layer_idx}.mlp.experts before
backend selection, while preserving override_quant_config precedence;
alternatively ensure every caller, including Qwen3MoE, passes the resolved
per-layer configuration.

---

Nitpick comments:
In `@tests/unittest/_torch/modules/moe/test_moe_backend.py`:
- Around line 330-334: Add explicit test-db entries for
test_moe_nvfp4_activation_quantization_capability and the related W4A16 NVFP4
selection, missing FlashInfer, and unsupported-SM fallback tests, ensuring the
applicable test_moe_backend suites select them in CI. Preserve existing test-db
conventions and include every relevant fallback-path test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 0f87bc57-198a-4222-bf72-1654d8ab2cfe

📥 Commits

Reviewing files that changed from the base of the PR and between 49f8ebc and 137b965.

📒 Files selected for processing (5)
  • tensorrt_llm/_torch/model_config.py
  • tensorrt_llm/_torch/modules/fused_moe/create_moe.py
  • tests/unittest/_torch/modules/moe/test_cute_dsl_b12x_moe_backend.py
  • tests/unittest/_torch/modules/moe/test_moe_backend.py
  • tests/unittest/_torch/test_model_config.py
💤 Files with no reviewable changes (2)
  • tests/unittest/_torch/test_model_config.py
  • tests/unittest/_torch/modules/moe/test_cute_dsl_b12x_moe_backend.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tensorrt_llm/_torch/model_config.py

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63492 [ run ] completed with state SUCCESS. Commit: 137b965
/LLM/main/L0_MergeRequest_PR pipeline #51461 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

@pamelap-nvidia

Copy link
Copy Markdown
Collaborator Author

/bot run --disable-fail-fast

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63514 [ run ] triggered by Bot. Commit: 137b965 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63514 [ run ] completed with state SUCCESS. Commit: 137b965
/LLM/main/L0_MergeRequest_PR pipeline #51482 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

Signed-off-by: Pamela <179191831+pamelap-nvidia@users.noreply.github.com>
@pamelap-nvidia

Copy link
Copy Markdown
Collaborator Author

/bot run

@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

🧹 Nitpick comments (1)
tensorrt_llm/_torch/modules/linear.py (1)

2127-2132: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add type annotations to the override.

get_tp_alignment() omits parameter and return annotations. Add precise types for tp_mode, quant_config, and the integer return value.

Based on coding guidelines, “Annotate every function.”

🤖 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/modules/linear.py` around lines 2127 - 2132, Update the
get_tp_alignment override to add precise type annotations for tp_mode and
quant_config, and annotate its return value as int; preserve the existing
parameters, default value, and return of 32.

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/modules/linear.py`:
- Around line 2024-2026: Update W4A16NVFP4LinearMethod._prepare_input() to
explicitly reject FP8 input with a RuntimeError rather than an assertion,
consistent with the cleared module.inv_input_scale state. Add a regression test
verifying FP8 input raises RuntimeError while preserving supported W4A16
behavior.

In `@tests/unittest/_torch/thop/parallel/test_fp4_linear.py`:
- Line 815: Remove the obsolete FP4 activation quantization setup in the test
around the W4A16_NVFP4 QuantConfig, including the unused x_fp4 and x_sf_block
assignments; pass the high-precision x directly to l_marlin and retain only
values still consumed by the test.

---

Nitpick comments:
In `@tensorrt_llm/_torch/modules/linear.py`:
- Around line 2127-2132: Update the get_tp_alignment override to add precise
type annotations for tp_mode and quant_config, and annotate its return value as
int; preserve the existing parameters, default value, and return of 32.
🪄 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: 7036ddf7-7d41-457e-8579-d319b1695e0e

📥 Commits

Reviewing files that changed from the base of the PR and between 137b965 and e5eb6c9.

📒 Files selected for processing (4)
  • tensorrt_llm/_torch/modules/linear.py
  • tests/unittest/_torch/modules/moe/test_cute_dsl_b12x_moe_backend.py
  • tests/unittest/_torch/modules/test_w4a16_nvfp4_linear.py
  • tests/unittest/_torch/thop/parallel/test_fp4_linear.py
💤 Files with no reviewable changes (1)
  • tests/unittest/_torch/modules/test_w4a16_nvfp4_linear.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/unittest/_torch/modules/moe/test_cute_dsl_b12x_moe_backend.py

Comment on lines +2024 to +2026
module.input_scale = None
module.inv_input_scale = None
module.alpha = None

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline tensorrt_llm/_torch/modules/linear.py \
  --items all \
  --match 'W4A16NVFP4LinearMethod|MarlinNVFP4LinearMethod' \
  --view expanded

rg -n -C 3 --type py \
  'torch\.float8_e4m3fn|Fp4QuantizedTensor|W4A16NVFP4LinearMethod|is_static_nvfp4_input_eligible' \
  tensorrt_llm tests

Repository: NVIDIA/TensorRT-LLM

Length of output: 50376


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- linear.py target methods ---'
sed -n '1980,2155p' tensorrt_llm/_torch/modules/linear.py

printf '%s\n' '--- W4A16NVFP4LinearMethod references ---'
rg -n -C 5 --type py 'W4A16NVFP4LinearMethod|_prepare_input\(' tensorrt_llm/_torch tests/unittest/_torch

printf '%s\n' '--- FP8 input production and invocation paths ---'
rg -n -C 5 --type py \
  'to\(torch\.float8_e4m3fn\)|dtype=torch\.float8_e4m3fn|input_scale|inv_input_scale' \
  tensorrt_llm/_torch/modules tensorrt_llm/_torch/models tests/unittest/_torch/modules

Repository: NVIDIA/TensorRT-LLM

Length of output: 50376


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- target implementation ---'
sed -n '1995,2145p' tensorrt_llm/_torch/modules/linear.py

printf '%s\n' '--- direct references in linear.py and nearby tests ---'
rg -n -C 4 \
  'W4A16NVFP4LinearMethod|torch\.float8_e4m3fn|inv_input_scale|input_scale' \
  tensorrt_llm/_torch/modules/linear.py \
  tests/unittest/_torch/modules/linear.py \
  tests/unittest/_torch/modules/test_linear.py \
  tests/unittest/_torch/modules 2>/dev/null | head -n 1000

printf '%s\n' '--- callers of Linear with FP8 activation configuration ---'
rg -n -C 4 --type py \
  'dtype_activation|activation_dtype|torch\.float8_e4m3fn|w4a16|W4A16' \
  tensorrt_llm/_torch/modules tensorrt_llm/_torch/models tests/unittest/_torch/modules \
  | head -n 1500

Repository: NVIDIA/TensorRT-LLM

Length of output: 50375


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- W4A16 and activation-quantization symbols ---'
rg -n -C 6 --type py \
  'W4A16NVFP4LinearMethod|MarlinNVFP4LinearMethod|quantizes_nvfp4_activations|is_static_nvfp4_input_eligible' \
  tensorrt_llm/_torch/modules/linear.py \
  tensorrt_llm/_torch/modules/mla.py \
  tensorrt_llm/_torch/modules/rms_norm.py \
  tests/unittest/_torch/modules 2>/dev/null | head -n 1600

printf '%s\n' '--- upstream FP8-producing paths near Linear calls ---'
rg -n -C 5 --type py \
  'torch\.float8_e4m3fn|fp8_quant|quantize.*fp8|return.*fp8|Linear\(' \
  tensorrt_llm/_torch/modules/mla.py \
  tensorrt_llm/_torch/modules/rms_norm.py \
  tensorrt_llm/_torch/modules/linear.py \
  tests/unittest/_torch/modules 2>/dev/null | head -n 1600

printf '%s\n' '--- tests mentioning W4A16/Marlin/NVFP4 linear ---'
rg -l --type py \
  'W4A16NVFP4LinearMethod|MarlinNVFP4LinearMethod|W4A16|Marlin.*NVFP4|NVFP4.*Marlin' \
  tests tensorrt_llm/_torch | sort

Repository: NVIDIA/TensorRT-LLM

Length of output: 50376


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- current change for W4A16 input handling ---'
git diff --unified=12 -- tensorrt_llm/_torch/modules/linear.py \
  | sed -n '/W4A16NVFP4LinearMethod/,/MarlinNVFP4LinearMethod/p'

printf '%s\n' '--- canonical eligibility predicate ---'
sed -n '3890,3935p' tensorrt_llm/_torch/modules/linear.py

printf '%s\n' '--- relevant existing tests ---'
sed -n '540,640p' tests/unittest/_torch/modules/test_w4a16_nvfp4_linear.py
sed -n '780,860p' tests/unittest/_torch/modules/test_w4a16_nvfp4_linear.py

printf '%s\n' '--- Linear input dispatch ---'
sed -n '3600,3760p' tensorrt_llm/_torch/modules/linear.py

Repository: NVIDIA/TensorRT-LLM

Length of output: 15225


Reject FP8 input explicitly in W4A16NVFP4LinearMethod._prepare_input().

W4A16 is a weight-only path and clears module.inv_input_scale. Replace the FP8 assertion with a RuntimeError and add a regression test.

🤖 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/modules/linear.py` around lines 2024 - 2026, Update
W4A16NVFP4LinearMethod._prepare_input() to explicitly reject FP8 input with a
RuntimeError rather than an assertion, consistent with the cleared
module.inv_input_scale state. Add a regression test verifying FP8 input raises
RuntimeError while preserving supported W4A16 behavior.

bias=False,
dtype=dtype,
quant_config=QuantConfig(quant_algo=QuantAlgo.NVFP4),
quant_config=QuantConfig(quant_algo=QuantAlgo.W4A16_NVFP4),

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Remove unused FP4 activation quantization.

After this change, the test passes high-precision x to l_marlin. x_fp4 and x_sf_block at lines 839-840 have no use. Ruff F841 rejects these assignments. Remove the obsolete quantization setup.

Proposed fix
-        x_sf_global = (448 * 6) / x.abs().max().float()
-        x_fp4, x_sf_block = torch.ops.trtllm.fp4_quantize(
-            x, x_sf_global, scaling_vector_size, False)
-
         with torch.inference_mode():
             output = l_marlin(x)

Based on learnings, Ruff enables F rules in this repository.

🤖 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/thop/parallel/test_fp4_linear.py` at line 815, Remove
the obsolete FP4 activation quantization setup in the test around the
W4A16_NVFP4 QuantConfig, including the unused x_fp4 and x_sf_block assignments;
pass the high-precision x directly to l_marlin and retain only values still
consumed by the test.

Source: Learnings

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63638 [ run ] triggered by Bot. Commit: e5eb6c9 Link to invocation

@tensorrt-cicd

Copy link
Copy Markdown
Collaborator

PR_Github #63638 [ run ] completed with state FAILURE. Commit: e5eb6c9
/LLM/main/L0_MergeRequest_PR pipeline #51593 completed with status: 'FAILURE'

CI Report

⚠️ Action Required:

  • Please check the failed tests and fix your PR
  • If you cannot view the failures, ask the CI triggerer to share details
  • Once fixed, request an NVIDIA team member to trigger CI again

CI Agent Failure Analysis

Link to invocation

Comment on lines +61 to +62

def _canonicalize_quant_weight(key: str, value):

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.

please add a comment about why and which quantization config will use the if condition.

return layer_quant_config

quant_config = model_config.quant_config
if (quant_config is not None and quant_config.quant_algo

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.

it is quite confusing to me.

what if we pass MARLIN moe backend on Hopper, would it fallback to NVFP4 will cause issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants