Hardware Locality (hwloc)  v2.0-20191027.0400.gite37e7d8
opencl.h
00001 /*
00002  * Copyright © 2012-2018 Inria.  All rights reserved.
00003  * Copyright © 2013, 2018 Université Bordeaux.  All right reserved.
00004  * See COPYING in top-level directory.
00005  */
00006 
00014 #ifndef HWLOC_OPENCL_H
00015 #define HWLOC_OPENCL_H
00016 
00017 #include <hwloc.h>
00018 #include <hwloc/autogen/config.h>
00019 #include <hwloc/helper.h>
00020 #ifdef HWLOC_LINUX_SYS
00021 #include <hwloc/linux.h>
00022 #endif
00023 
00024 #ifdef __APPLE__
00025 #include <OpenCL/cl.h>
00026 #include <OpenCL/cl_ext.h>
00027 #else
00028 #include <CL/cl.h>
00029 #include <CL/cl_ext.h>
00030 #endif
00031 
00032 #include <stdio.h>
00033 
00034 
00035 #ifdef __cplusplus
00036 extern "C" {
00037 #endif
00038 
00039 
00068 static __hwloc_inline int
00069 hwloc_opencl_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
00070                                cl_device_id device __hwloc_attribute_unused,
00071                                hwloc_cpuset_t set)
00072 {
00073 #if (defined HWLOC_LINUX_SYS) && (defined CL_DEVICE_TOPOLOGY_AMD)
00074         /* If we're on Linux + AMD OpenCL, use the AMD extension + the sysfs mechanism to get the local cpus */
00075 #define HWLOC_OPENCL_DEVICE_SYSFS_PATH_MAX 128
00076         char path[HWLOC_OPENCL_DEVICE_SYSFS_PATH_MAX];
00077         cl_device_topology_amd amdtopo;
00078         cl_int clret;
00079 
00080         if (!hwloc_topology_is_thissystem(topology)) {
00081                 errno = EINVAL;
00082                 return -1;
00083         }
00084 
00085         clret = clGetDeviceInfo(device, CL_DEVICE_TOPOLOGY_AMD, sizeof(amdtopo), &amdtopo, NULL);
00086         if (CL_SUCCESS != clret) {
00087                 hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
00088                 return 0;
00089         }
00090         if (CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD != amdtopo.raw.type) {
00091                 hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
00092                 return 0;
00093         }
00094 
00095         sprintf(path, "/sys/bus/pci/devices/0000:%02x:%02x.%01x/local_cpus",
00096                 (unsigned) amdtopo.pcie.bus, (unsigned) amdtopo.pcie.device, (unsigned) amdtopo.pcie.function);
00097         if (hwloc_linux_read_path_as_cpumask(path, set) < 0
00098             || hwloc_bitmap_iszero(set))
00099                 hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
00100 #else
00101         /* Non-Linux + AMD OpenCL systems simply get a full cpuset */
00102         hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
00103 #endif
00104   return 0;
00105 }
00106 
00122 static __hwloc_inline hwloc_obj_t
00123 hwloc_opencl_get_device_osdev_by_index(hwloc_topology_t topology,
00124                                        unsigned platform_index, unsigned device_index)
00125 {
00126         unsigned x = (unsigned) -1, y = (unsigned) -1;
00127         hwloc_obj_t osdev = NULL;
00128         while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
00129                 if (HWLOC_OBJ_OSDEV_COPROC == osdev->attr->osdev.type
00130                     && osdev->name
00131                     && sscanf(osdev->name, "opencl%ud%u", &x, &y) == 2
00132                     && platform_index == x && device_index == y)
00133                         return osdev;
00134         }
00135         return NULL;
00136 }
00137 
00158 static __hwloc_inline hwloc_obj_t
00159 hwloc_opencl_get_device_osdev(hwloc_topology_t topology __hwloc_attribute_unused,
00160                               cl_device_id device __hwloc_attribute_unused)
00161 {
00162 #ifdef CL_DEVICE_TOPOLOGY_AMD
00163         hwloc_obj_t osdev;
00164         cl_device_topology_amd amdtopo;
00165         cl_int clret;
00166 
00167         clret = clGetDeviceInfo(device, CL_DEVICE_TOPOLOGY_AMD, sizeof(amdtopo), &amdtopo, NULL);
00168         if (CL_SUCCESS != clret) {
00169                 errno = EINVAL;
00170                 return NULL;
00171         }
00172         if (CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD != amdtopo.raw.type) {
00173                 errno = EINVAL;
00174                 return NULL;
00175         }
00176 
00177         osdev = NULL;
00178         while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
00179                 hwloc_obj_t pcidev = osdev->parent;
00180                 if (strncmp(osdev->name, "opencl", 6))
00181                         continue;
00182                 if (pcidev
00183                     && pcidev->type == HWLOC_OBJ_PCI_DEVICE
00184                     && pcidev->attr->pcidev.domain == 0
00185                     && pcidev->attr->pcidev.bus == amdtopo.pcie.bus
00186                     && pcidev->attr->pcidev.dev == amdtopo.pcie.device
00187                     && pcidev->attr->pcidev.func == amdtopo.pcie.function)
00188                         return osdev;
00189                 /* if PCI are filtered out, we need a info attr to match on */
00190         }
00191 
00192         return NULL;
00193 #else
00194         return NULL;
00195 #endif
00196 }
00197 
00201 #ifdef __cplusplus
00202 } /* extern "C" */
00203 #endif
00204 
00205 
00206 #endif /* HWLOC_OPENCL_H */