Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
cb69309
[PyTorch] Register an op's forward and backward without autograd glue
pggPL Aug 5, 2026
419c4e2
[PyTorch] Compile an OperationFuser group holding one operation
pggPL Aug 5, 2026
7cf976f
[PyTorch] Accept an operation's declared forward kwargs under compile
pggPL Aug 6, 2026
4f773fc
[PyTorch] Restrict compiled forward kwargs to tensors
pggPL Aug 7, 2026
97e4764
[PyTorch] Refine fusible custom-op integration
pggPL Sep 4, 2026
b86d8f9
[PyTorch] Decline fused grouped MLP when the backward format is not E…
wilyan09007 Sep 4, 2026
e61b66d
[PyTorch] Fix: Resolve EP symm-mem window offset for both old and new…
phu0ngng Sep 4, 2026
1f25d6a
[NCCL][PyTorch] Fix test-fusible-ops-file-rendezvous-bug (#3478)
nWEIdia Sep 4, 2026
80a89ad
Reduce Grouped MLP Fuser CPU Overhead (#3410)
zhongbozhu Sep 4, 2026
d1e9c33
Use cuDNN's deterministic dprob in the fused grouped MLP (#3407)
ZhiyuLi-Nvidia Sep 4, 2026
29229b5
[PyTorch] Reduce CUDA graph memory retention (#3427)
buptzyb Sep 4, 2026
846379d
Relax runtime checks for activation recompute into Warnings (#3436)
ghadiaravi13 Sep 4, 2026
a30aee5
fix: Unreachable backend check after earlier backend skip (#3368)
andrewwhitecdw Sep 5, 2026
5f6105b
[Common] Preserve shared-memory pointer provenance in TMA kernels (#3…
Oleg-Goncharov Sep 5, 2026
dc8909d
Update Linear docstring referring torch.Linear (#3491)
negvet Sep 8, 2026
f2bec23
[PyTorch] Document fine-grained quantization recipes (#3336)
negvet Sep 8, 2026
cd24504
Fix hybrid fp8 test guard (#3492)
negvet Sep 8, 2026
2281cd5
[PyTorch] Register custom ops one at a time
pggPL Sep 8, 2026
b97f5ab
[PyTorch] Use torch's register_custom_class API for opaque quantizers…
mmarcinkiewicz Sep 8, 2026
7c6fa59
Add entrypoint for flagos multi-backend plugin system (#3401)
lxd-cumt Sep 9, 2026
39a5401
[PyTorch] Fix NaN expert weight gradients at num_groups == 1 with SRe…
GarlGuo Sep 9, 2026
7ba2f9f
[Common] Fix Grouped MXFP8 work mapping and TMA synchronization (#3483)
Oleg-Goncharov Sep 9, 2026
1b178bc
[PyTorch] Derive an op's compile declarations; gate groups to one op
pggPL Sep 9, 2026
d88c652
Merge remote-tracking branch 'upstream/main' into ops_fuser_compile_main
pggPL Sep 9, 2026
e1b33b0
[PyTorch] Tidy BasicOperation's compile plumbing
pggPL Sep 9, 2026
048162b
[PyTorch] Name an op's custom-op methods after Linear's
pggPL Sep 9, 2026
2f8582f
[PyTorch] Guard compiled fuser cleanup and delayed scaling
pggPL Sep 9, 2026
4c60703
[PyTorch] Remove added fuser regression tests
pggPL Sep 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions docs/_static/css/diagram-colors.css
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,18 @@ html[data-theme="dark"] .subtitle,
html[data-theme="dark"] .memory-label { fill: #e0e0e0; }
html[data-theme="dark"] .connector { stroke: #bdbdbd; }


/* fine_grained_quantization diagrams */
html[data-theme="dark"] .fmt-mxfp8 { fill: #10375c; stroke: #64b5f6; }
html[data-theme="dark"] .fmt-nvfp4 { fill: #5c3a10; stroke: #ffb74d; }
html[data-theme="dark"] .fmt-bf16 { fill: #1e4620; stroke: #81c784; }
html[data-theme="dark"] .fmt-mxfp8-text { fill: #90caf9; }
html[data-theme="dark"] .fmt-nvfp4-text { fill: #ffcc80; }
html[data-theme="dark"] .fmt-bf16-text { fill: #a5d6a7; }
html[data-theme="dark"] .source { fill: #3a2f5c; stroke: #b39ddb; }
html[data-theme="dark"] .quantizer { fill: #1e4620; stroke: #81c784; }
html[data-theme="dark"] .representation { fill: #10375c; stroke: #64b5f6; }
html[data-theme="dark"] .dequantize { fill: #5c3a10; stroke: #ffb74d; }
html[data-theme="dark"] .rowlabel,
html[data-theme="dark"] .legend,
html[data-theme="dark"] .op { fill: #e0e0e0; }
20 changes: 19 additions & 1 deletion docs/api/pytorch.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
PyTorch
=======

.. autoapiclass:: transformer_engine.pytorch.Linear(in_features, out_features, bias=True, **kwargs)
.. autoapiclass:: transformer_engine.pytorch.Linear(in_features, out_features, **kwargs)
:members: forward, set_tensor_parallel_group

.. autoapiclass:: transformer_engine.pytorch.GroupedLinear(in_features, out_features, bias=True, **kwargs)
Expand Down Expand Up @@ -112,6 +112,12 @@ Communication-computation overlap
:members: FP8, NONE


Fine-grained quantization recipes
---------------------------------

.. autoapiclass:: transformer_engine.pytorch.QuantizerRole(module_type="", tensor_type="", name="")


Quantized tensors
-----------------

Expand All @@ -129,6 +135,10 @@ Quantized tensors

.. autoapiclass:: transformer_engine.pytorch.NVFP4TensorStorage(rowwise_data, rowwise_scale_inv, columnwise_data, columnwise_scale_inv, amax_rowwise, amax_columnwise, fp4_dtype, quantizer)

.. autoapiclass:: transformer_engine.pytorch.HybridQuantizedTensorStorage(*, rowwise_storage, columnwise_storage, quantizer, fake_dtype=None)

.. autoapiclass:: transformer_engine.pytorch.IdentityTensorStorage(*, hp_data, fake_dtype=None, quantizer=None)

.. autoapiclass:: transformer_engine.pytorch.Float8Tensor(shape, dtype, data, fp8_scale_inv, fp8_dtype, requires_grad=False, data_transpose=None, quantizer=None)

.. autoapiclass:: transformer_engine.pytorch.MXFP8Tensor(rowwise_data, rowwise_scale_inv, columnwise_data, columnwise_scale_inv, fp8_dtype, quantizer)
Expand All @@ -137,6 +147,10 @@ Quantized tensors

.. autoapiclass:: transformer_engine.pytorch.NVFP4Tensor(rowwise_data, rowwise_scale_inv, columnwise_data, columnwise_scale_inv, amax_rowwise, amax_columnwise, fp4_dtype, quantizer)

.. autoapiclass:: transformer_engine.pytorch.HybridQuantizedTensor(shape, dtype, *, rowwise_storage, columnwise_storage, quantizer, requires_grad=False, device=None)

.. autoapiclass:: transformer_engine.pytorch.IdentityTensor(shape, dtype, *, hp_data, quantizer=None, requires_grad=False, device=None)

Quantizers
----------

Expand All @@ -153,6 +167,10 @@ Quantizers

.. autoapiclass:: transformer_engine.pytorch.NVFP4Quantizer(fp4_dtype, *, rowwise=True, columnwise=True, **kwargs)

.. autoapiclass:: transformer_engine.pytorch.HybridQuantizer(*, rowwise_quantizer, columnwise_quantizer, columnwise_source="original")

.. autoapiclass:: transformer_engine.pytorch.IdentityQuantizer(*, dtype=None, rowwise=True, columnwise=True)

Tensor saving and restoring functions
-------------------------------------

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#!/usr/bin/env python3
# Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# See LICENSE for license information.

"""Runnable fine-grained quantization recipe example.

The factory assigns one precision to each ``demo.fc1`` Linear GEMM:

* fprop: ``weight.row(MXFP8) x input.row(MXFP8)``
* dgrad: ``weight.col(NVFP4) x grad_output.row(NVFP4)``
* wgrad: ``input.col(original BF16) x grad_output.col(original BF16)``

``demo.fc2`` runs every GEMM in high precision. ``demo.output`` is not
special-cased and therefore exercises the MXFP8 base-factory fallback.

Run from the Transformer Engine repository root::

python docs/examples/fine_grained_quantization/\
pytorch_fine_grained_quantization_example.py
"""

from __future__ import annotations

import torch
import transformer_engine.pytorch as te


def require_supported_hardware() -> None:
"""Fail early with TE's reason when either required format is unavailable."""

if not torch.cuda.is_available():
raise SystemExit("This example requires a CUDA-capable NVIDIA GPU.")

failures = []
for name, check in (
("MXFP8", te.is_mxfp8_available),
("NVFP4", te.is_nvfp4_available),
):
available, reason = check(return_reason=True)
if not available:
failures.append(f"{name}: {reason}")
if failures:
raise SystemExit("Required formats are unavailable: " + "; ".join(failures))


require_supported_hardware()

# START_FINE_GRAINED_QUANTIZATION_EXAMPLE

from typing import Optional

import torch

import transformer_engine.pytorch as te
from transformer_engine.common.recipe import CustomRecipe
from transformer_engine.pytorch.custom_recipes.quantizer_factories import (
mxfp8_factory,
nvfp4_factory,
)


THREE_FORMAT_MODULE = "demo.fc1"
HIGH_PRECISION_MODULE = "demo.fc2"
BASE_FACTORY = mxfp8_factory


def quantizer_factory(role: Optional[te.QuantizerRole]):
"""Return a fresh quantizer for every role, including ``None``.

``BASE_FACTORY`` makes the factory total: unknown roles, future role values,
and untargeted modules all retain valid MXFP8 behavior.
"""

if role is not None and role.name == THREE_FORMAT_MODULE:
# Constructing fresh child quantizers for every call is recommended.
if role.tensor_type == "input":
# Wgrad retains the original BF16 input.
return te.HybridQuantizer(
rowwise_quantizer=mxfp8_factory(role),
columnwise_quantizer=te.IdentityQuantizer(),
columnwise_source="original",
)
if role.tensor_type == "weight":
# Dgrad uses NVFP4 quantized from the dequantized MXFP8 fprop weight.
return te.HybridQuantizer(
rowwise_quantizer=mxfp8_factory(role),
columnwise_quantizer=nvfp4_factory(role),
columnwise_source="rowwise_dequantized",
)
if role.tensor_type == "grad_output":
# Dgrad uses NVFP4 while wgrad retains the original BF16 gradient.
return te.HybridQuantizer(
rowwise_quantizer=nvfp4_factory(role),
columnwise_quantizer=te.IdentityQuantizer(),
columnwise_source="original",
)

if role is not None and role.name == HIGH_PRECISION_MODULE:
return te.IdentityQuantizer()

return BASE_FACTORY(role)


linear_options = {"bias": False, "params_dtype": torch.bfloat16, "device": "cuda"}
model = torch.nn.Sequential(
te.Linear(128, 256, name=THREE_FORMAT_MODULE, **linear_options),
torch.nn.GELU(),
te.Linear(256, 256, name=HIGH_PRECISION_MODULE, **linear_options),
torch.nn.GELU(),
te.Linear(256, 128, name="demo.output", **linear_options),
)
inputs = torch.randn(64, 128, device="cuda", dtype=torch.bfloat16, requires_grad=True)
recipe = CustomRecipe(qfactory=quantizer_factory)

with te.autocast(enabled=True, recipe=recipe):
outputs = model(inputs)

loss = outputs.float().square().mean()
loss.backward()

# END_FINE_GRAINED_QUANTIZATION_EXAMPLE

gradients = [inputs.grad, *(parameter.grad for parameter in model.parameters())]
assert all(gradient is not None for gradient in gradients)
assert all(torch.isfinite(gradient).all() for gradient in gradients)

print(f"GPU: {torch.cuda.get_device_name()}")
print(f"TE Linear names: {[model[index].name for index in (0, 2, 4)]}")
print(f"loss: {loss.item():.6f}; forward and backward completed")
Loading
Loading