1 /*
2  * Copyright © 2012 Blue Brain Project, BBP/EPFL. All rights reserved.
3  * Copyright © 2012-2015 Inria.  All rights reserved.
4  * See COPYING in top-level directory.
5  */
6 
7 #include "hwloc.h"
8 #include "hwloc/gl.h"
9 #include "hwloc/helper.h"
10 
11 #include <errno.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include "stdlib.h"
15 
main(void)16 int main(void)
17 {
18   hwloc_topology_t topology;
19   hwloc_obj_t pcidev, osdev, parent;
20   hwloc_obj_t firstgpu = NULL, lastgpu = NULL;
21   unsigned port, device;
22   char* cpuset_string;
23   unsigned nr_pcidev;
24   unsigned nr_osdev;
25   unsigned nr_gpus;
26   unsigned i;
27   int err;
28 
29   hwloc_topology_init(&topology); /* Topology initialization */
30 
31   /* Flags used for loading the I/O devices, bridges and their relevant info */
32   hwloc_topology_set_io_types_filter(topology, HWLOC_TYPE_FILTER_KEEP_IMPORTANT);
33 
34   /* Perform topology detection */
35   hwloc_topology_load(topology);
36 
37   /* Case 1: Get the cpusets of the packages connecting the PCI devices in the topology */
38   nr_pcidev = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_PCI_DEVICE);
39   for (i = 0; i < nr_pcidev; ++i) {
40       pcidev = hwloc_get_obj_by_type(topology, HWLOC_OBJ_PCI_DEVICE, i);
41       parent = hwloc_get_non_io_ancestor_obj(topology, pcidev);
42       /* Print the cpuset corresponding to each pci device */
43       hwloc_bitmap_asprintf(&cpuset_string, parent->cpuset);
44       printf(" %s | %s \n", cpuset_string, pcidev->name);
45       free(cpuset_string);
46     }
47 
48   /* Case 2: Get the number of connected GPUs in the topology and their attached displays */
49   nr_gpus = 0;
50   nr_osdev = hwloc_get_nbobjs_by_type(topology, HWLOC_OBJ_OS_DEVICE);
51   for (i = 0; i < nr_osdev; ++i) {
52       const char *model, *backend;
53       osdev = hwloc_get_obj_by_type(topology, HWLOC_OBJ_OS_DEVICE, i);
54 
55       backend = hwloc_obj_get_info_by_name(osdev, "Backend");
56       model = hwloc_obj_get_info_by_name(osdev, "GPUModel");
57 
58       err = hwloc_gl_get_display_by_osdev(topology, osdev, &port, &device);
59       if (!err) {
60 	err = strcmp(backend, "GL");
61 	assert(!err);
62 
63 	assert(osdev->attr->osdev.type == HWLOC_OBJ_OSDEV_GPU);
64 
65 	if (!firstgpu)
66 	  firstgpu = osdev;
67 	lastgpu = osdev;
68 	printf("GPU #%u (%s) is connected to DISPLAY:%u.%u \n", nr_gpus, model, port, device);
69 	nr_gpus++;
70       } else {
71 	if (backend) {
72 	  err = strcmp(backend, "GL");
73 	  assert(err);
74 	}
75       }
76     }
77 
78   /* Case 3: Get the first GPU connected to a valid display, specified by its port and device */
79   if (firstgpu) {
80     assert(sscanf(firstgpu->name, ":%u.%u", &port, &device) == 2);
81     osdev = hwloc_gl_get_display_osdev_by_port_device(topology, port, device);
82     assert(osdev == firstgpu);
83     pcidev = osdev->parent;
84     parent = hwloc_get_non_io_ancestor_obj(topology, pcidev);
85     hwloc_bitmap_asprintf(&cpuset_string, parent->cpuset);
86     printf("GPU %s (PCI %04x:%02x:%02x.%01x) is connected to DISPLAY:%u.%u close to %s\n",
87 	   osdev->name,
88 	   pcidev->attr->pcidev.domain, pcidev->attr->pcidev.bus, pcidev->attr->pcidev.dev, pcidev->attr->pcidev.func,
89 	   port, device, cpuset_string);
90     free(cpuset_string);
91   }
92 
93   /* Case 4: Get the last GPU connected to a valid display, specified by its name */
94   if (lastgpu) {
95     assert(sscanf(lastgpu->name, ":%u.%u", &port, &device) == 2);
96     osdev = hwloc_gl_get_display_osdev_by_name(topology, lastgpu->name);
97     assert(osdev == lastgpu);
98     pcidev = osdev->parent;
99     parent = hwloc_get_non_io_ancestor_obj(topology, pcidev);
100     hwloc_bitmap_asprintf(&cpuset_string, parent->cpuset);
101     printf("GPU %s (PCI %04x:%02x:%02x.%01x) is connected to DISPLAY:%u.%u close to %s\n",
102 	   osdev->name,
103 	   pcidev->attr->pcidev.domain, pcidev->attr->pcidev.bus, pcidev->attr->pcidev.dev, pcidev->attr->pcidev.func,
104 	   port, device, cpuset_string);
105     free(cpuset_string);
106   }
107 
108   return 0;
109 }
110