已合并
feat: add _group_start and _group_end bindings for ProcessGroupHCCL from v2.7.1 #41510
feat: add _group_start and _group_end bindings for ProcessGroupHCCL from v2.7.1 #41510
已合并
chansinging创建于 7月13日
2 个文件变更+88-0
@@ -0,0 +1,84 @@
1+import os
2+import torch
3+import torch.distributed as dist
4+from torch.testing._internal.common_utils import run_tests
5+from torch.testing._internal.distributed._tensor.common_dtensor import DTensorTestBase
6+ 
7+import torch_npu
8+from torch_npu.testing.common_distributed import with_comms
9+from torch.distributed.distributed_c10d import _get_default_group
10+ 
11+os.environ["HCCL_NPU_SOCKET_PORT_RANGE"] = "10000,60000"
12+os.environ["TIMEOUT"] = "1800"
13+os.environ["TORCH_TEST_TIMEOUT"] = "1800"
14+ 
15+class TestHcclGroupStartEnd(DTensorTestBase):
16+ 
17+ def _get_hccl_backend(self):
18+ if dist.get_backend() != "hccl":
19+ self.skipTest(f"Current backend is {dist.get_backend()}, but this test requires hccl. Skipping.")
20+ 
21+ pg = _get_default_group()
22+ return pg._get_backend(torch.device(self.device_type))
23+ 
24+ @with_comms
25+ def test_group_all_reduce_reliability(self):
26+ backend = self._get_hccl_backend()
27+ n = 4 * 1024 * 1024
28+ 
29+ x = torch.ones(n, device=self.device_type) * (self.rank + 1)
30+ y = torch.ones(n, device=self.device_type) * (self.rank + 1)
31+ w = torch.ones(n, device=self.device_type)
32+ 
33+ backend._group_start()
34+ work_x = torch.distributed.all_reduce(x, async_op=True)
35+ work_y = torch.distributed.all_reduce(y, async_op=True)
36+ backend._group_end()
37+ 
38+ work_x.wait()
39+ self.assertTrue(work_x.is_completed())
40+ self.assertTrue(work_y.is_completed())
41+ result_x = torch.matmul(x, w)
42+ 
43+ work_y.wait()
44+ result_y = torch.matmul(y, w)
45+ 
46+ expected = sum(range(1, self.world_size + 1))
47+ 
48+ self.assertEqual(x, torch.full_like(x, expected))
49+ self.assertEqual(y, torch.full_like(y, expected))
50+ self.assertEqual(result_x, expected * n)
51+ self.assertEqual(result_y, expected * n)
52+ 
53+ @with_comms
54+ def test_group_p2p_reliability(self):
55+ if self.world_size < 2:
56+ return
57+ 
58+ backend = self._get_hccl_backend()
59+ n = 1024 * 1024
60+ 
61+ x = torch.ones(n, device=self.device_type) * (self.rank + 1)
62+ y = torch.ones(n, device=self.device_type) * (self.rank + 1)
63+
64+ reqs = []
65+ 
66+ backend._group_start()
67+ if self.rank == 0:
68+ reqs.append(torch.distributed.isend(x, dst=1))
69+ reqs.append(torch.distributed.isend(y, dst=1))
70+ elif self.rank == 1:
71+ reqs.append(torch.distributed.irecv(x, src=0))
72+ reqs.append(torch.distributed.irecv(y, src=0))
73+ backend._group_end()
74+ 
75+ for req in reqs:
76+ req.wait()
77+ self.assertTrue(req.is_completed())
78+ 
79+ if self.rank == 1:
80+ self.assertEqual(x, torch.full_like(x, 1))
81+ self.assertEqual(y, torch.full_like(y, 1))
82+ 
83+if __name__ == "__main__":
84+ run_tests()
@@ -458,6 +458,10 @@ PyObject* c10d_npu_init(PyObject* _unused, PyObject* noargs)
458 .def("_add_ephemeral_timeout",458 .def("_add_ephemeral_timeout",
459 &::c10d_npu::ProcessGroupHCCL::addEphemeralTimeout,459 &::c10d_npu::ProcessGroupHCCL::addEphemeralTimeout,
460 py::arg("timeout"),460 py::arg("timeout"),
461+ py::call_guard<py::gil_scoped_release>())
462+ .def("_group_start", &::c10d_npu::ProcessGroupHCCL::groupStart,
463+ py::call_guard<py::gil_scoped_release>())
464+ .def("_group_end", &::c10d_npu::ProcessGroupHCCL::groupEnd,
461 py::call_guard<py::gil_scoped_release>());465 py::call_guard<py::gil_scoped_release>());
462 466 
463 intrusive_ptr_class_<::c10d_npu::ProcessGroupHCCL::Options>(467 intrusive_ptr_class_<::c10d_npu::ProcessGroupHCCL::Options>(