Skip to content

Commit d5c1b24

Browse files
committed
fix lint and comments.
Signed-off-by: Shiqing Fan <shiqingf@nvidia.com>
1 parent 5419298 commit d5c1b24

4 files changed

Lines changed: 75 additions & 11 deletions

File tree

tests/pytorch/distributed/test_gtp.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,3 +1604,55 @@ def test_fallback_skipped_when_already_finalized(self):
16041604
assert torch.all(
16051605
p.main_grad == 5.0
16061606
), "main_grad must be untouched when _already_finalized=True"
1607+
1608+
@pytest.mark.skipif(not torch.cuda.is_available(), reason="CUDA required")
1609+
def test_fallback_skipped_for_pure_ag_param(self):
1610+
"""Regression: cross-graph fwd-AG prefetch in flight + finalize_after_drain=True.
1611+
1612+
A param can be in _inflight_comm_params because of an outstanding async
1613+
all-gather (e.g. a cross-graph forward prefetch reaching the
1614+
bwd→optimizer boundary). No reduce-scatter was ever issued for that
1615+
param, so _rs_ticket is None on every weight. Previously the fallback
1616+
called cache.get(None) and crashed with KeyError; the guard now skips
1617+
the inline accumulation entirely when no weight has an RS ticket.
1618+
"""
1619+
dtype = torch.bfloat16
1620+
p = GTPShardedParam(torch.zeros(8, 4, dtype=dtype, device="cuda"))
1621+
p.group = self._FakeGroup()
1622+
p.expert_idx = None
1623+
p.pad_length = 0
1624+
p.chain_id = gtp_module.GTPChain.UNGRAPHED.value
1625+
p._quantizer = None
1626+
p.is_routed_expert = False
1627+
# Pre-existing main_grad with a sentinel that must survive untouched.
1628+
p.main_grad = torch.full((8, 4), 7.0, dtype=dtype, device="cuda")
1629+
p._prefetch_handle = None
1630+
p._wgrad_rs_handle = None
1631+
p._cached_ag_stream = None
1632+
p._cached_rs_stream = None
1633+
p.ag_event = torch.cuda.Event(external=True)
1634+
p.rs_event = torch.cuda.Event(external=True)
1635+
p.rs_event.record()
1636+
p._already_finalized = False
1637+
# Critical: simulates a pure-AG prefetch — no RS ever issued, ticket is None.
1638+
p._rs_ticket = None
1639+
1640+
saved = set(gtp_module._inflight_comm_params)
1641+
gtp_module._inflight_comm_params.clear()
1642+
gtp_module._inflight_comm_params.add(p)
1643+
try:
1644+
# Must NOT raise KeyError(None) from cache.get(None).
1645+
gtp_module.wait_async_comms(
1646+
chain_id=p.chain_id,
1647+
skip_rs=False,
1648+
finalize_after_drain=True,
1649+
)
1650+
finally:
1651+
gtp_module._inflight_comm_params.clear()
1652+
gtp_module._inflight_comm_params.update(saved)
1653+
1654+
torch.cuda.synchronize()
1655+
assert torch.all(p.main_grad == 7.0), \
1656+
"main_grad must be untouched for a pure-AG param (no wgrad to accumulate)"
1657+
assert p._already_finalized is False, \
1658+
"_already_finalized must stay False — no finalize happened for a pure-AG param"

transformer_engine/pytorch/csrc/extensions/pybind.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,10 @@ void init_extension() {
133133

134134
#include "common/util/pybind_helper.h"
135135

136-
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
137-
NVTE_DECLARE_COMMON_PYBIND11_HANDLES(m)
138-
m.def("quantize", transformer_engine::pytorch::quantize, py::arg("tensor"), py::arg("quantizer"),
139-
py::arg("output") = py::none(), py::arg("noop") = py::none());
136+
// Bindings for the NVFP4 split-amax fast-path used by GTP (coalesced
137+
// per-expert amax allreduce + cast). Kept separate from PYBIND11_MODULE
138+
// so the latter stays under cpplint's 500-line readability/fn_size limit.
139+
static void RegisterNvfp4AmaxBindings(py::module &m) {
140140
m.def("compute_amax_nvfp4", transformer_engine::pytorch::compute_amax_nvfp4,
141141
"NVFP4: compute local amax into output's amax buffers; no cast, no allreduce",
142142
py::arg("tensor"), py::arg("quantizer"), py::arg("output") = py::none());
@@ -148,6 +148,13 @@ PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
148148
m.def("compute_multi_amax_nvfp4", transformer_engine::pytorch::compute_multi_amax_nvfp4,
149149
"NVFP4: fused multi-tensor amax compute (writes both rowwise+columnwise amax per output)",
150150
py::arg("tensor_list"), py::arg("quantizer_list"), py::arg("output_list"));
151+
}
152+
153+
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {
154+
NVTE_DECLARE_COMMON_PYBIND11_HANDLES(m)
155+
m.def("quantize", transformer_engine::pytorch::quantize, py::arg("tensor"), py::arg("quantizer"),
156+
py::arg("output") = py::none(), py::arg("noop") = py::none());
157+
RegisterNvfp4AmaxBindings(m);
151158
m.def("dequantize", &transformer_engine::pytorch::dequantize, "Dequantize", py::arg("input"),
152159
py::arg("otype"));
153160
m.def("create_empty_quantized_tensor",

transformer_engine/pytorch/module/generalized_tensor_parallelism.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1679,11 +1679,16 @@ def wait_async_comms(
16791679
param._already_ag_drained = True
16801680
if not skip_rs:
16811681
param._wait_reduce_scatter(finalize_grad=finalize_after_drain)
1682-
if finalize_after_drain and not getattr(param, "_already_finalized", False):
1683-
# Fallback path: _wait_reduce_scatter ran sync (no handle to
1684-
# drain), so it didn't accumulate. Do the inline accumulation
1685-
# here, matching the wgrad_reduce_scatter / _wait_reduce_scatter
1686-
# finalize-grad pattern (state reset + main_grad.add_ + release).
1682+
# Fallback inline-accumulation: only when finalize is requested,
1683+
# _wait_reduce_scatter didn't already finalize, and an RS actually
1684+
# ran for this param (rs_ticket set). Skips pure-AG prefetches in
1685+
# _inflight_comm_params (no wgrad to accumulate).
1686+
need_fallback_accumulation = (
1687+
finalize_after_drain
1688+
and not getattr(param, "_already_finalized", False)
1689+
and any(w._rs_ticket is not None for w in param._weights)
1690+
)
1691+
if need_fallback_accumulation:
16871692
cache = get_global_GTP_cache()
16881693
param.rs_event.wait()
16891694
for w in param._weights:

transformer_engine/pytorch/module/linear.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ class LinearFwdArgs:
154154
cpu_offloading: bool
155155
is_grad_enabled: bool
156156

157-
# --- Extended tensor parallelism ---
157+
# --- Generalized tensor parallelism ---
158158
gtp_size: int = 1
159159

160160

@@ -226,7 +226,7 @@ class LinearBwdArgs:
226226
cpu_offloading: bool = False
227227
owns_input: bool = False
228228

229-
# --- Extended tensor parallelism ---
229+
# --- Generalized tensor parallelism ---
230230
gtp_size: int = 1
231231

232232
# --- Per-backward scratch state (populated inside _linear_backward) ---

0 commit comments

Comments
 (0)