root/opal/mca/hwloc/hwloc201/hwloc/include/hwloc/opencl.h

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

DEFINITIONS

This source file includes following definitions.
  1. hwloc_opencl_get_device_cpuset
  2. hwloc_opencl_get_device_osdev_by_index
  3. hwloc_opencl_get_device_osdev

   1 /*
   2  * Copyright © 2012-2018 Inria.  All rights reserved.
   3  * Copyright © 2013, 2018 Université Bordeaux.  All right reserved.
   4  * See COPYING in top-level directory.
   5  */
   6 
   7 /** \file
   8  * \brief Macros to help interaction between hwloc and the OpenCL interface.
   9  *
  10  * Applications that use both hwloc and OpenCL may want to
  11  * include this file so as to get topology information for OpenCL devices.
  12  */
  13 
  14 #ifndef HWLOC_OPENCL_H
  15 #define HWLOC_OPENCL_H
  16 
  17 #include <hwloc.h>
  18 #include <hwloc/autogen/config.h>
  19 #include <hwloc/helper.h>
  20 #ifdef HWLOC_LINUX_SYS
  21 #include <hwloc/linux.h>
  22 #endif
  23 
  24 #ifdef __APPLE__
  25 #include <OpenCL/cl.h>
  26 #include <OpenCL/cl_ext.h>
  27 #else
  28 #include <CL/cl.h>
  29 #include <CL/cl_ext.h>
  30 #endif
  31 
  32 #include <stdio.h>
  33 
  34 
  35 #ifdef __cplusplus
  36 extern "C" {
  37 #endif
  38 
  39 
  40 /** \defgroup hwlocality_opencl Interoperability with OpenCL
  41  *
  42  * This interface offers ways to retrieve topology information about
  43  * OpenCL devices.
  44  *
  45  * Only the AMD OpenCL interface currently offers useful locality information
  46  * about its devices.
  47  *
  48  * @{
  49  */
  50 
  51 /** \brief Get the CPU set of logical processors that are physically
  52  * close to OpenCL device \p device.
  53  *
  54  * Return the CPU set describing the locality of the OpenCL device \p device.
  55  *
  56  * Topology \p topology and device \p device must match the local machine.
  57  * I/O devices detection and the OpenCL component are not needed in the topology.
  58  *
  59  * The function only returns the locality of the device.
  60  * If more information about the device is needed, OS objects should
  61  * be used instead, see hwloc_opencl_get_device_osdev()
  62  * and hwloc_opencl_get_device_osdev_by_index().
  63  *
  64  * This function is currently only implemented in a meaningful way for
  65  * Linux with the AMD OpenCL implementation; other systems will simply
  66  * get a full cpuset.
  67  */
  68 static __hwloc_inline int
  69 hwloc_opencl_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
  70                                cl_device_id device __hwloc_attribute_unused,
  71                                hwloc_cpuset_t set)
  72 {
  73 #if (defined HWLOC_LINUX_SYS) && (defined CL_DEVICE_TOPOLOGY_AMD)
  74         /* If we're on Linux + AMD OpenCL, use the AMD extension + the sysfs mechanism to get the local cpus */
  75 #define HWLOC_OPENCL_DEVICE_SYSFS_PATH_MAX 128
  76         char path[HWLOC_OPENCL_DEVICE_SYSFS_PATH_MAX];
  77         cl_device_topology_amd amdtopo;
  78         cl_int clret;
  79 
  80         if (!hwloc_topology_is_thissystem(topology)) {
  81                 errno = EINVAL;
  82                 return -1;
  83         }
  84 
  85         clret = clGetDeviceInfo(device, CL_DEVICE_TOPOLOGY_AMD, sizeof(amdtopo), &amdtopo, NULL);
  86         if (CL_SUCCESS != clret) {
  87                 hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
  88                 return 0;
  89         }
  90         if (CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD != amdtopo.raw.type) {
  91                 hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
  92                 return 0;
  93         }
  94 
  95         sprintf(path, "/sys/bus/pci/devices/0000:%02x:%02x.%01x/local_cpus",
  96                 (unsigned) amdtopo.pcie.bus, (unsigned) amdtopo.pcie.device, (unsigned) amdtopo.pcie.function);
  97         if (hwloc_linux_read_path_as_cpumask(path, set) < 0
  98             || hwloc_bitmap_iszero(set))
  99                 hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
 100 #else
 101         /* Non-Linux + AMD OpenCL systems simply get a full cpuset */
 102         hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
 103 #endif
 104   return 0;
 105 }
 106 
 107 /** \brief Get the hwloc OS device object corresponding to the
 108  * OpenCL device for the given indexes.
 109  *
 110  * Return the OS device object describing the OpenCL device
 111  * whose platform index is \p platform_index,
 112  * and whose device index within this platform if \p device_index.
 113  * Return NULL if there is none.
 114  *
 115  * The topology \p topology does not necessarily have to match the current
 116  * machine. For instance the topology may be an XML import of a remote host.
 117  * I/O devices detection and the OpenCL component must be enabled in the topology.
 118  *
 119  * \note The corresponding PCI device object can be obtained by looking
 120  * at the OS device parent object (unless PCI devices are filtered out).
 121  */
 122 static __hwloc_inline hwloc_obj_t
 123 hwloc_opencl_get_device_osdev_by_index(hwloc_topology_t topology,
 124                                        unsigned platform_index, unsigned device_index)
 125 {
 126         unsigned x = (unsigned) -1, y = (unsigned) -1;
 127         hwloc_obj_t osdev = NULL;
 128         while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
 129                 if (HWLOC_OBJ_OSDEV_COPROC == osdev->attr->osdev.type
 130                     && osdev->name
 131                     && sscanf(osdev->name, "opencl%ud%u", &x, &y) == 2
 132                     && platform_index == x && device_index == y)
 133                         return osdev;
 134         }
 135         return NULL;
 136 }
 137 
 138 /** \brief Get the hwloc OS device object corresponding to OpenCL device \p deviceX.
 139  *
 140  * Use OpenCL device attributes to find the corresponding hwloc OS device object.
 141  * Return NULL if there is none or if useful attributes are not available.
 142  *
 143  * This function currently only works on AMD OpenCL devices that support
 144  * the CL_DEVICE_TOPOLOGY_AMD extension. hwloc_opencl_get_device_osdev_by_index()
 145  * should be preferred whenever possible, i.e. when platform and device index
 146  * are known.
 147  *
 148  * Topology \p topology and device \p device must match the local machine.
 149  * I/O devices detection and the OpenCL component must be enabled in the topology.
 150  * If not, the locality of the object may still be found using
 151  * hwloc_opencl_get_device_cpuset().
 152  *
 153  * \note This function cannot work if PCI devices are filtered out.
 154  *
 155  * \note The corresponding hwloc PCI device may be found by looking
 156  * at the result parent pointer (unless PCI devices are filtered out).
 157  */
 158 static __hwloc_inline hwloc_obj_t
 159 hwloc_opencl_get_device_osdev(hwloc_topology_t topology __hwloc_attribute_unused,
 160                               cl_device_id device __hwloc_attribute_unused)
 161 {
 162 #ifdef CL_DEVICE_TOPOLOGY_AMD
 163         hwloc_obj_t osdev;
 164         cl_device_topology_amd amdtopo;
 165         cl_int clret;
 166 
 167         clret = clGetDeviceInfo(device, CL_DEVICE_TOPOLOGY_AMD, sizeof(amdtopo), &amdtopo, NULL);
 168         if (CL_SUCCESS != clret) {
 169                 errno = EINVAL;
 170                 return NULL;
 171         }
 172         if (CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD != amdtopo.raw.type) {
 173                 errno = EINVAL;
 174                 return NULL;
 175         }
 176 
 177         osdev = NULL;
 178         while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
 179                 hwloc_obj_t pcidev = osdev->parent;
 180                 if (strncmp(osdev->name, "opencl", 6))
 181                         continue;
 182                 if (pcidev
 183                     && pcidev->type == HWLOC_OBJ_PCI_DEVICE
 184                     && pcidev->attr->pcidev.domain == 0
 185                     && pcidev->attr->pcidev.bus == amdtopo.pcie.bus
 186                     && pcidev->attr->pcidev.dev == amdtopo.pcie.device
 187                     && pcidev->attr->pcidev.func == amdtopo.pcie.function)
 188                         return osdev;
 189                 /* if PCI are filtered out, we need a info attr to match on */
 190         }
 191 
 192         return NULL;
 193 #else
 194         return NULL;
 195 #endif
 196 }
 197 
 198 /** @} */
 199 
 200 
 201 #ifdef __cplusplus
 202 } /* extern "C" */
 203 #endif
 204 
 205 
 206 #endif /* HWLOC_OPENCL_H */

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