1 /*
2 * Copyright © 2011-2021 Inria. All rights reserved.
3 * See COPYING in top-level directory.
4 */
5
6 #include "hwloc.h"
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdint.h>
12 #include <assert.h>
13
main(void)14 int main(void)
15 {
16 hwloc_topology_t topology;
17 hwloc_obj_t obj, group, saved, res, root;
18 hwloc_obj_t objs[32];
19 hwloc_uint64_t values[32*32];
20 int depth;
21 hwloc_obj_type_t type;
22 unsigned width;
23 unsigned i, j;
24 int err;
25
26 /* testing of adding specific groups */
27
28 hwloc_topology_init(&topology);
29 hwloc_topology_set_synthetic(topology, "pack:4 [numa] pu:4");
30 hwloc_topology_load(topology);
31 root = hwloc_get_root_obj(topology);
32 assert(hwloc_topology_get_depth(topology) == 3);
33 /* insert a group identical to root, will be merged */
34 group = hwloc_topology_alloc_group_object(topology);
35 assert(group);
36 group->cpuset = hwloc_bitmap_dup(root->cpuset);
37 res = hwloc_topology_insert_group_object(topology, group);
38 assert(res);
39 assert(res == root);
40 assert(hwloc_topology_get_depth(topology) == 3);
41 /* insert a group identical to a package, will be merged */
42 group = hwloc_topology_alloc_group_object(topology);
43 assert(group);
44 obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PACKAGE, 1);
45 assert(obj);
46 group->cpuset = hwloc_bitmap_dup(obj->cpuset);
47 res = hwloc_topology_insert_group_object(topology, group);
48 assert(res);
49 assert(res == obj);
50 assert(hwloc_topology_get_depth(topology) == 3);
51 /* insert a invalid group of two PUs in different packages, will fail */
52 group = hwloc_topology_alloc_group_object(topology);
53 assert(group);
54 obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 1);
55 assert(obj);
56 group->cpuset = hwloc_bitmap_dup(obj->cpuset);
57 obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, 12);
58 assert(obj);
59 hwloc_bitmap_or(group->cpuset, group->cpuset, obj->cpuset);
60 res = hwloc_topology_insert_group_object(topology, group);
61 assert(!res);
62 assert(hwloc_topology_get_depth(topology) == 3);
63 /* insert a group of two packages with high kind (so that it gets merged later) */
64 group = hwloc_topology_alloc_group_object(topology);
65 assert(group);
66 obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PACKAGE, 1);
67 assert(obj);
68 group->cpuset = hwloc_bitmap_dup(obj->cpuset);
69 obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PACKAGE, 2);
70 assert(obj);
71 hwloc_bitmap_or(group->cpuset, group->cpuset, obj->cpuset);
72 group->attr->group.kind = (unsigned)-1;
73 res = hwloc_topology_insert_group_object(topology, group);
74 assert(res == group);
75 saved = group;
76 assert(hwloc_topology_get_depth(topology) == 4);
77 /* insert same group with lower kind to replace the previous one */
78 group = hwloc_topology_alloc_group_object(topology);
79 assert(group);
80 obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PACKAGE, 1);
81 assert(obj);
82 group->cpuset = hwloc_bitmap_dup(obj->cpuset);
83 obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PACKAGE, 2);
84 assert(obj);
85 hwloc_bitmap_or(group->cpuset, group->cpuset, obj->cpuset);
86 group->attr->group.kind = 0;
87 res = hwloc_topology_insert_group_object(topology, group);
88 assert(res == saved); /* the core should move the contents of this new group into a previous one */
89 assert(res != group);
90 assert(hwloc_topology_get_depth(topology) == 4);
91 /* insert yet another same group with higher kind, it will be dropped in favor of the previous-previous one */
92 group = hwloc_topology_alloc_group_object(topology);
93 assert(group);
94 obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PACKAGE, 1);
95 assert(obj);
96 group->cpuset = hwloc_bitmap_dup(obj->cpuset);
97 obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PACKAGE, 2);
98 assert(obj);
99 hwloc_bitmap_or(group->cpuset, group->cpuset, obj->cpuset);
100 group->attr->group.kind = (unsigned)-1;
101 res = hwloc_topology_insert_group_object(topology, group);
102 assert(res == saved);
103 assert(res != group);
104 assert(hwloc_topology_get_depth(topology) == 4);
105 /* insert a conflict group of two packages by nodeset, will fail */
106 group = hwloc_topology_alloc_group_object(topology);
107 assert(group);
108 obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PACKAGE, 0);
109 assert(obj);
110 group->nodeset = hwloc_bitmap_dup(obj->nodeset);
111 obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PACKAGE, 2);
112 assert(obj);
113 hwloc_bitmap_or(group->nodeset, group->nodeset, obj->nodeset);
114 res = hwloc_topology_insert_group_object(topology, group);
115 assert(!res);
116 /* insert a group of three packages by nodeset */
117 group = hwloc_topology_alloc_group_object(topology);
118 assert(group);
119 obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PACKAGE, 0);
120 assert(obj);
121 group->nodeset = hwloc_bitmap_dup(obj->nodeset);
122 obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PACKAGE, 1);
123 assert(obj);
124 hwloc_bitmap_or(group->nodeset, group->nodeset, obj->nodeset);
125 obj = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PACKAGE, 2);
126 assert(obj);
127 hwloc_bitmap_or(group->nodeset, group->nodeset, obj->nodeset);
128 res = hwloc_topology_insert_group_object(topology, group);
129 assert(res == group);
130 assert(hwloc_topology_get_depth(topology) == 5);
131
132 hwloc_topology_destroy(topology);
133
134 /* intensive testing of two grouping cases (2+1 and 2+2+1) */
135
136 /* group 3 numa nodes as 1 group of 2 and 1 on the side */
137 hwloc_topology_init(&topology);
138 hwloc_topology_set_synthetic(topology, "node:3 pu:1");
139 hwloc_topology_load(topology);
140 /* 3 group at depth 1 */
141 depth = hwloc_get_type_depth(topology, HWLOC_OBJ_GROUP);
142 assert(depth == 1);
143 width = hwloc_get_nbobjs_by_depth(topology, 1);
144 assert(width == 3);
145 /* insert distances and groups */
146 for(i=0; i<3; i++)
147 objs[i] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, i);
148 values[0] = 1; values[1] = 4; values[2] = 4;
149 values[3] = 4; values[4] = 1; values[5] = 2;
150 values[6] = 4; values[7] = 2; values[8] = 1;
151 err = hwloc_distances_add(topology, 3, objs, values,
152 HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER,
153 HWLOC_DISTANCES_ADD_FLAG_GROUP);
154 assert(!err);
155 /* 1 groups at depth 1 and 2 */
156 depth = hwloc_get_type_depth(topology, HWLOC_OBJ_GROUP);
157 assert(depth == -2);
158 type = hwloc_get_depth_type(topology, 1);
159 assert(type == HWLOC_OBJ_GROUP);
160 width = hwloc_get_nbobjs_by_depth(topology, 1);
161 assert(width == 1);
162 type = hwloc_get_depth_type(topology, 2);
163 assert(type == HWLOC_OBJ_GROUP);
164 width = hwloc_get_nbobjs_by_depth(topology, 2);
165 assert(width == 3);
166 /* 3 nodes */
167 depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
168 assert(depth == HWLOC_TYPE_DEPTH_NUMANODE);
169 width = hwloc_get_nbobjs_by_depth(topology, depth);
170 assert(width == 3);
171 /* find the root obj */
172 obj = hwloc_get_root_obj(topology);
173 assert(obj->arity == 2);
174 /* check its children */
175 /* first child is a group with PU+NUMA children */
176 assert(obj->children[0]->type == HWLOC_OBJ_GROUP);
177 assert(obj->children[0]->depth == 2);
178 assert(obj->children[0]->arity == 1);
179 assert(obj->children[0]->first_child->type == HWLOC_OBJ_PU);
180 assert(obj->children[0]->memory_arity == 1);
181 assert(obj->children[0]->memory_first_child->type == HWLOC_OBJ_NUMANODE);
182 /* second child is a group with two group children */
183 assert(obj->children[1]->type == HWLOC_OBJ_GROUP);
184 assert(obj->children[1]->depth == 1);
185 assert(obj->children[1]->arity == 2);
186 assert(obj->children[1]->children[0]->type == HWLOC_OBJ_GROUP);
187 assert(obj->children[1]->children[1]->type == HWLOC_OBJ_GROUP);
188 assert(obj->children[1]->memory_arity == 0);
189 hwloc_topology_destroy(topology);
190
191 /* group 5 packages as 2 group of 2 and 1 on the side, all of them below a common node object */
192 hwloc_topology_init(&topology);
193 hwloc_topology_set_synthetic(topology, "node:1 pack:5 pu:1");
194 hwloc_topology_load(topology);
195 for(i=0; i<5; i++)
196 objs[i] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PACKAGE, i);
197 values[ 0] = 1; values[ 1] = 2; values[ 2] = 4; values[ 3] = 4; values[ 4] = 4;
198 values[ 5] = 2; values[ 6] = 1; values[ 7] = 4; values[ 8] = 4; values[ 9] = 4;
199 values[10] = 4; values[11] = 4; values[12] = 1; values[13] = 4; values[14] = 4;
200 values[15] = 4; values[16] = 4; values[17] = 4; values[18] = 1; values[19] = 2;
201 values[20] = 4; values[21] = 4; values[22] = 4; values[23] = 2; values[24] = 1;
202 err = hwloc_distances_add(topology, 5, objs, values,
203 HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER,
204 HWLOC_DISTANCES_ADD_FLAG_GROUP);
205 assert(!err);
206 /* 1 node */
207 depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
208 assert(depth == HWLOC_TYPE_DEPTH_NUMANODE);
209 width = hwloc_get_nbobjs_by_depth(topology, depth);
210 assert(width == 1);
211 /* 2 groups at depth 1 */
212 depth = hwloc_get_type_depth(topology, HWLOC_OBJ_GROUP);
213 assert(depth == 1);
214 width = hwloc_get_nbobjs_by_depth(topology, depth);
215 assert(width == 2);
216 /* 5 packages at depth 2 */
217 depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PACKAGE);
218 assert(depth == 2);
219 width = hwloc_get_nbobjs_by_depth(topology, depth);
220 assert(width == 5);
221 /* check root */
222 obj = hwloc_get_root_obj(topology);
223 assert(obj->arity == 3);
224 assert(obj->memory_arity == 1);
225 /* check root children */
226 assert(obj->children[0]->type == HWLOC_OBJ_GROUP);
227 assert(obj->children[0]->depth == 1);
228 assert(obj->children[0]->arity == 2);
229 assert(obj->children[1]->type == HWLOC_OBJ_PACKAGE);
230 assert(obj->children[1]->depth == 2);
231 assert(obj->children[1]->arity == 1);
232 assert(obj->children[2]->type == HWLOC_OBJ_GROUP);
233 assert(obj->children[2]->depth == 1);
234 assert(obj->children[2]->arity == 2);
235 obj = obj->memory_first_child;
236 assert(obj->type == HWLOC_OBJ_NUMANODE);
237 assert(obj->arity == 0);
238 assert(obj->memory_arity == 0);
239 hwloc_topology_destroy(topology);
240
241 /* testing of adding/replacing/removing distance matrices
242 and grouping with/without accuracy
243 */
244
245 /* grouping matrix 4*2*2 */
246 for(i=0; i<16; i++) {
247 for(j=0; j<16; j++)
248 if (i==j)
249 values[i+16*j] = values[j+16*i] = 30;
250 else if (i/2==j/2)
251 values[i+16*j] = values[j+16*i] = 50;
252 else if (i/4==j/4)
253 values[i+16*j] = values[j+16*i] = 70;
254 else
255 values[i+16*j] = values[j+16*i] = 90;
256 }
257
258 /* default 2*8*1 */
259 hwloc_topology_init(&topology);
260 hwloc_topology_set_synthetic(topology, "node:2 core:8 pu:1");
261 hwloc_topology_load(topology);
262 depth = hwloc_topology_get_depth(topology);
263 assert(depth == 4);
264 width = hwloc_get_nbobjs_by_depth(topology, 0);
265 assert(width == 1);
266 width = hwloc_get_nbobjs_by_depth(topology, 1);
267 assert(width == 2);
268 width = hwloc_get_nbobjs_by_depth(topology, 2);
269 assert(width == 16);
270 width = hwloc_get_nbobjs_by_depth(topology, 3);
271 assert(width == 16);
272 width = hwloc_get_nbobjs_by_depth(topology, HWLOC_TYPE_DEPTH_NUMANODE);
273 assert(width == 2);
274 /* group 8cores as 2*2*2 */
275 for(i=0; i<16; i++)
276 objs[i] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_CORE, i);
277 assert(!hwloc_distances_add(topology, 16, objs, values,
278 HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER,
279 HWLOC_DISTANCES_ADD_FLAG_GROUP));
280 depth = hwloc_topology_get_depth(topology);
281 assert(depth == 6);
282 width = hwloc_get_nbobjs_by_depth(topology, 0);
283 assert(width == 1);
284 width = hwloc_get_nbobjs_by_depth(topology, 1);
285 assert(width == 2);
286 width = hwloc_get_nbobjs_by_depth(topology, 2);
287 assert(width == 4);
288 width = hwloc_get_nbobjs_by_depth(topology, 3);
289 assert(width == 8);
290 width = hwloc_get_nbobjs_by_depth(topology, 4);
291 assert(width == 16);
292 width = hwloc_get_nbobjs_by_depth(topology, HWLOC_TYPE_DEPTH_NUMANODE);
293 assert(width == 2);
294 hwloc_topology_destroy(topology);
295
296 /* play with accuracy */
297 values[0] = 29; /* diagonal, instead of 3 (0.0333% error) */
298 values[1] = 51; values[16] = 52; /* smallest group, instead of 5 (0.02% error) */
299 putenv((char *) "HWLOC_GROUPING_ACCURACY=0.1"); /* ok */
300 hwloc_topology_init(&topology);
301 hwloc_topology_set_synthetic(topology, "node:2 core:8 pu:1");
302 hwloc_topology_load(topology);
303 for(i=0; i<16; i++)
304 objs[i] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_CORE, i);
305 assert(!hwloc_distances_add(topology, 16, objs, values,
306 HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER,
307 HWLOC_DISTANCES_ADD_FLAG_GROUP|HWLOC_DISTANCES_ADD_FLAG_GROUP_INACCURATE));
308 depth = hwloc_topology_get_depth(topology);
309 assert(depth == 6);
310 hwloc_topology_destroy(topology);
311
312 putenv((char *) "HWLOC_GROUPING_ACCURACY=try"); /* ok */
313 hwloc_topology_init(&topology);
314 hwloc_topology_set_synthetic(topology, "node:2 core:8 pu:1");
315 hwloc_topology_load(topology);
316 for(i=0; i<16; i++)
317 objs[i] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_CORE, i);
318 assert(!hwloc_distances_add(topology, 16, objs, values,
319 HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER,
320 HWLOC_DISTANCES_ADD_FLAG_GROUP|HWLOC_DISTANCES_ADD_FLAG_GROUP_INACCURATE));
321 depth = hwloc_topology_get_depth(topology);
322 assert(depth == 6);
323 hwloc_topology_destroy(topology);
324
325 hwloc_topology_init(&topology);
326 hwloc_topology_set_synthetic(topology, "node:2 core:8 pu:1");
327 hwloc_topology_load(topology);
328 for(i=0; i<16; i++)
329 objs[i] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_CORE, i);
330 assert(!hwloc_distances_add(topology, 16, objs, values,
331 HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER,
332 HWLOC_DISTANCES_ADD_FLAG_GROUP /* no inaccurate flag, cannot group */));
333 depth = hwloc_topology_get_depth(topology);
334 assert(depth == 4);
335 hwloc_topology_destroy(topology);
336
337 putenv((char *) "HWLOC_GROUPING_ACCURACY=0.01"); /* too small, cannot group */
338 hwloc_topology_init(&topology);
339 hwloc_topology_set_synthetic(topology, "node:2 core:8 pu:1");
340 hwloc_topology_load(topology);
341 for(i=0; i<16; i++)
342 objs[i] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_CORE, i);
343 assert(!hwloc_distances_add(topology, 16, objs, values,
344 HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER,
345 HWLOC_DISTANCES_ADD_FLAG_GROUP|HWLOC_DISTANCES_ADD_FLAG_GROUP_INACCURATE));
346 depth = hwloc_topology_get_depth(topology);
347 assert(depth == 4);
348 hwloc_topology_destroy(topology);
349
350 putenv((char *) "HWLOC_GROUPING_ACCURACY=0"); /* full accuracy, cannot group */
351 hwloc_topology_init(&topology);
352 hwloc_topology_set_synthetic(topology, "node:2 core:8 pu:1");
353 hwloc_topology_load(topology);
354 for(i=0; i<16; i++)
355 objs[i] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_CORE, i);
356 assert(!hwloc_distances_add(topology, 16, objs, values,
357 HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER,
358 HWLOC_DISTANCES_ADD_FLAG_GROUP|HWLOC_DISTANCES_ADD_FLAG_GROUP_INACCURATE));
359 depth = hwloc_topology_get_depth(topology);
360 assert(depth == 4);
361 hwloc_topology_destroy(topology);
362
363 /* default 2*4*4 */
364 hwloc_topology_init(&topology);
365 hwloc_topology_set_synthetic(topology, "node:2 core:4 pu:4");
366 hwloc_topology_load(topology);
367 depth = hwloc_topology_get_depth(topology);
368 assert(depth == 4);
369 width = hwloc_get_nbobjs_by_depth(topology, 0);
370 assert(width == 1);
371 width = hwloc_get_nbobjs_by_depth(topology, 1);
372 assert(width == 2);
373 width = hwloc_get_nbobjs_by_depth(topology, 2);
374 assert(width == 8);
375 width = hwloc_get_nbobjs_by_depth(topology, 3);
376 assert(width == 32);
377 width = hwloc_get_nbobjs_by_depth(topology, HWLOC_TYPE_DEPTH_NUMANODE);
378 assert(width == 2);
379 /* apply useless core distances */
380 for(i=0; i<8; i++) {
381 objs[i] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_CORE, i);
382 for(j=0; j<8; j++)
383 if (i==j)
384 values[i+8*j] = values[j+8*i] = 1;
385 else if (i/4==j/4)
386 values[i+8*j] = values[j+8*i] = 4;
387 else
388 values[i+8*j] = values[j+8*i] = 8;
389 }
390 assert(!hwloc_distances_add(topology, 8, objs, values,
391 HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER,
392 HWLOC_DISTANCES_ADD_FLAG_GROUP));
393 depth = hwloc_topology_get_depth(topology);
394 assert(depth == 4);
395 /* group 4cores as 2*2 */
396 for(i=0; i<8; i++) {
397 objs[i] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_CORE, i);
398 for(j=0; j<8; j++)
399 if (i==j)
400 values[i+8*j] = values[j+8*i] = 1;
401 else if (i/2==j/2)
402 values[i+8*j] = values[j+8*i] = 4;
403 else
404 values[i+8*j] = values[j+8*i] = 8;
405 }
406 assert(!hwloc_distances_add(topology, 8, objs, values,
407 HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER,
408 HWLOC_DISTANCES_ADD_FLAG_GROUP));
409 depth = hwloc_topology_get_depth(topology);
410 assert(depth == 5);
411 width = hwloc_get_nbobjs_by_depth(topology, 0);
412 assert(width == 1);
413 width = hwloc_get_nbobjs_by_depth(topology, 1);
414 assert(width == 2);
415 width = hwloc_get_nbobjs_by_depth(topology, 2);
416 assert(width == 4);
417 width = hwloc_get_nbobjs_by_depth(topology, 3);
418 assert(width == 8);
419 width = hwloc_get_nbobjs_by_depth(topology, 4);
420 assert(width == 32);
421 width = hwloc_get_nbobjs_by_depth(topology, HWLOC_TYPE_DEPTH_NUMANODE);
422 assert(width == 2);
423 /* group 4PUs as 2*2 */
424 for(i=0; i<32; i++) {
425 objs[i] = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PU, i);
426 for(j=0; j<32; j++)
427 if (i==j)
428 values[i+32*j] = values[j+32*i] = 1;
429 else if (i/2==j/2)
430 values[i+32*j] = values[j+32*i] = 4;
431 else
432 values[i+32*j] = values[j+32*i] = 8;
433 }
434 assert(!hwloc_distances_add(topology, 32, objs, values,
435 HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_FROM_USER,
436 HWLOC_DISTANCES_ADD_FLAG_GROUP));
437 depth = hwloc_topology_get_depth(topology);
438 assert(depth == 6);
439 width = hwloc_get_nbobjs_by_depth(topology, 0);
440 assert(width == 1);
441 width = hwloc_get_nbobjs_by_depth(topology, 1);
442 assert(width == 2);
443 width = hwloc_get_nbobjs_by_depth(topology, 2);
444 assert(width == 4);
445 width = hwloc_get_nbobjs_by_depth(topology, 3);
446 assert(width == 8);
447 width = hwloc_get_nbobjs_by_depth(topology, 4);
448 assert(width == 16);
449 width = hwloc_get_nbobjs_by_depth(topology, 5);
450 assert(width == 32);
451 width = hwloc_get_nbobjs_by_depth(topology, HWLOC_TYPE_DEPTH_NUMANODE);
452 assert(width == 2);
453 hwloc_topology_destroy(topology);
454
455 return 0;
456 }
457