已合并
test(distributed): add test for FileStore,Store,TCPStore #31911
Nice try创建于 3月17日
test(distributed): add test for FileStore,Store,TCPStore #31911
已合并
共 5 个文件变更+201-0
| @@ -22,6 +22,7 @@ | |||
| 22 | |torch.distributed.HashStore|是|-| | 22 | |torch.distributed.HashStore|是|-| |
| 23 | |torch.distributed.FileStore|是|-| | 23 | |torch.distributed.FileStore|是|-| |
| 24 | |torch.distributed.PrefixStore|是|-| | 24 | |torch.distributed.PrefixStore|是|-| |
| 25 | +|torch.distributed.Store.\_\_init\_\_|是|-| | ||
| 25 | |torch.distributed.Store.set|是|-| | 26 | |torch.distributed.Store.set|是|-| |
| 26 | |torch.distributed.Store.get|是|-| | 27 | |torch.distributed.Store.get|是|-| |
| 27 | |torch.distributed.Store.add|是|-| | 28 | |torch.distributed.Store.add|是|-| |
| @@ -30,6 +31,21 @@ | |||
| 30 | |torch.distributed.Store.num_keys|是|-| | 31 | |torch.distributed.Store.num_keys|是|-| |
| 31 | |torch.distributed.Store.delete_key|是|-| | 32 | |torch.distributed.Store.delete_key|是|-| |
| 32 | |torch.distributed.Store.set_timeout|是|-| | 33 | |torch.distributed.Store.set_timeout|是|-| |
| 34 | +|torch.distributed.Store.append|是|-| | ||
| 35 | +|torch.distributed.Store.check|是|-| | ||
| 36 | +|torch.distributed.Store.has_extended_api|是|-| | ||
| 37 | +|torch.distributed.Store.multi_set|是|-| | ||
| 38 | +|torch.distributed.Store.multi_get|是|-| | ||
| 39 | +|torch.distributed.Store.timeout|是|-| | ||
| 40 | +|torch.distributed.TCPStore.\_\_init\_\_|是|-| | ||
| 41 | +|torch.distributed.TCPStore.host|是|-| | ||
| 42 | +|torch.distributed.TCPStore.libuvBackend|是|-| | ||
| 43 | +|torch.distributed.TCPStore.port|是|-| | ||
| 44 | +|torch.distributed.HashStore.\_\_init\_\_|是|-| | ||
| 45 | +|torch.distributed.FileStore.\_\_init\_\_|是|-| | ||
| 46 | +|torch.distributed.FileStore.path|是|-| | ||
| 47 | +|torch.distributed.PrefixStore.\_\_init\_\_|是|-| | ||
| 48 | +|torch.distributed.PrefixStore.underlying_store|是|-| | ||
| 33 | |torch.distributed.new_group|是|当pg_options函数传入类型为torch_npu._C._distributed_c10d.ProcessGroupHCCL.Options()时,配置该变量属性hccl_config可控制HCCL通信域缓存区大小。具体示例可参考《PyTorch 训练模型迁移调优指南》的“hccl_buffer_size”章节,配置变量属性hccl_config的group_name字段可以设置HCCL通信域的通信组自定义名称,取值为长度不超过32的字符串。| | 49 | |torch.distributed.new_group|是|当pg_options函数传入类型为torch_npu._C._distributed_c10d.ProcessGroupHCCL.Options()时,配置该变量属性hccl_config可控制HCCL通信域缓存区大小。具体示例可参考《PyTorch 训练模型迁移调优指南》的“hccl_buffer_size”章节,配置变量属性hccl_config的group_name字段可以设置HCCL通信域的通信组自定义名称,取值为长度不超过32的字符串。| |
| 34 | |torch.distributed.get_group_rank|是|-| | 50 | |torch.distributed.get_group_rank|是|-| |
| 35 | |torch.distributed.get_global_rank|是|-| | 51 | |torch.distributed.get_global_rank|是|-| |
| @@ -22,6 +22,7 @@ | |||
| 22 | |torch.distributed.HashStore|是|-| | 22 | |torch.distributed.HashStore|是|-| |
| 23 | |torch.distributed.FileStore|是|-| | 23 | |torch.distributed.FileStore|是|-| |
| 24 | |torch.distributed.PrefixStore|是|-| | 24 | |torch.distributed.PrefixStore|是|-| |
| 25 | +|torch.distributed.Store.\_\_init\_\_|是|-| | ||
| 25 | |torch.distributed.Store.set|是|-| | 26 | |torch.distributed.Store.set|是|-| |
| 26 | |torch.distributed.Store.get|是|-| | 27 | |torch.distributed.Store.get|是|-| |
| 27 | |torch.distributed.Store.add|是|-| | 28 | |torch.distributed.Store.add|是|-| |
| @@ -30,6 +31,21 @@ | |||
| 30 | |torch.distributed.Store.num_keys|是|-| | 31 | |torch.distributed.Store.num_keys|是|-| |
| 31 | |torch.distributed.Store.delete_key|是|-| | 32 | |torch.distributed.Store.delete_key|是|-| |
| 32 | |torch.distributed.Store.set_timeout|是|-| | 33 | |torch.distributed.Store.set_timeout|是|-| |
| 34 | +|torch.distributed.Store.append|是|-| | ||
| 35 | +|torch.distributed.Store.check|是|-| | ||
| 36 | +|torch.distributed.Store.has_extended_api|是|-| | ||
| 37 | +|torch.distributed.Store.multi_set|是|-| | ||
| 38 | +|torch.distributed.Store.multi_get|是|-| | ||
| 39 | +|torch.distributed.Store.timeout|是|-| | ||
| 40 | +|torch.distributed.TCPStore.\_\_init\_\_|是|-| | ||
| 41 | +|torch.distributed.TCPStore.host|是|-| | ||
| 42 | +|torch.distributed.TCPStore.libuvBackend|是|-| | ||
| 43 | +|torch.distributed.TCPStore.port|是|-| | ||
| 44 | +|torch.distributed.HashStore.\_\_init\_\_|是|-| | ||
| 45 | +|torch.distributed.FileStore.\_\_init\_\_|是|-| | ||
| 46 | +|torch.distributed.FileStore.path|是|-| | ||
| 47 | +|torch.distributed.PrefixStore.\_\_init\_\_|是|-| | ||
| 48 | +|torch.distributed.PrefixStore.underlying_store|是|-| | ||
| 33 | |torch.distributed.new_group|是|当pg_options函数传入类型为torch_npu._C._distributed_c10d.ProcessGroupHCCL.Options()时,配置该变量属性hccl_config可控制HCCL通信域缓存区大小。具体示例可参考《PyTorch 训练模型迁移调优指南》的“hccl_buffer_size”章节,配置变量属性hccl_config的group_name字段可以设置HCCL通信域的通信组自定义名称,取值为长度不超过32的字符串。| | 49 | |torch.distributed.new_group|是|当pg_options函数传入类型为torch_npu._C._distributed_c10d.ProcessGroupHCCL.Options()时,配置该变量属性hccl_config可控制HCCL通信域缓存区大小。具体示例可参考《PyTorch 训练模型迁移调优指南》的“hccl_buffer_size”章节,配置变量属性hccl_config的group_name字段可以设置HCCL通信域的通信组自定义名称,取值为长度不超过32的字符串。| |
| 34 | |torch.distributed.get_group_rank|是|-| | 50 | |torch.distributed.get_group_rank|是|-| |
| 35 | |torch.distributed.get_global_rank|是|-| | 51 | |torch.distributed.get_global_rank|是|-| |
| @@ -22,6 +22,7 @@ | |||
| 22 | |torch.distributed.HashStore|是|-| | 22 | |torch.distributed.HashStore|是|-| |
| 23 | |torch.distributed.FileStore|是|-| | 23 | |torch.distributed.FileStore|是|-| |
| 24 | |torch.distributed.PrefixStore|是|-| | 24 | |torch.distributed.PrefixStore|是|-| |
| 25 | +|torch.distributed.Store.\_\_init\_\_|是|-| | ||
| 25 | |torch.distributed.Store.set|是|-| | 26 | |torch.distributed.Store.set|是|-| |
| 26 | |torch.distributed.Store.get|是|-| | 27 | |torch.distributed.Store.get|是|-| |
| 27 | |torch.distributed.Store.add|是|-| | 28 | |torch.distributed.Store.add|是|-| |
| @@ -30,6 +31,21 @@ | |||
| 30 | |torch.distributed.Store.num_keys|是|-| | 31 | |torch.distributed.Store.num_keys|是|-| |
| 31 | |torch.distributed.Store.delete_key|是|-| | 32 | |torch.distributed.Store.delete_key|是|-| |
| 32 | |torch.distributed.Store.set_timeout|是|-| | 33 | |torch.distributed.Store.set_timeout|是|-| |
| 34 | +|torch.distributed.Store.append|是|-| | ||
| 35 | +|torch.distributed.Store.check|是|-| | ||
| 36 | +|torch.distributed.Store.has_extended_api|是|-| | ||
| 37 | +|torch.distributed.Store.multi_set|是|-| | ||
| 38 | +|torch.distributed.Store.multi_get|是|-| | ||
| 39 | +|torch.distributed.Store.timeout|是|-| | ||
| 40 | +|torch.distributed.TCPStore.\_\_init\_\_|是|-| | ||
| 41 | +|torch.distributed.TCPStore.host|是|-| | ||
| 42 | +|torch.distributed.TCPStore.libuvBackend|是|-| | ||
| 43 | +|torch.distributed.TCPStore.port|是|-| | ||
| 44 | +|torch.distributed.HashStore.\_\_init\_\_|是|-| | ||
| 45 | +|torch.distributed.FileStore.\_\_init\_\_|是|-| | ||
| 46 | +|torch.distributed.FileStore.path|是|-| | ||
| 47 | +|torch.distributed.PrefixStore.\_\_init\_\_|是|-| | ||
| 48 | +|torch.distributed.PrefixStore.underlying_store|是|-| | ||
| 33 | |torch.distributed.new_group|是|当pg_options函数传入类型为torch_npu._C._distributed_c10d.ProcessGroupHCCL.Options()时,配置该变量属性hccl_config可控制HCCL通信域缓存区大小。具体示例可参考《PyTorch 训练模型迁移调优指南》的“hccl_buffer_size”章节,配置变量属性hccl_config的group_name字段可以设置HCCL通信域的通信组自定义名称,取值为长度不超过32的字符串。| | 49 | |torch.distributed.new_group|是|当pg_options函数传入类型为torch_npu._C._distributed_c10d.ProcessGroupHCCL.Options()时,配置该变量属性hccl_config可控制HCCL通信域缓存区大小。具体示例可参考《PyTorch 训练模型迁移调优指南》的“hccl_buffer_size”章节,配置变量属性hccl_config的group_name字段可以设置HCCL通信域的通信组自定义名称,取值为长度不超过32的字符串。| |
| 34 | |torch.distributed.get_group_rank|是|-| | 50 | |torch.distributed.get_group_rank|是|-| |
| 35 | |torch.distributed.get_global_rank|是|-| | 51 | |torch.distributed.get_global_rank|是|-| |
| @@ -22,6 +22,7 @@ | |||
| 22 | |torch.distributed.HashStore|是|-| | 22 | |torch.distributed.HashStore|是|-| |
| 23 | |torch.distributed.FileStore|是|-| | 23 | |torch.distributed.FileStore|是|-| |
| 24 | |torch.distributed.PrefixStore|是|-| | 24 | |torch.distributed.PrefixStore|是|-| |
| 25 | +|torch.distributed.Store.\_\_init\_\_|是|-| | ||
| 25 | |torch.distributed.Store.set|是|-| | 26 | |torch.distributed.Store.set|是|-| |
| 26 | |torch.distributed.Store.get|是|-| | 27 | |torch.distributed.Store.get|是|-| |
| 27 | |torch.distributed.Store.add|是|-| | 28 | |torch.distributed.Store.add|是|-| |
| @@ -30,6 +31,21 @@ | |||
| 30 | |torch.distributed.Store.num_keys|是|-| | 31 | |torch.distributed.Store.num_keys|是|-| |
| 31 | |torch.distributed.Store.delete_key|是|-| | 32 | |torch.distributed.Store.delete_key|是|-| |
| 32 | |torch.distributed.Store.set_timeout|是|-| | 33 | |torch.distributed.Store.set_timeout|是|-| |
| 34 | +|torch.distributed.Store.append|是|-| | ||
| 35 | +|torch.distributed.Store.check|是|-| | ||
| 36 | +|torch.distributed.Store.has_extended_api|是|-| | ||
| 37 | +|torch.distributed.Store.multi_set|是|-| | ||
| 38 | +|torch.distributed.Store.multi_get|是|-| | ||
| 39 | +|torch.distributed.Store.timeout|是|-| | ||
| 40 | +|torch.distributed.TCPStore.\_\_init\_\_|是|-| | ||
| 41 | +|torch.distributed.TCPStore.host|是|-| | ||
| 42 | +|torch.distributed.TCPStore.libuvBackend|是|-| | ||
| 43 | +|torch.distributed.TCPStore.port|是|-| | ||
| 44 | +|torch.distributed.HashStore.\_\_init\_\_|是|-| | ||
| 45 | +|torch.distributed.FileStore.\_\_init\_\_|是|-| | ||
| 46 | +|torch.distributed.FileStore.path|是|-| | ||
| 47 | +|torch.distributed.PrefixStore.\_\_init\_\_|是|-| | ||
| 48 | +|torch.distributed.PrefixStore.underlying_store|是|-| | ||
| 33 | |torch.distributed.new_group|是|当pg_options函数传入类型为torch_npu._C._distributed_c10d.ProcessGroupHCCL.Options()时,配置该变量属性hccl_config可控制HCCL通信域缓存区大小。具体示例可参考《PyTorch 训练模型迁移调优指南》的“hccl_buffer_size”章节,配置变量属性hccl_config的group_name字段可以设置HCCL通信域的通信组自定义名称,取值为长度不超过32的字符串。| | 49 | |torch.distributed.new_group|是|当pg_options函数传入类型为torch_npu._C._distributed_c10d.ProcessGroupHCCL.Options()时,配置该变量属性hccl_config可控制HCCL通信域缓存区大小。具体示例可参考《PyTorch 训练模型迁移调优指南》的“hccl_buffer_size”章节,配置变量属性hccl_config的group_name字段可以设置HCCL通信域的通信组自定义名称,取值为长度不超过32的字符串。| |
| 34 | |torch.distributed.get_group_rank|是|-| | 50 | |torch.distributed.get_group_rank|是|-| |
| 35 | |torch.distributed.get_global_rank|是|-| | 51 | |torch.distributed.get_global_rank|是|-| |
| @@ -0,0 +1,137 @@ | |||
| 1 | +""" | ||
| 2 | +Add validation cases for torch.distributed APIs on NPU: | ||
| 3 | +1. test/distributed/test_store.py from PyTorch community lacks sufficient API validations, so this file is added. | ||
| 4 | +2. This file validates | ||
| 5 | +torch.distributed.FileStore.path | ||
| 6 | +torch.distributed.Store.__init__ | ||
| 7 | +torch.distributed.Store.add | ||
| 8 | +torch.distributed.Store.timeout | ||
| 9 | +torch.distributed.TCPStore.host | ||
| 10 | +torch.distributed.TCPStore.port | ||
| 11 | +(extendable). | ||
| 12 | +""" | ||
| 13 | + | ||
| 14 | +import os | ||
| 15 | +import time | ||
| 16 | +import socket | ||
| 17 | +import tempfile | ||
| 18 | +from datetime import timedelta | ||
| 19 | + | ||
| 20 | +import torch | ||
| 21 | +import torch.distributed as dist | ||
| 22 | +from torch.testing._internal.common_utils import TestCase, run_tests | ||
| 23 | + | ||
| 24 | +import torch_npu | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +def find_free_port() -> int: | ||
| 28 | + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: | ||
| 29 | + s.bind(('', 0)) | ||
| 30 | + return s.getsockname()[1] | ||
| 31 | + | ||
| 32 | + | ||
| 33 | +class TestStoreAPIs(TestCase): | ||
| 34 | + """Test cases for specific behavioral validations of Store APIs.""" | ||
| 35 | + | ||
| 36 | + def test_filestore_path_behavior(self): | ||
| 37 | + """Test if FileStore actually uses the specified path for data exchange.""" | ||
| 38 | + with tempfile.TemporaryDirectory() as temp_dir: | ||
| 39 | + filename = os.path.join(temp_dir, "npu_filestore.txt") | ||
| 40 | + | ||
| 41 | + store_master = dist.FileStore(filename, 2) | ||
| 42 | + self.assertEqual(store_master.path, filename) | ||
| 43 | + store_master.set("shared_key", "npu_data") | ||
| 44 | + | ||
| 45 | + store_worker = dist.FileStore(filename, 2) | ||
| 46 | + val = store_worker.get("shared_key") | ||
| 47 | + | ||
| 48 | + self.assertEqual(val, b"npu_data") | ||
| 49 | + | ||
| 50 | + def test_store_init(self): | ||
| 51 | + """Test the initialization (super().__init__) of the base Store class.""" | ||
| 52 | + class MyCustomStore(dist.Store): | ||
| 53 | + def __init__(self): | ||
| 54 | + super().__init__() | ||
| 55 | + self.is_initialized = True | ||
| 56 | + | ||
| 57 | + custom_store = MyCustomStore() | ||
| 58 | + self.assertTrue(custom_store.is_initialized) | ||
| 59 | + self.assertIsInstance(custom_store, dist.Store) | ||
| 60 | + | ||
| 61 | + def test_store_add_behavior(self): | ||
| 62 | + """Test the add operation mathematically on a HashStore.""" | ||
| 63 | + store = dist.HashStore() | ||
| 64 | + key = "test_add_key" | ||
| 65 | + | ||
| 66 | + res1 = store.add(key, 5) | ||
| 67 | + self.assertEqual(res1, 5) | ||
| 68 | + | ||
| 69 | + res2 = store.add(key, 10) | ||
| 70 | + self.assertEqual(res2, 15) | ||
| 71 | + | ||
| 72 | + self.assertEqual(store.get(key), b"15") | ||
| 73 | + | ||
| 74 | + res3 = store.add(key, -3) | ||
| 75 | + self.assertEqual(res3, 12) | ||
| 76 | + | ||
| 77 | + def test_store_timeout_behavior(self): | ||
| 78 | + """Test if the timeout property actively interrupts blocking operations.""" | ||
| 79 | + store = dist.HashStore() | ||
| 80 | + | ||
| 81 | + timeout_seconds = 1 | ||
| 82 | + test_timeout = timedelta(seconds=timeout_seconds) | ||
| 83 | + store.set_timeout(test_timeout) | ||
| 84 | + self.assertEqual(store.timeout, test_timeout) | ||
| 85 | + | ||
| 86 | + start_time = time.time() | ||
| 87 | + with self.assertRaises(RuntimeError) as context: | ||
| 88 | + store.wait(["non_existent_key"], test_timeout) | ||
| 89 | + elapsed_time = time.time() - start_time | ||
| 90 | + | ||
| 91 | + self.assertTrue( | ||
| 92 | + "Timeout" in str(context.exception) or "Wait timeout" in str(context.exception), | ||
| 93 | + f"Exception message does not indicate timeout: {context.exception}" | ||
| 94 | + ) | ||
| 95 | + | ||
| 96 | + self.assertTrue( | ||
| 97 | + 0.8 <= elapsed_time <= 2.5, | ||
| 98 | + f"Actual wait time {elapsed_time:.2f}s did not respect the {timeout_seconds}s timeout." | ||
| 99 | + ) | ||
| 100 | + | ||
| 101 | + def test_tcpstore_host_and_port_behavior(self): | ||
| 102 | + """Test TCPStore host and port by establishing an actual Client-Server connection.""" | ||
| 103 | + host = "127.0.0.1" | ||
| 104 | + port = find_free_port() | ||
| 105 | + | ||
| 106 | + server_store = dist.TCPStore( | ||
| 107 | + host_name=host, | ||
| 108 | + port=port, | ||
| 109 | + world_size=2, | ||
| 110 | + is_master=True, | ||
| 111 | + timeout=timedelta(seconds=5), | ||
| 112 | + wait_for_workers=False | ||
| 113 | + ) | ||
| 114 | + | ||
| 115 | + self.assertEqual(server_store.host, host) | ||
| 116 | + self.assertEqual(server_store.port, port) | ||
| 117 | + | ||
| 118 | + server_store.set("tcp_key", "tcp_value") | ||
| 119 | + | ||
| 120 | + client_store = dist.TCPStore( | ||
| 121 | + host_name=host, | ||
| 122 | + port=port, | ||
| 123 | + world_size=2, | ||
| 124 | + is_master=False, | ||
| 125 | + timeout=timedelta(seconds=5) | ||
| 126 | + ) | ||
| 127 | + | ||
| 128 | + client_store.wait(["tcp_key"], timedelta(seconds=5)) | ||
| 129 | + val = client_store.get("tcp_key") | ||
| 130 | + self.assertEqual(val, b"tcp_value") | ||
| 131 | + | ||
| 132 | + del client_store | ||
| 133 | + del server_store | ||
| 134 | + | ||
| 135 | + | ||
| 136 | +if __name__ == "__main__": | ||
| 137 | + run_tests() | ||