OpenVDB 13.1.0
Loading...
Searching...
No Matches
DeviceStreamMap.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4/*!
5 \file DeviceStreamMap.h
6
7 \author Ken Museth
8
9 \date October 15, 2024
10
11 \brief nanovdb::cuda::DeviceStreamMap maps device IDs to CUDA streams,
12 which is useful for multi-GPU applications.
13*/
14
15#ifndef NANOVDB_CUDA_DEVICESTREAMMAP_H_HAS_BEEN_INCLUDED
16#define NANOVDB_CUDA_DEVICESTREAMMAP_H_HAS_BEEN_INCLUDED
17
18#include <cuda.h>
19#include <map>
20#include <vector>
21#include <nanovdb/util/cuda/Util.h>// for cudaCheck, deviceCount etc
22
23namespace nanovdb {// ================================================================
24
25namespace cuda {// ===================================================================
26
27/// @brief map from a device ID to an associated cuda stream. Useful for multi-GPU applications.
28class DeviceStreamMap : public std::map<int, cudaStream_t>
29{
30 using FuncT = CUresult(size_t*, const CUmemAllocationProp*, CUmemAllocationGranularity_flags);
31 FuncT *mFunctPtr;
32
33public:
34
35 enum DeviceType { Any = 0, PeerToPeer = 1, Unified = 3 };
36
37 /// @brief Initiates a map between CUDA device IDs and corresponding streams that satisfy certain constraints.
38 /// All devices should be able to access memory on all the other devices!
39 /// @param t Type of device to include in map. Any means all available devices, PeerToPeer means only devices that
40 /// access all another devices are included, and Unified means all devices support unified memory, concurrent access,
41 /// and can be access by all other devices.
42 /// @param exclude optional list of device IDs to exclude from the map
43 /// @param verbose 0 means quiet, 1 means print if a device is ignores and 2 means print is a device is included
44 DeviceStreamMap(DeviceType t = DeviceType::Unified, std::vector<int> exclude = {}, int verbose = 0);
45
46 /// @brief Destructor
48
49 /// @brief returns the minimum page size of all the devices in this map
50 size_t getMinPageSize() const;
51
52 /// @brief Print information about all the devices included in this map
53 void printDevInfo(std::FILE* file = stdout) const {for (auto &p : *this) util::cuda::printDevInfo(p.first, nullptr, file);}
54
55 /// @brief Returns the number of device associated with this map
56 int deviceCount() const {return this->size();}
57
58};// DeviceStreamMap
59
60DeviceStreamMap::DeviceStreamMap(DeviceType t, std::vector<int> exclude, int verbose)
61{
62 std::initializer_list<cudaDeviceAttr> filter = {cudaDevAttrUnifiedAddressing, cudaDevAttrConcurrentManagedAccess};
63 const int devCount = util::cuda::deviceCount(), current = util::cuda::currentDevice();
64 for (int dev = 0; dev < devCount; ++dev) {
65 int check = 1;
66 for (auto it=exclude.begin(); check && it!=exclude.end(); ++it) if (dev == *it) check = 0;
67 for (auto it=filter.begin(); (t&2) && check && it!=filter.end(); ++it) cudaCheck(cudaDeviceGetAttribute( &check, *it, dev));
68 for (auto it= this->begin(); (t&1) && check && it!= this->end(); ++it) cudaCheck(cudaDeviceCanAccessPeer(&check, dev, it->first));
69 if (check) {
70 cudaCheck(cudaSetDevice(dev));
71 cudaStream_t stream;
72 cudaCheck(cudaStreamCreate(&stream));
73 if (verbose>1) util::cuda::printDevInfo(dev, "Using");
74 (*this)[dev] = stream;
75 } else if (verbose) util::cuda::printDevInfo(dev, "Ignoring");
76 }
77 cudaCheck(cudaSetDevice(current));// reset to the previous device
78
79 void* entryPoint = nullptr;
80#if CUDART_VERSION >= 13000
81 cudaDriverEntryPointQueryResult queryResult;
82 cudaCheck(cudaGetDriverEntryPointByVersion("cuMemGetAllocationGranularity", &entryPoint, 13000, cudaEnableDefault, &queryResult));
83 NANOVDB_ASSERT(queryResult == cudaDriverEntryPointSuccess);
84#elif CUDART_VERSION >= 12000// queryResult argument was added in CUDA 12
85 cudaDriverEntryPointQueryResult queryResult;
86 cudaCheck(cudaGetDriverEntryPoint("cuMemGetAllocationGranularity", &entryPoint, cudaEnableDefault, &queryResult));
87 NANOVDB_ASSERT(queryResult == cudaDriverEntryPointSuccess);
88#else
89 cudaCheck(cudaGetDriverEntryPoint("cuMemGetAllocationGranularity", &entryPoint, cudaEnableDefault));
90#endif
91 mFunctPtr = reinterpret_cast<FuncT*>(entryPoint);
92}// DeviceStreamMap::DeviceStreamMap
93
95{
96 const int current = util::cuda::currentDevice();
97 for (auto& [device, stream] : *this) {
98 cudaCheck(cudaSetDevice(device));
99 cudaCheck(cudaStreamDestroy(stream));
100 }
101 cudaCheck(cudaSetDevice(current));// reset to the previous device
102}
103
105{
106 NANOVDB_ASSERT(mFunctPtr);
107 CUmemAllocationProp prop = {};
108 prop.type = CU_MEM_ALLOCATION_TYPE_PINNED;
109 prop.location.type = CU_MEM_LOCATION_TYPE_DEVICE;
110 size_t minGranularity = 0;
111 for (auto it = this->begin(); it!=this->end(); ++it) {
112 prop.location.id = it->first;
113 size_t granularity = 0;
114 (*mFunctPtr)(&granularity, &prop, CU_MEM_ALLOC_GRANULARITY_MINIMUM);
115 if (minGranularity < granularity) minGranularity = granularity;
116 }
117 return minGranularity;
118}// DeviceStreamMap::getMinPageSize
119
120}// namespace cuda
121
122}// namespace nanovdb
123
124#endif // end of NANOVDB_CUDA_DEVICESTREAMMAP_H_HAS_BEEN_INCLUDED
DeviceStreamMap(DeviceType t=DeviceType::Unified, std::vector< int > exclude={}, int verbose=0)
Initiates a map between CUDA device IDs and corresponding streams that satisfy certain constraints....
Definition DeviceStreamMap.h:60
int deviceCount() const
Returns the number of device associated with this map.
Definition DeviceStreamMap.h:56
size_t getMinPageSize() const
returns the minimum page size of all the devices in this map
Definition DeviceStreamMap.h:104
void printDevInfo(std::FILE *file=stdout) const
Print information about all the devices included in this map.
Definition DeviceStreamMap.h:53
~DeviceStreamMap()
Destructor.
Definition DeviceStreamMap.h:94
DeviceType
Definition DeviceStreamMap.h:35
@ PeerToPeer
Definition DeviceStreamMap.h:35
@ Unified
Definition DeviceStreamMap.h:35
@ Any
Definition DeviceStreamMap.h:35
Definition GridHandle.h:37
int deviceCount()
Returns the number of devices with compute capability greater or equal to 1.0 that are available for ...
Definition Util.h:190
int currentDevice()
Returns the ID of the current device.
Definition Util.h:181
void printDevInfo(int device, const char *preMsg=nullptr, std::FILE *file=stderr)
Print information about a specific device.
Definition Util.h:201
Defines a simple memory pool used to call cub functions that use dynamic temporary storage.
Definition GridHandle.h:31
#define NANOVDB_ASSERT(x)
Definition Util.h:53
Cuda specific utility functions.
#define cudaCheck(ans)
Definition Util.h:49