1 /*
2 * Copyright © 2010-2020 Inria. All rights reserved.
3 * Copyright © 2011 Cisco Systems, Inc. All rights reserved.
4 * See COPYING in top-level directory.
5 */
6
7 #include "hwloc.h"
8
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdint.h>
13 #include <assert.h>
14
15 /* test setting/retrieving distances */
16
print_distances(const struct hwloc_distances_s * distances)17 static void print_distances(const struct hwloc_distances_s *distances)
18 {
19 unsigned nbobjs = distances->nbobjs;
20 unsigned i, j;
21
22 printf(" ");
23 /* column header */
24 for(j=0; j<nbobjs; j++)
25 printf(" % 5d", (int) distances->objs[j]->os_index);
26 printf("\n");
27
28 /* each line */
29 for(i=0; i<nbobjs; i++) {
30 /* row header */
31 printf("% 5d", (int) distances->objs[i]->os_index);
32 /* each value */
33 for(j=0; j<nbobjs; j++)
34 printf(" % 5d", (int) distances->values[i*nbobjs+j]);
35 printf("\n");
36 }
37 }
38
check_distances(hwloc_topology_t topology,int depth,unsigned expected)39 static void check_distances(hwloc_topology_t topology, int depth, unsigned expected)
40 {
41 struct hwloc_distances_s *distances[2];
42 unsigned nr = 0;
43 int err = hwloc_distances_get_by_depth(topology, depth, &nr, distances, 0, 0);
44 assert(!err);
45 assert(nr == expected);
46 if (!nr) {
47 printf("No distance at depth %d\n", depth);
48 return;
49 }
50 nr = 2;
51 err = hwloc_distances_get_by_depth(topology, depth, &nr, distances, 0, 0);
52 assert(!err);
53 printf("distance matrix for depth %d:\n", depth);
54 print_distances(distances[0]);
55 assert(!hwloc_distances_get_name(topology, distances[0]));
56 hwloc_distances_release(topology, distances[0]);
57 if (nr > 1) {
58 print_distances(distances[1]);
59 assert(!hwloc_distances_get_name(topology, distances[1]));
60 hwloc_distances_release(topology, distances[1]);
61 }
62 }
63
main(void)64 int main(void)
65 {
66 hwloc_topology_t topology;
67 struct hwloc_distances_s *distances[2];
68 hwloc_obj_t objs[16];
69 hwloc_uint64_t values[16*16], value1, value2;
70 int topodepth;
71 unsigned i, j, k, nr;
72 int err;
73
74 hwloc_topology_init(&topology);
75 hwloc_topology_set_synthetic(topology, "node:4 core:4 pu:1");
76 hwloc_topology_load(topology);
77
78 nr = 0;
79 err = hwloc_distances_get(topology, &nr, distances, 0, 0);
80 assert(!err);
81 assert(!nr);
82 if (!nr)
83 printf("No distance\n");
84
85 printf("\nInserting NUMA distances\n");
86 for(i=0; i<4; i++)
87 objs[i] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, i);
88 /* matrix 2*2 */
89 for(i=0; i<16; i++)
90 values[i] = 8;
91 values[0+4*1] = 4;
92 values[1+4*0] = 4;
93 values[2+4*3] = 4;
94 values[3+4*2] = 4;
95 for(i=0; i<4; i++)
96 values[i+4*i] = 1;
97 err = hwloc_distances_add(topology, 4, objs, values,
98 HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER,
99 HWLOC_DISTANCES_ADD_FLAG_GROUP);
100 assert(!err);
101
102 err = hwloc_topology_refresh(topology);
103 assert(!err);
104
105 topodepth = hwloc_topology_get_depth(topology);
106 assert(topodepth == 5);
107 check_distances(topology, 0, 0);
108 check_distances(topology, 1, 0);
109 check_distances(topology, 2, 0);
110 check_distances(topology, 3, 0);
111 check_distances(topology, 4, 0);
112 check_distances(topology, HWLOC_TYPE_DEPTH_NUMANODE, 1);
113
114 /* check numa distances */
115 printf("Checking NUMA distances\n");
116 nr = 1;
117 err = hwloc_distances_get_by_type(topology, HWLOC_OBJ_NUMANODE, &nr, distances, 0, 0);
118 assert(!err);
119 assert(nr == 1);
120 assert(distances[0]);
121 assert(distances[0]->objs);
122 assert(distances[0]->values);
123 assert(distances[0]->kind == (HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER));
124 /* check helpers */
125 assert(hwloc_distances_obj_index(distances[0], hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2)) == 2);
126 err = hwloc_distances_obj_pair_values(distances[0],
127 hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 1),
128 hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 2),
129 &value1, &value2);
130 assert(!err);
131 assert(value1 == values[1*4+2]);
132 assert(value2 == values[2*4+1]);
133 /* check helpers on errors */
134 assert(hwloc_distances_obj_index(distances[0], hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 0)) == -1);
135 err = hwloc_distances_obj_pair_values(distances[0],
136 hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 1),
137 hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 2),
138 &value1, &value2);
139 assert(err == -1);
140 /* check that some random values are ok */
141 assert(distances[0]->values[0] == 1); /* diagonal */
142 assert(distances[0]->values[4] == 4); /* same group */
143 assert(distances[0]->values[6] == 8); /* different group */
144 assert(distances[0]->values[9] == 8); /* different group */
145 assert(distances[0]->values[10] == 1); /* diagonal */
146 assert(distances[0]->values[14] == 4); /* same group */
147 hwloc_distances_release(topology, distances[0]);
148
149 printf("\nInserting PU distances\n");
150 /* matrix 4*2*2 */
151 for(i=0; i<16; i++)
152 objs[i] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, i);
153 for(i=0; i<256; i++)
154 values[i] = 8;
155 for(i=0; i<4; i++) {
156 for(j=0; j<4; j++)
157 for(k=0; k<4; k++)
158 values[i*64+i*4+16*j+k] = 4;
159 values[i*64+i*4+1] = 2;
160 values[i*64+i*4+16] = 2;
161 values[i*64+i*4+2*16+3] = 2;
162 values[i*64+i*4+3*16+2] = 2;
163 }
164 for(i=0; i<16; i++)
165 values[i+16*i] = 1;
166 err = hwloc_distances_add(topology, 16, objs, values,
167 HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER,
168 HWLOC_DISTANCES_ADD_FLAG_GROUP);
169 assert(!err);
170
171 topodepth = hwloc_topology_get_depth(topology);
172 assert(topodepth == 6);
173 check_distances(topology, 0, 0);
174 check_distances(topology, 1, 0);
175 check_distances(topology, 2, 0);
176 check_distances(topology, 3, 0);
177 check_distances(topology, 4, 0);
178 check_distances(topology, 5, 1);
179 check_distances(topology, HWLOC_TYPE_DEPTH_NUMANODE, 1);
180
181 /* check PU distances */
182 printf("Checking PU distances\n");
183 nr = 1;
184 err = hwloc_distances_get_by_type(topology, HWLOC_OBJ_PU, &nr, distances, 0, 0);
185 assert(!err);
186 assert(nr == 1);
187 assert(distances[0]);
188 assert(distances[0]->values);
189 assert(distances[0]->kind == (HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER));
190 /* check that some random values are ok */
191 assert(distances[0]->values[0] == 1); /* diagonal */
192 assert(distances[0]->values[1] == 2); /* same group */
193 assert(distances[0]->values[3] == 4); /* same biggroup */
194 assert(distances[0]->values[15] == 8); /* different biggroup */
195 assert(distances[0]->values[250] == 8); /* different biggroup */
196 assert(distances[0]->values[253] == 4); /* same group */
197 assert(distances[0]->values[254] == 2); /* same biggroup */
198 assert(distances[0]->values[255] == 1); /* diagonal */
199 hwloc_distances_release(topology, distances[0]);
200
201 printf("\nInserting 2nd PU distances\n");
202 /* matrix 4*1 */
203 for(i=0; i<4; i++)
204 objs[i] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, i);
205 for(i=0; i<16; i++)
206 values[i] = 3;
207 for(i=0; i<4; i++)
208 values[i+4*i] = 7;
209 err = hwloc_distances_add(topology, 4, objs, values,
210 HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH|HWLOC_DISTANCES_KIND_FROM_USER,
211 HWLOC_DISTANCES_ADD_FLAG_GROUP);
212 assert(!err);
213
214 topodepth = hwloc_topology_get_depth(topology);
215 assert(topodepth == 6);
216 check_distances(topology, 0, 0);
217 check_distances(topology, 1, 0);
218 check_distances(topology, 2, 0);
219 check_distances(topology, 3, 0);
220 check_distances(topology, 4, 0);
221 check_distances(topology, 5, 2);
222 check_distances(topology, HWLOC_TYPE_DEPTH_NUMANODE, 1);
223
224 /* check PU distances */
225 printf("Checking 2nd PU distances\n");
226 nr = 2;
227 err = hwloc_distances_get_by_type(topology, HWLOC_OBJ_PU, &nr, distances, 0, 0);
228 assert(!err);
229 assert(nr == 2);
230 assert(distances[1]);
231 assert(distances[1]->values);
232 assert(distances[1]->kind == (HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH|HWLOC_DISTANCES_KIND_FROM_USER));
233 /* check that some random values are ok */
234 assert(distances[1]->values[0] == 7); /* diagonal */
235 assert(distances[1]->values[1] == 3); /* other */
236 assert(distances[1]->values[3] == 3); /* other */
237 assert(distances[1]->values[15] == 7); /* diagonal */
238 hwloc_distances_release(topology, distances[0]);
239 hwloc_distances_release(topology, distances[1]);
240
241 /* inserting heterogeneous distance */
242 printf("\nInserting heterogeneous distances\n");
243 objs[0] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_NUMANODE, 0);
244 objs[1] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_CORE, 1);
245 objs[2] = hwloc_get_obj_by_depth(topology, 1, 0);
246 for(i=0; i<3; i++) {
247 for(j=0; j<3; j++)
248 values[i*3+j] = 10;
249 values[i*3+i] = 5;
250 }
251 err = hwloc_distances_add(topology, 3, objs, values,
252 HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH|HWLOC_DISTANCES_KIND_FROM_USER,
253 0);
254 assert(!err);
255
256 /* check distances by kind */
257 nr = 2;
258 err = hwloc_distances_get(topology, &nr, distances, HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH, 0);
259 assert(!err);
260 assert(nr == 2);
261 hwloc_distances_release(topology, distances[0]);
262 assert(distances[1]->objs[0]->type == HWLOC_OBJ_NUMANODE);
263 assert(distances[1]->objs[0]->logical_index == 0);
264 assert(distances[1]->objs[1]->type == HWLOC_OBJ_CORE);
265 assert(distances[1]->objs[1]->logical_index == 1);
266 assert(distances[1]->objs[2]->type == HWLOC_OBJ_GROUP);
267 assert(distances[1]->objs[2]->logical_index == 0);
268 assert(distances[1]->kind == (HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH|HWLOC_DISTANCES_KIND_FROM_USER|HWLOC_DISTANCES_KIND_HETEROGENEOUS_TYPES));
269 hwloc_distances_release(topology, distances[1]);
270 nr = 2;
271 err = hwloc_distances_get(topology, &nr, distances, HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_OS, 0);
272 assert(!err);
273 assert(nr == 0);
274 nr = 2;
275 err = hwloc_distances_get(topology, &nr, distances, HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER, 0);
276 assert(!err);
277 assert(nr == 2);
278 hwloc_distances_release(topology, distances[0]);
279 hwloc_distances_release(topology, distances[1]);
280
281 /* check distances by name */
282 nr = 0;
283 err = hwloc_distances_get_by_name(topology, NULL, &nr, distances, 0);
284 assert(!err);
285 assert(nr == 4);
286 nr = 0;
287 err = hwloc_distances_get_by_name(topology, "nomatch", &nr, distances, 0);
288 assert(!err);
289 assert(nr == 0);
290
291 /* removing one PU distance */
292 printf("Removing the 2nd PU distances\n");
293 nr = 2;
294 err = hwloc_distances_get_by_type(topology, HWLOC_OBJ_PU, &nr, distances, 0, 0);
295 assert(!err);
296 assert(nr == 2);
297 hwloc_distances_release(topology, distances[0]);
298 hwloc_distances_release_remove(topology, distances[1]);
299 nr = 0;
300 err = hwloc_distances_get_by_type(topology, HWLOC_OBJ_PU, &nr, distances, 0, 0);
301 assert(!err);
302 assert(nr == 1);
303
304 /* remove distances */
305 printf("Removing distances\n");
306 /* remove both PU distances */
307 err = hwloc_distances_remove_by_type(topology, HWLOC_OBJ_PU);
308 assert(!err);
309 nr = 0;
310 err = hwloc_distances_get_by_type(topology, HWLOC_OBJ_PU, &nr, distances, 0, 0);
311 assert(!err);
312 assert(!nr);
313 nr = 0;
314 err = hwloc_distances_get_by_type(topology, HWLOC_OBJ_NUMANODE, &nr, distances, 0, 0);
315 assert(!err);
316 assert(nr == 1);
317 /* remove all distances */
318 err = hwloc_distances_remove(topology);
319 assert(!err);
320 nr = 0;
321 err = hwloc_distances_get(topology, &nr, distances, 0, 0);
322 assert(!err);
323 assert(!nr);
324 nr = 0;
325 err = hwloc_distances_get_by_type(topology, HWLOC_OBJ_PU, &nr, distances, 0, 0);
326 assert(!err);
327 assert(!nr);
328 nr = 0;
329 err = hwloc_distances_get_by_type(topology, HWLOC_OBJ_NUMANODE, &nr, distances, 0, 0);
330 assert(!err);
331 assert(!nr);
332
333 hwloc_topology_destroy(topology);
334
335 return 0;
336 }
337