17#ifndef NANOVDB_CUDA_DEVICEBUFFER_H_HAS_BEEN_INCLUDED
18#define NANOVDB_CUDA_DEVICEBUFFER_H_HAS_BEEN_INCLUDED
49 void *mCpuData, **mGpuData;
50 int mDeviceCount, mManaged;
51 cudaEvent_t *mEvents =
nullptr;
58 void init(uint64_t
size,
int device, cudaStream_t stream);
68 void freeDualDeviceBuffers(cudaStream_t stream)
72 for (
int i = 0; i < mDeviceCount; ++i) {
74 const cudaStream_t freeStream = (i == current) ? stream : cudaStream_t{0};
75 if (i != current)
cudaCheck(cudaSetDevice(i));
78 if (i != current)
cudaCheck(cudaSetDevice(current));
80 if (mEvents && mEvents[i]) {
89 using PtrT = std::shared_ptr<DualDeviceBuffer>;
92 DualDeviceBuffer() : mSize(0), mCpuData(nullptr), mGpuData(nullptr), mDeviceCount(0), mManaged(0){}
100 this->init(
size, device, stream);
109 int device = cudaCpuDeviceId;
110 if (!host)
cudaCheck(cudaGetDevice(&device));
111 this->init(
size, device,
reinterpret_cast<cudaStream_t
>(stream));
125 cudaCheck(cudaGetDeviceCount(&mDeviceCount));
126 mGpuData =
new void*[mDeviceCount]();
131 mGpuData[device] = gpuData;
144 cudaCheck(cudaGetDeviceCount(&mDeviceCount));
145 mGpuData =
new void*[mDeviceCount]();
146 for (
auto &p : list) {
149 mGpuData[p.first] = p.second;
159 , mCpuData(other.mCpuData)
160 , mGpuData(other.mGpuData)
161 , mDeviceCount(other.mDeviceCount)
162 , mManaged(other.mManaged)
163 , mEvents(other.mEvents)
165 other.mCpuData = other.mGpuData =
nullptr;
166 other.mEvents =
nullptr;
167 other.mSize = other.mDeviceCount = other.mManaged = 0;
178 cudaCheck(cudaMemcpy(mCpuData, buffer.
data(), mSize, cudaMemcpyHostToHost));
179 }
else if (mGpuData[device]) {
180 cudaCheck(cudaMemcpyAsync(mGpuData[device], buffer.
data(), mSize, cudaMemcpyHostToDevice, stream));
228 static PtrT createPtr(uint64_t
size,
void* cpuData,
void* gpuData) {
return std::make_shared<DualDeviceBuffer>(
size, cpuData, gpuData);}
229 static PtrT createPtr(uint64_t
size,
void* cpuData, std::initializer_list<std::pair<int,void*>> list) {
return std::make_shared<DualDeviceBuffer>(
size, cpuData, list);}
230 static PtrT createPtr(
const HostBuffer& buffer,
int device = cudaCpuDeviceId, cudaStream_t stream = 0) {
return std::make_shared<DualDeviceBuffer>(buffer, device, stream);}
245 void*
data()
const {
return mCpuData; }
252 template <
typename T>
253 T*
data(ptrdiff_t count = 0,
int device = cudaCpuDeviceId)
const
255 NANOVDB_ASSERT(device >= cudaCpuDeviceId && device < mDeviceCount);
256 void *ptr = device == cudaCpuDeviceId ? mCpuData : mGpuData[device];
257 return ptr ?
reinterpret_cast<T*
>(ptr) + count :
nullptr;
264 void*
data(ptrdiff_t byteOffset,
int device = cudaCpuDeviceId)
const
266 NANOVDB_ASSERT(device >= cudaCpuDeviceId && device < mDeviceCount);
267 void *ptr = device == cudaCpuDeviceId ? mCpuData : mGpuData[device];
268 return ptr ?
reinterpret_cast<char*
>(ptr) + byteOffset :
nullptr;
282 if (mEvents && mEvents[device])
cudaCheck(cudaStreamWaitEvent(stream, mEvents[device], 0));
306 if (!mEvents)
return;
307 if (mEvents[device] ==
nullptr) {
310 if (current != device)
cudaCheck(cudaSetDevice(device));
311 cudaCheck(cudaEventCreateWithFlags(&mEvents[device], cudaEventDisableTiming));
312 if (current != device)
cudaCheck(cudaSetDevice(current));
316 cudaCheck(cudaStreamWaitEvent(stream, mEvents[device], 0));
318 cudaCheck(cudaEventRecord(mEvents[device], stream));
328 return mGpuData[device];
334 int device = cudaCpuDeviceId;
347 void deviceUpload(
int device = 0, cudaStream_t stream = 0,
bool sync =
true);
366 void deviceDownload(
int device = 0, cudaStream_t stream = 0,
bool sync =
true);
380 uint64_t
size()
const {
return mSize; }
385 int count = mCpuData ? 1 : 0;
386 for (
int i=0; i<mDeviceCount; ++i)
if (mGpuData[i]) ++count;
394 bool empty()
const {
return mSize == 0; }
403 void clear(cudaStream_t stream = 0);
418using DeviceBuffer [[deprecated(
"grid storage is moving to cuda::Buffer<std::byte>: build into a host handle and use cuda::copyTo (cuda/HandleStorage.h, host-callable); see the CUDA examples")]] =
DualDeviceBuffer;
424 if (
this == &other)
return *
this;
427 this->freeDualDeviceBuffers(cudaStream_t{0});
432 mCpuData = other.mCpuData;
433 mGpuData = other.mGpuData;
434 mDeviceCount = other.mDeviceCount;
435 mManaged = other.mManaged;
436 mEvents = other.mEvents;
437 other.mCpuData =
nullptr;
438 other.mGpuData =
nullptr;
439 other.mEvents =
nullptr;
441 other.mDeviceCount = 0;
446inline void DualDeviceBuffer::init(uint64_t size,
int device, cudaStream_t stream)
449 cudaCheck(cudaGetDeviceCount(&mDeviceCount));
450 mGpuData =
new void*[mDeviceCount]();
451 mEvents =
new cudaEvent_t[mDeviceCount]();
452 NANOVDB_ASSERT(device >= cudaCpuDeviceId && device < mDeviceCount);
453 if (device == cudaCpuDeviceId) {
455 checkPtr(mCpuData,
"cuda::DualDeviceBuffer::init: failed to allocate host buffer");
458 checkPtr(mGpuData[device],
"cuda::DualDeviceBuffer::init: failed to allocate device buffer");
468 checkPtr(mCpuData,
"uninitialized cpu source data");
469 if (mGpuData[device] ==
nullptr) {
470 if (mManaged==0)
throw std::runtime_error(
"DualDeviceBuffer::deviceUpload called on externally managed memory that wasn\'t allocated.");
473 checkPtr(mGpuData[device],
"uninitialized gpu destination data");
477 cudaCheck(cudaMemcpyAsync(mGpuData[device], mCpuData, mSize, cudaMemcpyHostToDevice, stream));
479 if (sync)
cudaCheck(cudaStreamSynchronize(stream));
485 cudaGetDevice(&device);
492 checkPtr(mGpuData[device],
"uninitialized gpu source data");
493 if (mCpuData ==
nullptr) {
494 if (mManaged==0)
throw std::runtime_error(
"DualDeviceBuffer::deviceDownload called on uninitialized cpu destination memory that is externally managed.");
495 cudaCheck(cudaMallocHost((
void**)&mCpuData, mSize));
497 checkPtr(mCpuData,
"uninitialized cpu destination data");
499 cudaCheck(cudaMemcpyAsync(mCpuData, mGpuData[device], mSize, cudaMemcpyDeviceToHost, stream));
501 if (sync)
cudaCheck(cudaStreamSynchronize(stream));
515 this->freeDualDeviceBuffers(stream);
529using CudaDeviceBuffer [[deprecated(
"Use GridHandle<cuda::Buffer<std::byte>> with cuda::copyTo instead")]] =
cuda::DualDeviceBuffer;
HostBuffer - a buffer that contains a shared or private bump pool to either externally or internally ...
#define checkPtr(ptr, msg)
Definition HostBuffer.h:92
This is a buffer that contains a shared or private pool to either externally or internally managed ho...
Definition HostBuffer.h:181
const void * data() const
Retuns a pointer to the raw memory buffer managed by this allocator.
Definition HostBuffer.h:257
Simple memory buffer using un-managed pinned host memory when compiled with NVCC. Obviously this clas...
Definition DeviceBuffer.h:47
void recordUse(int device, cudaStream_t stream)
Record that this buffer's device data was just used on stream, so that the buffer's device frees (des...
Definition DeviceBuffer.h:304
~DualDeviceBuffer()
Destructor frees memory on both the host and device.
Definition DeviceBuffer.h:187
uint64_t capacity() const
Definition DeviceBuffer.h:381
DualDeviceBuffer(uint64_t size, bool host, void *stream)
Constructor.
Definition DeviceBuffer.h:107
static PtrT createPtr(uint64_t size, void *cpuData, void *gpuData)
Factory methods that create a shared pointer to an DualDeviceBuffer instance.
Definition DeviceBuffer.h:228
DualDeviceBuffer(uint64_t size, void *cpuData, std::initializer_list< std::pair< int, void * > > list)
Constructor for externally managed host and multiple device buffers.
Definition DeviceBuffer.h:138
void deviceUpload(int device=0, cudaStream_t stream=0, bool sync=true)
Uploads buffer on the host to a specific device. If it doesn't exist it's created first.
Definition DeviceBuffer.h:465
T * data(ptrdiff_t count=0, int device=cudaCpuDeviceId) const
Returns an offset pointer of a specific type from the allocated host memory.
Definition DeviceBuffer.h:253
static DualDeviceBuffer create(const HostBuffer &buffer, int device=cudaCpuDeviceId, cudaStream_t stream=0)
Static factory method that returns an instance of this buffer constructed from a HostBuffer.
Definition DeviceBuffer.h:221
void clear(void *stream)
Definition DeviceBuffer.h:404
DualDeviceBuffer(uint64_t size, int device=cudaCpuDeviceId, cudaStream_t stream=0)
Constructor with a specified device and size.
Definition DeviceBuffer.h:98
void * data(ptrdiff_t byteOffset, int device=cudaCpuDeviceId) const
Returns a byte offset void pointer from the allocated host memory.
Definition DeviceBuffer.h:264
void deviceUpload(void *stream, bool sync)
Definition DeviceBuffer.h:357
void * deviceData() const
Retuns a raw pointer to the current device/GPU buffer managed by this allocator.
Definition DeviceBuffer.h:333
bool empty() const
Returns true if this allocator is empty, i.e. has no allocated memory.
Definition DeviceBuffer.h:394
int bufferCount() const
Returns the number of buffers that are not NULL.
Definition DeviceBuffer.h:384
void deviceUpload(int device, void *stream, bool sync)
Definition DeviceBuffer.h:348
uint64_t size() const
Returns the size in bytes of the raw memory buffer managed by this allocator.
Definition DeviceBuffer.h:380
std::shared_ptr< DualDeviceBuffer > PtrT
Definition DeviceBuffer.h:89
void clear(cudaStream_t stream=0)
De-allocate all memory managed by this allocator and set all pointers to NULL.
Definition DeviceBuffer.h:511
int deviceCount() const
Definition DeviceBuffer.h:390
DualDeviceBuffer(DualDeviceBuffer &&other) noexcept
Move copy-constructor.
Definition DeviceBuffer.h:157
DualDeviceBuffer()
Default constructor of an empty buffer.
Definition DeviceBuffer.h:92
void * deviceData(int device) const
Retuns a raw pointer to the specified device/GPU buffer managed by this allocator.
Definition DeviceBuffer.h:326
void * data() const
Retuns a raw void pointer to the host/CPU buffer managed by this allocator.
Definition DeviceBuffer.h:245
static DualDeviceBuffer create(uint64_t size, const DualDeviceBuffer *dummy=nullptr, int device=cudaCpuDeviceId, cudaStream_t stream=0)
Static factory method that returns an instance of this buffer.
Definition DeviceBuffer.h:202
DualDeviceBuffer(const HostBuffer &buffer, int device=cudaCpuDeviceId, cudaStream_t stream=0)
Copy-constructor from a HostBuffer.
Definition DeviceBuffer.h:174
static PtrT createPtr(uint64_t size, void *cpuData, std::initializer_list< std::pair< int, void * > > list)
Factory methods that create a shared pointer to an DualDeviceBuffer instance.
Definition DeviceBuffer.h:229
void orderAfterPriorUses(int device, cudaStream_t stream) const
Order work subsequently issued on stream after every prior use of this device buffer,...
Definition DeviceBuffer.h:280
bool isEmpty() const
Returns true if this allocator is empty, i.e. has no allocated memory.
Definition DeviceBuffer.h:395
static DualDeviceBuffer create(uint64_t size, void *cpuData, std::initializer_list< std::pair< int, void * > > list)
Static factory method that returns an instance of this buffer that wraps externally managed host and ...
Definition DeviceBuffer.h:215
void deviceDownload(int device, void *stream, bool sync)
Definition DeviceBuffer.h:367
static DualDeviceBuffer create(uint64_t size, void *cpuData, void *gpuData)
Static factory method that returns an instance of this buffer that wraps externally managed memory.
Definition DeviceBuffer.h:209
static PtrT createPtr(const HostBuffer &buffer, int device=cudaCpuDeviceId, cudaStream_t stream=0)
Factory methods that create a shared pointer to an DualDeviceBuffer instance.
Definition DeviceBuffer.h:230
DualDeviceBuffer(const DualDeviceBuffer &)=delete
Disallow copy-construction.
static PtrT createPtr(uint64_t size, const DualDeviceBuffer *=nullptr, int device=cudaCpuDeviceId, cudaStream_t stream=0)
Factory methods that create a shared pointer to an DualDeviceBuffer instance.
Definition DeviceBuffer.h:227
void deviceDownload(int device=0, cudaStream_t stream=0, bool sync=true)
Download data from a specified device to the host. If the host buffer des not exist it will first be ...
Definition DeviceBuffer.h:489
DualDeviceBuffer & operator=(const DualDeviceBuffer &)=delete
Disallow copy assignment operation.
static DualDeviceBuffer create(uint64_t size, const DualDeviceBuffer *dummy, bool host, void *stream)
Static factory method that return an instance of this buffer.
Definition DeviceBuffer.h:195
DualDeviceBuffer(uint64_t size, void *cpuData, void *gpuData)
Constructor for externally managed host and device buffers.
Definition DeviceBuffer.h:120
Definition GridHandle.h:37
cudaError_t freeAsync(void *d_ptr, cudaStream_t)
Wrapper forced to synchronous cudaFree; see the mode comment above. The trailing stream argument is a...
Definition Util.h:127
cudaError_t mallocAsync(void **d_ptr, size_t size, cudaStream_t)
Wrapper forced to synchronous cudaMalloc; see the mode comment above. The trailing stream argument is...
Definition Util.h:120
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
static constexpr bool hasDeviceDual
Definition DeviceBuffer.h:534
Definition HostBuffer.h:101