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