11#ifndef NANOVDB_CUDA_DEVICEMESH_H_HAS_BEEN_INCLUDED
12#define NANOVDB_CUDA_DEVICEMESH_H_HAS_BEEN_INCLUDED
19#ifdef NANOVDB_USE_NCCL
52 cudaStream_t
stream = cudaStream_t(0);
58 using DeviceVecT = std::vector<DeviceNode>;
59 using const_iterator = DeviceVecT::const_iterator;
60 using size_type = DeviceVecT::size_type;
78 size_type
deviceCount()
const {
return mDeviceNodes.size(); };
84 const_iterator
begin()
const {
return mDeviceNodes.begin(); };
86 const_iterator
end()
const {
return mDeviceNodes.end(); };
88#ifdef NANOVDB_USE_NCCL
90 ncclComm_t comm(
int deviceId)
const {
return mComms[deviceId]; }
94 bool canAccessPeer(
int deviceId,
int peerId)
const {
return mConnectivity[deviceId][peerId] & (1 << cudaDevP2PAttrAccessSupported); }
98 bool hasManagedMemory(
int deviceId)
const {
99 int managedMemoryValue = 0;
100 cudaDeviceGetAttribute(&managedMemoryValue, cudaDevAttrManagedMemory, deviceId);
101 return static_cast<bool>(managedMemoryValue);
104 DeviceVecT mDeviceNodes;
106#ifdef NANOVDB_USE_NCCL
107 std::vector<ncclComm_t> mComms;
109 std::vector<std::vector<uint32_t>> mConnectivity;
119 for (
int deviceId = 0; deviceId <
deviceCount; ++deviceId) {
121 cudaSetDevice(deviceId);
123 cudaStreamCreate(&stream);
124 mDeviceNodes.push_back({deviceId, stream});
127#ifdef NANOVDB_USE_NCCL
129 ncclCommInitAll(mComms.data(),
deviceCount,
nullptr);
133 for (
const auto& deviceNode : mDeviceNodes) {
135 for (
const auto& peerNode : mDeviceNodes) {
136 mConnectivity[deviceNode.id][peerNode.id] = 0;
137 if (deviceNode.id != peerNode.id) {
138 int peerAccessSupportedValue = 0;
139 cudaDeviceGetP2PAttribute(&peerAccessSupportedValue, cudaDevP2PAttrAccessSupported, deviceNode.id, peerNode.id);
140 if (peerAccessSupportedValue) {
141 mConnectivity[deviceNode.id][peerNode.id] |= (1 << cudaDevP2PAttrAccessSupported);
149 : mDeviceNodes(std::move(other.mDeviceNodes)),
150#ifdef NANOVDB_USE_NCCL
151 mComms(std::move(other.mComms)),
153 mConnectivity(std::move(other.mConnectivity))
161#ifdef NANOVDB_USE_NCCL
162 std::for_each(mComms.begin(), mComms.end(), [](ncclComm_t comm) {
163 ncclCommFinalize(comm);
164 ncclCommDestroy(comm);
168 std::for_each(mDeviceNodes.begin(), mDeviceNodes.end(), [](
DeviceNode& deviceNode) {
169 cudaSetDevice(deviceNode.id);
170 cudaStreamDestroy(deviceNode.stream);
176 mDeviceNodes = std::move(other.mDeviceNodes);
177#ifdef NANOVDB_USE_NCCL
178 mComms = std::move(other.mComms);
180 mConnectivity = std::move(other.mConnectivity);
188 void* entryPoint =
nullptr;
189#if CUDART_VERSION >= 12500
190 cudaDriverEntryPointQueryResult queryResult = cudaDriverEntryPointSymbolNotFound;
191 cudaCheck(cudaGetDriverEntryPointByVersion(
"cuMemGetAllocationGranularity", &entryPoint, 12000, cudaEnableDefault, &queryResult));
193#elif CUDART_VERSION >= 12000
194 cudaDriverEntryPointQueryResult queryResult = cudaDriverEntryPointSymbolNotFound;
195 cudaCheck(cudaGetDriverEntryPoint(
"cuMemGetAllocationGranularity", &entryPoint, cudaEnableDefault, &queryResult));
198 cudaCheck(cudaGetDriverEntryPoint(
"cuMemGetAllocationGranularity", &entryPoint, cudaEnableDefault));
208 using FuncT = CUresult(
size_t*,
const CUmemAllocationProp*, CUmemAllocationGranularity_flags);
212 CUmemAllocationProp prop = {};
213 prop.type = CU_MEM_ALLOCATION_TYPE_PINNED;
214 prop.location.type = CU_MEM_LOCATION_TYPE_DEVICE;
215 size_t minGranularity = 0;
216 for (
const auto& node : mesh) {
217 prop.location.id = node.id;
218 size_t granularity = 0;
219 (*functPtr)(&granularity, &prop, CU_MEM_ALLOC_GRANULARITY_MINIMUM);
220 if (minGranularity < granularity) minGranularity = granularity;
222 return minGranularity;
This class wraps a vector of per-device IDs and CUDA streams and holds inter-device connectivity info...
Definition DeviceMesh.h:57
size_type deviceCount() const
Returns the number of devices.
Definition DeviceMesh.h:78
~DeviceMesh()
Destroys the per-device CUDA stream and finalizes and destroys the per-device NCCL communicators.
Definition DeviceMesh.h:157
const_iterator begin() const
Returns an iterator to the first device node.
Definition DeviceMesh.h:84
DeviceMesh & operator=(const DeviceMesh &)=delete
Disallow copy-assignment.
const DeviceNode & operator[](int deviceId) const
Returns a const reference to the DeviceNode for a particular device.
Definition DeviceMesh.h:81
DeviceMesh(const DeviceMesh &)=delete
Disallow copy-construction.
const_iterator end() const
Returns an iterator past the last device node.
Definition DeviceMesh.h:86
bool canAccessPeer(int deviceId, int peerId) const
Returns whether or not peer to peer access is supported between two devices.
Definition DeviceMesh.h:94
DeviceMesh()
Constructs a device mesh for all devices on the host and initializes a CUDA stream (and NCCL communic...
Definition DeviceMesh.h:112
RAII class that caches/restores the current device at construction/destruction.
Definition DeviceMesh.h:30
DeviceGuard()
Definition DeviceMesh.h:32
DeviceGuard(DeviceGuard &&other)=delete
DeviceGuard is not copyable nor movable.
DeviceGuard & operator=(const DeviceGuard &)=delete
DeviceGuard is not copyable nor movable.
DeviceGuard & operator=(DeviceGuard &&other)=delete
DeviceGuard is not copyable nor movable.
~DeviceGuard()
Definition DeviceMesh.h:33
DeviceGuard(const DeviceGuard &)=delete
DeviceGuard is not copyable nor movable.
Definition VoxToNanoVDB.h:15
Definition GridHandle.h:37
void * queryAllocationGranularityEntryPoint()
Definition DeviceMesh.h:186
Definition GridHandle.h:37
size_t minDevicePageSize(const DeviceMesh &mesh)
Returns the minimum page size (in bytes) across all devices on the system.
Definition DeviceMesh.h:206
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
POD struct representing a device id and a stream on that device.
Definition DeviceMesh.h:50
cudaStream_t stream
Definition DeviceMesh.h:52