Skip to content

Commit 1f25d6a

Browse files
nWEIdiaclaudeptrendx
authored
[NCCL][PyTorch] Fix test-fusible-ops-file-rendezvous-bug (#3478)
* world_group() used a single hardcoded init_method="file:///tmp/rdzv", shared across every world_size this test parametrizes over ([device_count(), 1, 2]), and neither world_group() nor test_distributed_fuser_ops ever calls destroy_process_group() or removes the file afterwards. A world_size=N run's leftover FileStore content can then corrupt a differently-shaped world_size=M run that reuses the same path in the same pytest session, surfacing as a confusing NCCL bootstrap failure: torch.distributed.DistBackendError: NCCL error ... ncclOsSocketPollConnect: connect to <self> ... Connection refused, exceeded error retry count after 35 attempts instead of a clear rendezvous error. Confirmed 100% deterministic: running the full file fresh (no pre-existing /tmp/rdzv) still fails test_distributed_fuser_ops[2] every time, because the [4] parametrization (which runs first) leaves /tmp/rdzv behind for [2] to trip over. This was previously masked by older bundled NCCL (2.30.7), which apparently tolerated the stale/mismatched FileStore well enough to still succeed; a newer NCCL (2.31.2) surfaces it as a hard failure. See the investigation writeup for the full comparison: Fix: key the rendezvous path by world_size (file:///tmp/rdzv_test_fusible_ops_{world_size}), and defensively remove any pre-existing file at that path in test_distributed_fuser_ops before launching each subprocess job, to also cover a leftover file from an earlier crashed run of the same world_size. Verified on a GB200 node NCCL 2.31.2, the container that previously failed 2 of 3 parametrizations): all 3 world_size parametrizations now pass, including two runs of the full file back to back with no manual cleanup in between. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Wei Wang <weiwan@nvidia.com> * Use unique rendezvous files in fusible ops tests Signed-off-by: Przemek Tredak <ptredak@nvidia.com> --------- Signed-off-by: Wei Wang <weiwan@nvidia.com> Signed-off-by: Przemek Tredak <ptredak@nvidia.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: Przemek Tredak <ptredak@nvidia.com>
1 parent e61b66d commit 1f25d6a

2 files changed

Lines changed: 13 additions & 7 deletions

File tree

‎tests/pytorch/distributed/test_fusible_ops.py‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import pathlib
1313
import subprocess
1414
import sys
15+
import tempfile
1516
from typing import Optional
1617

1718
import pytest
@@ -58,7 +59,8 @@ def world_group() -> torch.distributed.ProcessGroup:
5859
torch.cuda.set_device(rank)
5960
group = torch.distributed.init_process_group(
6061
"nccl",
61-
init_method="file:///tmp/rdzv",
62+
# Each parallel job must use a fresh FileStore shared by only its ranks.
63+
init_method=f"file://{os.environ['NVTE_TEST_RDZV_PATH']}",
6264
world_size=world_size,
6365
rank=rank,
6466
)
@@ -1053,10 +1055,10 @@ def test_distributed_fuser_ops(world_size: int) -> None:
10531055
current_file,
10541056
"--parallel",
10551057
]
1056-
result = subprocess.run(
1057-
command,
1058-
check=True,
1059-
)
1058+
with tempfile.TemporaryDirectory(prefix="te-test-fusible-ops-") as temp_dir:
1059+
env = dict(os.environ)
1060+
env["NVTE_TEST_RDZV_PATH"] = str(pathlib.Path(temp_dir) / "rdzv")
1061+
subprocess.run(command, check=True, env=env)
10601062

10611063

10621064
def main() -> None:

‎tests/pytorch/distributed/test_fusible_ops_with_userbuffers.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import pathlib
1313
import subprocess
1414
import sys
15+
import tempfile
1516

1617
import pytest
1718
import torch
@@ -107,7 +108,8 @@ def world_group() -> torch.distributed.ProcessGroup:
107108
torch.cuda.set_device(local_rank)
108109
group = torch.distributed.init_process_group(
109110
"nccl",
110-
init_method="file:///tmp/rdzv",
111+
# Each parallel job must use a fresh FileStore shared by only its ranks.
112+
init_method=f"file://{os.environ['NVTE_TEST_RDZV_PATH']}",
111113
world_size=world_size,
112114
rank=rank,
113115
device_id=torch.device(f"cuda:{local_rank}"),
@@ -471,7 +473,9 @@ def test_fuser_ops_with_userbuffers(
471473
env["NVTE_ALLOW_NONDETERMINISTIC_ALGO"] = "0"
472474

473475
# Launch parallel job
474-
run_distributed(command, env=env)
476+
with tempfile.TemporaryDirectory(prefix="te-test-fusible-ops-userbuffers-") as temp_dir:
477+
env["NVTE_TEST_RDZV_PATH"] = str(pathlib.Path(temp_dir) / "rdzv")
478+
run_distributed(command, env=env)
475479

476480

477481
def main() -> None:

0 commit comments

Comments
 (0)