Hardware Locality (hwloc)  v2.0-20191027.0400.gite37e7d8
cuda.h
00001 /*
00002  * Copyright © 2010-2017 Inria.  All rights reserved.
00003  * Copyright © 2010-2011 Université Bordeaux
00004  * Copyright © 2011 Cisco Systems, Inc.  All rights reserved.
00005  * See COPYING in top-level directory.
00006  */
00007 
00016 #ifndef HWLOC_CUDA_H
00017 #define HWLOC_CUDA_H
00018 
00019 #include <hwloc.h>
00020 #include <hwloc/autogen/config.h>
00021 #include <hwloc/helper.h>
00022 #ifdef HWLOC_LINUX_SYS
00023 #include <hwloc/linux.h>
00024 #endif
00025 
00026 #include <cuda.h>
00027 
00028 
00029 #ifdef __cplusplus
00030 extern "C" {
00031 #endif
00032 
00033 
00046 static __hwloc_inline int
00047 hwloc_cuda_get_device_pci_ids(hwloc_topology_t topology __hwloc_attribute_unused,
00048                               CUdevice cudevice, int *domain, int *bus, int *dev)
00049 {
00050   CUresult cres;
00051 
00052 #if CUDA_VERSION >= 4000
00053   cres = cuDeviceGetAttribute(domain, CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID, cudevice);
00054   if (cres != CUDA_SUCCESS) {
00055     errno = ENOSYS;
00056     return -1;
00057   }
00058 #else
00059   *domain = 0;
00060 #endif
00061   cres = cuDeviceGetAttribute(bus, CU_DEVICE_ATTRIBUTE_PCI_BUS_ID, cudevice);
00062   if (cres != CUDA_SUCCESS) {
00063     errno = ENOSYS;
00064     return -1;
00065   }
00066   cres = cuDeviceGetAttribute(dev, CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID, cudevice);
00067   if (cres != CUDA_SUCCESS) {
00068     errno = ENOSYS;
00069     return -1;
00070   }
00071 
00072   return 0;
00073 }
00074 
00091 static __hwloc_inline int
00092 hwloc_cuda_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
00093                              CUdevice cudevice, hwloc_cpuset_t set)
00094 {
00095 #ifdef HWLOC_LINUX_SYS
00096   /* If we're on Linux, use the sysfs mechanism to get the local cpus */
00097 #define HWLOC_CUDA_DEVICE_SYSFS_PATH_MAX 128
00098   char path[HWLOC_CUDA_DEVICE_SYSFS_PATH_MAX];
00099   int domainid, busid, deviceid;
00100 
00101   if (hwloc_cuda_get_device_pci_ids(topology, cudevice, &domainid, &busid, &deviceid))
00102     return -1;
00103 
00104   if (!hwloc_topology_is_thissystem(topology)) {
00105     errno = EINVAL;
00106     return -1;
00107   }
00108 
00109   sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.0/local_cpus", domainid, busid, deviceid);
00110   if (hwloc_linux_read_path_as_cpumask(path, set) < 0
00111       || hwloc_bitmap_iszero(set))
00112     hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
00113 #else
00114   /* Non-Linux systems simply get a full cpuset */
00115   hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
00116 #endif
00117   return 0;
00118 }
00119 
00130 static __hwloc_inline hwloc_obj_t
00131 hwloc_cuda_get_device_pcidev(hwloc_topology_t topology, CUdevice cudevice)
00132 {
00133   int domain, bus, dev;
00134 
00135   if (hwloc_cuda_get_device_pci_ids(topology, cudevice, &domain, &bus, &dev))
00136     return NULL;
00137 
00138   return hwloc_get_pcidev_by_busid(topology, domain, bus, dev, 0);
00139 }
00140 
00156 static __hwloc_inline hwloc_obj_t
00157 hwloc_cuda_get_device_osdev(hwloc_topology_t topology, CUdevice cudevice)
00158 {
00159         hwloc_obj_t osdev = NULL;
00160         int domain, bus, dev;
00161 
00162         if (hwloc_cuda_get_device_pci_ids(topology, cudevice, &domain, &bus, &dev))
00163                 return NULL;
00164 
00165         osdev = NULL;
00166         while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
00167                 hwloc_obj_t pcidev = osdev->parent;
00168                 if (strncmp(osdev->name, "cuda", 4))
00169                         continue;
00170                 if (pcidev
00171                     && pcidev->type == HWLOC_OBJ_PCI_DEVICE
00172                     && (int) pcidev->attr->pcidev.domain == domain
00173                     && (int) pcidev->attr->pcidev.bus == bus
00174                     && (int) pcidev->attr->pcidev.dev == dev
00175                     && pcidev->attr->pcidev.func == 0)
00176                         return osdev;
00177                 /* if PCI are filtered out, we need a info attr to match on */
00178         }
00179 
00180         return NULL;
00181 }
00182 
00198 static __hwloc_inline hwloc_obj_t
00199 hwloc_cuda_get_device_osdev_by_index(hwloc_topology_t topology, unsigned idx)
00200 {
00201         hwloc_obj_t osdev = NULL;
00202         while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
00203                 if (HWLOC_OBJ_OSDEV_COPROC == osdev->attr->osdev.type
00204                     && osdev->name
00205                     && !strncmp("cuda", osdev->name, 4)
00206                     && atoi(osdev->name + 4) == (int) idx)
00207                         return osdev;
00208         }
00209         return NULL;
00210 }
00211 
00215 #ifdef __cplusplus
00216 } /* extern "C" */
00217 #endif
00218 
00219 
00220 #endif /* HWLOC_CUDA_H */