root/opal/mca/hwloc/hwloc201/hwloc/hwloc/topology-nvml.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hwloc_nvml_discover
  2. hwloc_nvml_component_instantiate
  3. hwloc_nvml_component_init

   1 /*
   2  * Copyright © 2012-2017 Inria.  All rights reserved.
   3  * See COPYING in top-level directory.
   4  */
   5 
   6 #include <private/autogen/config.h>
   7 #include <hwloc.h>
   8 #include <hwloc/plugins.h>
   9 
  10 /* private headers allowed for convenience because this plugin is built within hwloc */
  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     /* these may fail with NVML_ERROR_NOT_SUPPORTED on old devices */
  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         /* PCIe Gen1 = 2.5GT/s signal-rate per lane with 8/10 encoding    = 0.25GB/s data-rate per lane
  82          * PCIe Gen2 = 5  GT/s signal-rate per lane with 8/10 encoding    = 0.5 GB/s data-rate per lane
  83          * PCIe Gen3 = 8  GT/s signal-rate per lane with 128/130 encoding = 1   GB/s data-rate per lane
  84          */
  85         lanespeed = maxgen <= 2 ? 2.5 * maxgen * 0.8 : 8.0 * 128/130; /* Gbit/s per lane */
  86         if (lanespeed * maxwidth != 0.)
  87           /* we found the max link speed, replace the current link speed found by pci (or none) */
  88           parent->attr->pcidev.linkspeed = lanespeed * maxwidth / 8; /* GB/s */
  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, /* after pci, and after cuda since likely less useful */
 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 };

/* [<][>][^][v][top][bottom][index][help] */