Skip to content

Remove the view() calls from Linear/LNLinear/LNMLP modules - #3523

Open
ptrendx wants to merge 12 commits into
NVIDIA:mainfrom
ptrendx:pr_view_remove_lnmlp
Open

ptrendx wants to merge 12 commits into
NVIDIA:mainfrom
ptrendx:pr_view_remove_lnmlp

Conversation

@ptrendx

@ptrendx ptrendx commented Sep 15, 2026

Copy link
Copy Markdown
Member

Description

This PR removes the unnecessary calls to view() from the TE modules to avoid the CPU overhead.

Results on GB200 (just the CPU time is reported):

Module             Precision               Forward    CPU reduction    Forward + backward    CPU reduction
  ━━━━━━━━━━━━━━━━━  ━━━━━━━━━━━  ━━━━━━━━━━━━━━━━━━━━  ━━━━━━━━━━━━━━━  ━━━━━━━━━━━━━━━━━━━━  ━━━━━━━━━━━━━━━
   Linear             BF16           59.19 → 51.19 µs            13.5%    311.30 → 276.50 µs            11.2%
  ─────────────────  ───────────  ────────────────────  ───────────────  ────────────────────  ───────────────
   Linear             MXFP8        114.51 → 103.62 µs             9.5%    440.93 → 416.92 µs             5.4%
  ─────────────────  ───────────  ────────────────────  ───────────────  ────────────────────  ───────────────
   LayerNormLinear    BF16           83.48 → 65.25 µs            21.8%    397.73 → 349.00 µs            12.3%
  ─────────────────  ───────────  ────────────────────  ───────────────  ────────────────────  ───────────────
   LayerNormLinear    MXFP8        135.42 → 121.07 µs            10.6%    518.67 → 490.49 µs             5.4%
  ─────────────────  ───────────  ────────────────────  ───────────────  ────────────────────  ───────────────
   LayerNormMLP       BF16         210.44 → 189.08 µs            10.2%    749.00 → 683.15 µs             8.8%
  ─────────────────  ───────────  ────────────────────  ───────────────  ────────────────────  ───────────────
   LayerNormMLP       MXFP8        236.67 → 221.99 µs             6.2%    797.14 → 765.84 µs             3.9%

Each commit is standalone and can be reviewed on its own.

Type of change

  • Documentation change (change only to the documentation, either a fix or a new content)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Infra/Build change
  • Code refactoring

Changes

Please list the changes introduced in this PR:

  • Change A
  • Change B

Checklist:

  • I have read and followed the contributing guidelines
  • The functionality is complete
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

transpose

Signed-off-by: Przemek Tredak <ptredak@nvidia.com>
Signed-off-by: Przemek Tredak <ptredak@nvidia.com>
…bias gradient

Signed-off-by: Przemek Tredak <ptredak@nvidia.com>
Signed-off-by: Przemek Tredak <ptredak@nvidia.com>
Signed-off-by: Przemek Tredak <ptredak@nvidia.com>
Signed-off-by: Przemek Tredak <ptredak@nvidia.com>
@ptrendx
ptrendx requested a review from ksivaman as a code owner September 15, 2026 23:35
@ptrendx

ptrendx commented Sep 15, 2026

Copy link
Copy Markdown
Member Author

/te-ci

@greptile-apps

greptile-apps Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge, with no outstanding findings or newly introduced actionable failures.

Summary

This PR removes activation-flattening and output-restoration views from Linear, LayerNormLinear, and LayerNormMLP while extending lower-level normalization, transpose, GEMM, bias-gradient, custom-recipe, and communication-overlap paths to preserve logical tensor shapes directly.

  • Preserves rank-1 and higher-rank activation shapes through forward and backward operations.
  • Updates normalization, transpose, GEMM, and bias-gradient implementations for logical N-D tensors.
  • Adds coverage for noncontiguous inputs, custom recipes, distributed overlap, and torch.compile.
  • The only change since the previous review adds ndim support to debug quantized tensors.

Reviews (4) · Last reviewed commit: "Fix the debug test"

Comment thread transformer_engine/pytorch/custom_recipes/gemm.py
Signed-off-by: Przemek Tredak <ptredak@nvidia.com>
@ptrendx

ptrendx commented Sep 16, 2026

Copy link
Copy Markdown
Member Author

/te-ci

ptrendx and others added 3 commits September 17, 2026 14:26
# Conflicts:
#	transformer_engine/pytorch/module/layernorm_linear.py
#	transformer_engine/pytorch/module/layernorm_mlp.py
Signed-off-by: Przemek Tredak <ptredak@nvidia.com>
@ptrendx

ptrendx commented Sep 18, 2026

Copy link
Copy Markdown
Member Author

/te-ci

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

LGTM. My comments are nits. Its surprising how using views for semantic convinience introduces so much CPU overheads. GroupedLinear would also benefit with similar optimizations I hope.

Comment on lines +206 to +212
NVTE_CHECK(output.data.shape[0] == row_length, "Output has invalid first dimension (expected ",
row_length, ", got ", output.data.shape[0], ").");
const size_t output_cols = std::accumulate(output.data.shape.begin() + 1, output.data.shape.end(),
size_t{1}, std::multiplies<size_t>());
NVTE_CHECK(output_cols == num_rows,
"Output has invalid product of dimensions after the first (expected ", num_rows,
", got ", output_cols, ").");

@vthumbe1503 vthumbe1503 Sep 19, 2026

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.

Nit: can we use flat_2d_dims for output as well?

Suggested change
NVTE_CHECK(output.data.shape[0] == row_length, "Output has invalid first dimension (expected ",
row_length, ", got ", output.data.shape[0], ").");
const size_t output_cols = std::accumulate(output.data.shape.begin() + 1, output.data.shape.end(),
size_t{1}, std::multiplies<size_t>());
NVTE_CHECK(output_cols == num_rows,
"Output has invalid product of dimensions after the first (expected ", num_rows,
", got ", output_cols, ").");
const auto [out_rows, out_cols] = output.flat_2d_dims();
NVTE_CHECK(out_rows== row_length, "Output has invalid first dimension (expected ",
row_length, ", got ", out_rows, ").");
NVTE_CHECK(out_cols == num_rows,
"Output has invalid product of dimensions after the first (expected ", num_rows,
", got ", out_cols, ").");

Comment thread transformer_engine/pytorch/jit.py
if return_layernorm_output:
if return_layernorm_output_gathered:
shape = list(inp_shape)
shape[0] *= tp_size if (sequence_parallel and set_parallel_mode) else 1

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.

lint seems to be failing since tp_size is not longer used in this function

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.

2 participants