|
|
|||
File indexing completed on 2026-09-25 09:16:39
0001 /* 0002 * SPDX-License-Identifier: BSD-3-Clause 0003 * Copyright © 2010-2023 Inria. All rights reserved. 0004 * Copyright © 2010-2011 Université Bordeaux 0005 * Copyright © 2011 Cisco Systems, Inc. All rights reserved. 0006 * See COPYING in top-level directory. 0007 */ 0008 0009 /** \file 0010 * \brief Macros to help interaction between hwloc and the CUDA Runtime API. 0011 * 0012 * Applications that use both hwloc and the CUDA Runtime API may want to 0013 * include this file so as to get topology information for CUDA devices. 0014 * 0015 */ 0016 0017 #ifndef HWLOC_CUDART_H 0018 #define HWLOC_CUDART_H 0019 0020 #include "hwloc.h" 0021 #include "hwloc/autogen/config.h" 0022 #include "hwloc/helper.h" 0023 #ifdef HWLOC_LINUX_SYS 0024 #include "hwloc/linux.h" 0025 #endif 0026 0027 #include <cuda.h> /* for CUDA_VERSION */ 0028 #include <cuda_runtime_api.h> 0029 0030 0031 #ifdef __cplusplus 0032 extern "C" { 0033 #endif 0034 0035 0036 /** \defgroup hwlocality_cudart Interoperability with the CUDA Runtime API 0037 * 0038 * This interface offers ways to retrieve topology information about 0039 * CUDA devices when using the CUDA Runtime API. 0040 * 0041 * @{ 0042 */ 0043 0044 /** \brief Return the domain, bus and device IDs of the CUDA device whose index is \p idx. 0045 * 0046 * Device index \p idx must match the local machine. 0047 * 0048 * \return 0 on success. 0049 * \return -1 on error, for instance if device information could not be found. 0050 */ 0051 static __hwloc_inline int 0052 hwloc_cudart_get_device_pci_ids(hwloc_topology_t topology __hwloc_attribute_unused, 0053 int idx, int *domain, int *bus, int *dev) 0054 { 0055 cudaError_t cerr; 0056 struct cudaDeviceProp prop; 0057 0058 cerr = cudaGetDeviceProperties(&prop, idx); 0059 if (cerr) { 0060 errno = ENOSYS; 0061 return -1; 0062 } 0063 0064 #if CUDA_VERSION >= 4000 0065 *domain = prop.pciDomainID; 0066 #else 0067 *domain = 0; 0068 #endif 0069 0070 *bus = prop.pciBusID; 0071 *dev = prop.pciDeviceID; 0072 0073 return 0; 0074 } 0075 0076 /** \brief Get the CPU set of processors that are physically 0077 * close to device \p idx. 0078 * 0079 * Store in \p set the CPU-set describing the locality of the CUDA device 0080 * whose index is \p idx. 0081 * 0082 * Topology \p topology and device \p idx must match the local machine. 0083 * I/O devices detection and the CUDA component are not needed in the topology. 0084 * 0085 * The function only returns the locality of the device. 0086 * If more information about the device is needed, OS objects should 0087 * be used instead, see hwloc_cudart_get_device_osdev_by_index(). 0088 * 0089 * This function is currently only implemented in a meaningful way for 0090 * Linux; other systems will simply get a full cpuset. 0091 * 0092 * \return 0 on success. 0093 * \return -1 on error, for instance if device information could not be found. 0094 */ 0095 static __hwloc_inline int 0096 hwloc_cudart_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused, 0097 int idx, hwloc_cpuset_t set) 0098 { 0099 #ifdef HWLOC_LINUX_SYS 0100 /* If we're on Linux, use the sysfs mechanism to get the local cpus */ 0101 #define HWLOC_CUDART_DEVICE_SYSFS_PATH_MAX 128 0102 char path[HWLOC_CUDART_DEVICE_SYSFS_PATH_MAX]; 0103 int domain, bus, dev; 0104 0105 if (hwloc_cudart_get_device_pci_ids(topology, idx, &domain, &bus, &dev)) 0106 return -1; 0107 0108 if (!hwloc_topology_is_thissystem(topology)) { 0109 errno = EINVAL; 0110 return -1; 0111 } 0112 0113 sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.0/local_cpus", (unsigned) domain, (unsigned) bus, (unsigned) dev); 0114 if (hwloc_linux_read_path_as_cpumask(path, set) < 0 0115 || hwloc_bitmap_iszero(set)) 0116 hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology)); 0117 #else 0118 /* Non-Linux systems simply get a full cpuset */ 0119 hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology)); 0120 #endif 0121 return 0; 0122 } 0123 0124 /** \brief Get the hwloc PCI device object corresponding to the 0125 * CUDA device whose index is \p idx. 0126 * 0127 * \return The hwloc PCI device object describing the CUDA device whose index is \p idx. 0128 * \return \c NULL if none could be found. 0129 * 0130 * Topology \p topology and device \p idx must match the local machine. 0131 * I/O devices detection must be enabled in topology \p topology. 0132 * The CUDA component is not needed in the topology. 0133 */ 0134 static __hwloc_inline hwloc_obj_t 0135 hwloc_cudart_get_device_pcidev(hwloc_topology_t topology, int idx) 0136 { 0137 int domain, bus, dev; 0138 0139 if (hwloc_cudart_get_device_pci_ids(topology, idx, &domain, &bus, &dev)) 0140 return NULL; 0141 0142 return hwloc_get_pcidev_by_busid(topology, domain, bus, dev, 0); 0143 } 0144 0145 /** \brief Get the hwloc OS device object corresponding to the 0146 * CUDA device whose index is \p idx. 0147 * 0148 * \return The hwloc OS device object describing the CUDA device whose index is \p idx. 0149 * \return \c NULL if none could be found. 0150 * 0151 * The topology \p topology does not necessarily have to match the current 0152 * machine. For instance the topology may be an XML import of a remote host. 0153 * I/O devices detection and the CUDA component must be enabled in the topology. 0154 * If not, the locality of the object may still be found using 0155 * hwloc_cudart_get_device_cpuset(). 0156 * 0157 * \note The corresponding PCI device object can be obtained by looking 0158 * at the OS device parent object (unless PCI devices are filtered out). 0159 * 0160 * \note This function is identical to hwloc_cuda_get_device_osdev_by_index(). 0161 */ 0162 static __hwloc_inline hwloc_obj_t 0163 hwloc_cudart_get_device_osdev_by_index(hwloc_topology_t topology, unsigned idx) 0164 { 0165 hwloc_obj_t osdev = NULL; 0166 while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) { 0167 if (HWLOC_OBJ_OSDEV_COPROC == osdev->attr->osdev.type 0168 && osdev->name 0169 && !strncmp("cuda", osdev->name, 4) 0170 && atoi(osdev->name + 4) == (int) idx) 0171 return osdev; 0172 } 0173 return NULL; 0174 } 0175 0176 /** @} */ 0177 0178 0179 #ifdef __cplusplus 0180 } /* extern "C" */ 0181 #endif 0182 0183 0184 #endif /* HWLOC_CUDART_H */
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|