[PyTorch] Fix NCCL communicator init in cuSOLVERMp context creation#3240
[PyTorch] Fix NCCL communicator init in cuSOLVERMp context creation#3240vcherepanov-nv wants to merge 2 commits into
Conversation
Construct the cuSOLVERMp context before any other distributed collective so the distributed test exercises lazy ProcessGroupNCCL communicator initialization. Signed-off-by: Vladimir Cherepanov <vcherepanov@nvidia.com>
Materialize the ProcessGroupNCCL communicator before borrowing its raw handle, retain the process group for the context lifetime, and validate the communicator size and rank during native context creation. Signed-off-by: Vladimir Cherepanov <vcherepanov@nvidia.com>
Greptile SummaryThis PR fixes a race condition where
Confidence Score: 4/5The fix is logically correct and addresses a real crash scenario; the only open questions are around private PyTorch API stability and cleanup safety during interpreter teardown. The barrier-based materialization approach is sound, the _group retention correctly prevents the communicator from being freed while the cuSolverMp grid holds a raw pointer to it, and the C++ validation catches misconfiguration early. The reliance on _get_backend()._comm_ptr() (private PyTorch internals) is the main fragility. transformer_engine/pytorch/newton_schulz.py — specifically the _get_nccl_comm_ptr private-API usage and the del teardown path. Important Files Changed
|
| dist.barrier(group=group, device_ids=[torch.cuda.current_device()]) | ||
| nccl_backend = group._get_backend(torch.device("cuda")) | ||
| return nccl_backend._comm_ptr() | ||
| comm_ptr = nccl_backend._comm_ptr() |
There was a problem hiding this comment.
Private PyTorch API dependency
_get_backend() and _comm_ptr() are private ProcessGroupNCCL methods and can be renamed, replaced, or removed across PyTorch minor releases without a deprecation cycle. If the API changes, the failure mode is a silent AttributeError at context-creation time rather than a compilation error, which may only surface in distributed runs. It would be worth tracking the PyTorch version that introduced these methods and adding an assertion or a version guard, or at minimum filing a PyTorch issue to request a stable public surface for borrowing the raw ncclComm_t.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| def __del__(self) -> None: | ||
| # Called when the context is manually destroyed or during Python teardown | ||
| self.destroy() |
There was a problem hiding this comment.
__del__ may race with CUDA context teardown
__del__ calls destroy() which in turn calls tex.cusolvermp_ctx_destroy. During interpreter shutdown, CUDA driver state is torn down in an unspecified order relative to Python object finalization. If the CUDA context has already been destroyed when __del__ fires, cusolvermp_ctx_destroy (and the cusolverMpDestroyGrid / cusolverMpDestroy calls inside it) may trigger CUDA errors or a segfault. Guarding with try/except Exception: pass inside __del__, or checking torch.cuda.is_initialized() before calling into the native layer, would prevent noisy teardown-time crashes in programs that forget to call destroy() explicitly.
Description
Fix cuSOLVERMp context initialization when borrowing an NCCL communicator from a PyTorch process group.
Fixes # (issue)
Type of change
Changes
Please list the changes introduced in this PR:
Checklist: