This source file includes following definitions.
- hwloc_nvml_discover
- hwloc_nvml_component_instantiate
- hwloc_nvml_component_init
1
2
3
4
5
6 #include <private/autogen/config.h>
7 #include <hwloc.h>
8 #include <hwloc/plugins.h>
9
10
11 #include <private/misc.h>
12 #include <private/debug.h>
13
14 #include <nvml.h>
15
16 static int
17 hwloc_nvml_discover(struct hwloc_backend *backend)
18 {
19 struct hwloc_topology *topology = backend->topology;
20 enum hwloc_type_filter_e filter;
21 nvmlReturn_t ret;
22 unsigned nb, i;
23
24 hwloc_topology_get_type_filter(topology, HWLOC_OBJ_OS_DEVICE, &filter);
25 if (filter == HWLOC_TYPE_FILTER_KEEP_NONE)
26 return 0;
27
28 ret = nvmlInit();
29 if (NVML_SUCCESS != ret)
30 return -1;
31 ret = nvmlDeviceGetCount(&nb);
32 if (NVML_SUCCESS != ret || !nb) {
33 nvmlShutdown();
34 return 0;
35 }
36
37 for(i=0; i<nb; i++) {
38 nvmlPciInfo_t pci;
39 nvmlDevice_t device;
40 hwloc_obj_t osdev, parent;
41 char buffer[64];
42
43 ret = nvmlDeviceGetHandleByIndex(i, &device);
44 assert(ret == NVML_SUCCESS);
45
46 osdev = hwloc_alloc_setup_object(topology, HWLOC_OBJ_OS_DEVICE, HWLOC_UNKNOWN_INDEX);
47 snprintf(buffer, sizeof(buffer), "nvml%u", i);
48 osdev->name = strdup(buffer);
49 osdev->depth = HWLOC_TYPE_DEPTH_UNKNOWN;
50 osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_GPU;
51
52 hwloc_obj_add_info(osdev, "Backend", "NVML");
53 hwloc_obj_add_info(osdev, "GPUVendor", "NVIDIA Corporation");
54
55 buffer[0] = '\0';
56 ret = nvmlDeviceGetName(device, buffer, sizeof(buffer));
57 hwloc_obj_add_info(osdev, "GPUModel", buffer);
58
59
60 buffer[0] = '\0';
61 ret = nvmlDeviceGetSerial(device, buffer, sizeof(buffer));
62 if (buffer[0] != '\0')
63 hwloc_obj_add_info(osdev, "NVIDIASerial", buffer);
64
65 buffer[0] = '\0';
66 ret = nvmlDeviceGetUUID(device, buffer, sizeof(buffer));
67 if (buffer[0] != '\0')
68 hwloc_obj_add_info(osdev, "NVIDIAUUID", buffer);
69
70 parent = NULL;
71 if (NVML_SUCCESS == nvmlDeviceGetPciInfo(device, &pci)) {
72 parent = hwloc_pcidisc_find_by_busid(topology, pci.domain, pci.bus, pci.device, 0);
73 if (!parent)
74 parent = hwloc_pcidisc_find_busid_parent(topology, pci.domain, pci.bus, pci.device, 0);
75 #if HAVE_DECL_NVMLDEVICEGETMAXPCIELINKGENERATION
76 if (parent && parent->type == HWLOC_OBJ_PCI_DEVICE) {
77 unsigned maxwidth = 0, maxgen = 0;
78 float lanespeed;
79 nvmlDeviceGetMaxPcieLinkWidth(device, &maxwidth);
80 nvmlDeviceGetMaxPcieLinkGeneration(device, &maxgen);
81
82
83
84
85 lanespeed = maxgen <= 2 ? 2.5 * maxgen * 0.8 : 8.0 * 128/130;
86 if (lanespeed * maxwidth != 0.)
87
88 parent->attr->pcidev.linkspeed = lanespeed * maxwidth / 8;
89 }
90 #endif
91 }
92 if (!parent)
93 parent = hwloc_get_root_obj(topology);
94
95 hwloc_insert_object_by_parent(topology, parent, osdev);
96 }
97
98 nvmlShutdown();
99 return 0;
100 }
101
102 static struct hwloc_backend *
103 hwloc_nvml_component_instantiate(struct hwloc_disc_component *component,
104 const void *_data1 __hwloc_attribute_unused,
105 const void *_data2 __hwloc_attribute_unused,
106 const void *_data3 __hwloc_attribute_unused)
107 {
108 struct hwloc_backend *backend;
109
110 backend = hwloc_backend_alloc(component);
111 if (!backend)
112 return NULL;
113 backend->discover = hwloc_nvml_discover;
114 return backend;
115 }
116
117 static struct hwloc_disc_component hwloc_nvml_disc_component = {
118 HWLOC_DISC_COMPONENT_TYPE_MISC,
119 "nvml",
120 HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
121 hwloc_nvml_component_instantiate,
122 5,
123 1,
124 NULL
125 };
126
127 static int
128 hwloc_nvml_component_init(unsigned long flags)
129 {
130 if (flags)
131 return -1;
132 if (hwloc_plugin_check_namespace("nvml", "hwloc_backend_alloc") < 0)
133 return -1;
134 return 0;
135 }
136
137 #ifdef HWLOC_INSIDE_PLUGIN
138 HWLOC_DECLSPEC extern const struct hwloc_component hwloc_nvml_component;
139 #endif
140
141 const struct hwloc_component hwloc_nvml_component = {
142 HWLOC_COMPONENT_ABI,
143 hwloc_nvml_component_init, NULL,
144 HWLOC_COMPONENT_TYPE_DISC,
145 0,
146 &hwloc_nvml_disc_component
147 };