28
28
29
29
from common import mpi_env_rank_and_size
30
30
import bluefog .torch as bf
31
- from bluefog .common .topology_util import ExponentialGraph , RingGraph , RingGraph
32
- from bluefog .common .topology_util import IsTopologyEquivalent
31
+ from bluefog .torch import (
32
+ ExponentialGraph ,
33
+ RingGraph ,
34
+ StarGraph ,
35
+ MeshGrid2DGraph ,
36
+ FullyConnectedGraph ,
37
+ )
38
+ from bluefog .torch import (
39
+ IsTopologyEquivalent ,
40
+ InferDestinationFromSourceRanks ,
41
+ InferSourceFromDestinationRanks ,
42
+ )
33
43
34
44
warnings .filterwarnings ("ignore" , message = "numpy.dtype size changed" )
35
45
warnings .filterwarnings ("ignore" , message = "numpy.ufunc size changed" )
@@ -75,10 +85,12 @@ def test_set_topology_fail_with_win_create(self):
75
85
76
86
if size == 1 :
77
87
expected_topology = nx .from_numpy_array (
78
- np .array ([[0.5 ]]), create_using = nx .DiGraph )
88
+ np .array ([[0.5 ]]), create_using = nx .DiGraph
89
+ )
79
90
elif size == 2 :
80
91
expected_topology = nx .from_numpy_array (
81
- np .array ([[0 , 0.2 ], [0.2 , 0 ]]), create_using = nx .DiGraph )
92
+ np .array ([[0 , 0.2 ], [0.2 , 0 ]]), create_using = nx .DiGraph
93
+ )
82
94
else :
83
95
expected_topology = RingGraph (size )
84
96
@@ -96,10 +108,16 @@ def test_set_and_load_topology(self):
96
108
bf .init ()
97
109
size = bf .size ()
98
110
if size == 4 :
99
- expected_topology = nx .DiGraph (np .array (
100
- [[1 / 3. , 1 / 3. , 1 / 3. , 0. ], [0. , 1 / 3. , 1 / 3. , 1 / 3. ],
101
- [1 / 3. , 0. , 1 / 3. , 1 / 3. ], [1 / 3. , 1 / 3. , 0. , 1 / 3. ]]
102
- ))
111
+ expected_topology = nx .DiGraph (
112
+ np .array (
113
+ [
114
+ [1 / 3.0 , 1 / 3.0 , 1 / 3.0 , 0.0 ],
115
+ [0.0 , 1 / 3.0 , 1 / 3.0 , 1 / 3.0 ],
116
+ [1 / 3.0 , 0.0 , 1 / 3.0 , 1 / 3.0 ],
117
+ [1 / 3.0 , 1 / 3.0 , 0.0 , 1 / 3.0 ],
118
+ ]
119
+ )
120
+ )
103
121
elif size == 1 :
104
122
expected_topology = nx .DiGraph (np .array ([[1.0 ]]))
105
123
else :
@@ -113,37 +131,81 @@ def test_in_out_neighbors_expo2(self):
113
131
rank = bf .rank ()
114
132
size = bf .size ()
115
133
assert bf .set_topology (ExponentialGraph (size ))
116
- in_neighobrs = bf .in_neighbor_ranks ()
134
+ in_neighbors = bf .in_neighbor_ranks ()
117
135
out_neighbors = bf .out_neighbor_ranks ()
118
136
119
137
degree = int (np .ceil (np .log2 (size )))
120
- expected_in_neighbors = sorted ([(rank - 2 ** i ) %
121
- size for i in range (degree )])
122
- expected_out_neighbors = sorted ([(rank + 2 ** i ) %
123
- size for i in range (degree )])
124
- assert sorted (in_neighobrs ) == expected_in_neighbors
138
+ expected_in_neighbors = sorted ([(rank - 2 ** i ) % size for i in range (degree )])
139
+ expected_out_neighbors = sorted ([(rank + 2 ** i ) % size for i in range (degree )])
140
+ assert sorted (in_neighbors ) == expected_in_neighbors
125
141
assert sorted (out_neighbors ) == expected_out_neighbors
126
142
127
143
def test_in_out_neighbors_biring (self ):
128
144
bf .init ()
129
145
rank = bf .rank ()
130
146
size = bf .size ()
131
147
assert bf .set_topology (RingGraph (size ))
132
- in_neighobrs = bf .in_neighbor_ranks ()
148
+ in_neighbors = bf .in_neighbor_ranks ()
133
149
out_neighbors = bf .out_neighbor_ranks ()
134
150
135
- expected_in_neighbors = list (set (
136
- map ( lambda x : x % size , [ rank - 1 , rank + 1 ])))
137
- expected_out_neighbors = list ( set (
138
- map ( lambda x : x % size , [ rank - 1 , rank + 1 ])) )
151
+ expected_in_neighbors = list (set (map ( lambda x : x % size , [ rank - 1 , rank + 1 ])))
152
+ expected_out_neighbors = list (
153
+ set (map ( lambda x : x % size , [ rank - 1 , rank + 1 ]))
154
+ )
139
155
140
156
if size <= 1 :
141
157
expected_in_neighbors = []
142
158
expected_out_neighbors = []
143
159
144
- assert sorted (in_neighobrs ) == expected_in_neighbors
160
+ assert sorted (in_neighbors ) == expected_in_neighbors
145
161
assert sorted (out_neighbors ) == expected_out_neighbors
146
162
147
163
164
+ @pytest .mark .parametrize (
165
+ "topo_func" ,
166
+ [ExponentialGraph , RingGraph , StarGraph , MeshGrid2DGraph , FullyConnectedGraph ],
167
+ )
168
+ def test_infer_destination_from_source_ranks (topo_func ):
169
+ bf .init ()
170
+ size = bf .size ()
171
+ bf .set_topology (topo_func (size ))
172
+ topo = bf .load_topology ()
173
+ in_neighbors = bf .in_neighbor_ranks ()
174
+ out_neighbors = bf .out_neighbor_ranks ()
175
+
176
+ # Make the W into average rule.
177
+ expected_W = (nx .to_numpy_array (topo ) > 0 ).astype (float )
178
+ expected_W /= expected_W .sum (axis = 0 )
179
+
180
+ src_ranks , W = InferDestinationFromSourceRanks (
181
+ src_ranks = in_neighbors , construct_adjacency_matrix = True
182
+ )
183
+ assert sorted (src_ranks ) == out_neighbors
184
+ np .testing .assert_allclose (W , expected_W )
185
+
186
+
187
+ @pytest .mark .parametrize (
188
+ "topo_func" ,
189
+ [ExponentialGraph , RingGraph , StarGraph , MeshGrid2DGraph , FullyConnectedGraph ],
190
+ )
191
+ def test_infer_source_from_destination_ranks (topo_func ):
192
+ bf .init ()
193
+ size = bf .size ()
194
+ bf .set_topology (topo_func (size ))
195
+ topo = bf .load_topology ()
196
+ in_neighbors = bf .in_neighbor_ranks ()
197
+ out_neighbors = bf .out_neighbor_ranks ()
198
+
199
+ # Make the W into average rule.
200
+ expected_W = (nx .to_numpy_array (topo ) > 0 ).astype (float )
201
+ expected_W /= expected_W .sum (axis = 0 )
202
+
203
+ dst_ranks , W = InferSourceFromDestinationRanks (
204
+ dst_ranks = out_neighbors , construct_adjacency_matrix = True
205
+ )
206
+ assert sorted (dst_ranks ) == in_neighbors
207
+ np .testing .assert_allclose (W , expected_W )
208
+
209
+
148
210
if __name__ == "__main__" :
149
211
unittest .main ()
0 commit comments