4#ifndef ACCEL_CUDA_DEVICE_BUFFER_CUH_
5#define ACCEL_CUDA_DEVICE_BUFFER_CUH_
13#include <cuda_runtime.h>
15#include "cuda/cuda_check.cuh"
33 DeviceBuffer() noexcept = default;
41 explicit DeviceBuffer(std::
size_t count) {
46 CUDA_CHECK(cudaMalloc(&raw, count *
sizeof(T)));
47 Data_ =
static_cast<T*
>(raw);
53 ~DeviceBuffer() { Reset(); }
55 DeviceBuffer(
const DeviceBuffer&) =
delete;
56 DeviceBuffer& operator=(
const DeviceBuffer&) =
delete;
58 DeviceBuffer(DeviceBuffer&& other) noexcept
59 : Data_(std::exchange(other.Data_,
nullptr)),
60 size_(std::exchange(other.size_, 0)) {}
62 DeviceBuffer& operator=(DeviceBuffer&& other)
noexcept {
65 Data_ = std::exchange(other.Data_,
nullptr);
66 size_ = std::exchange(other.size_, 0);
71 T* get() noexcept {
return Data_; }
72 const T* get() const noexcept {
return Data_; }
73 std::size_t size() const noexcept {
return size_; }
74 std::size_t SizeBytes() const noexcept {
return size_ *
sizeof(T); }
75 bool empty() const noexcept {
return size_ == 0; }
76 explicit operator bool() const noexcept {
return Data_ !=
nullptr; }
79 void Reset() noexcept {
80 if (Data_ !=
nullptr) {
81 static_cast<void>(cudaFree(Data_));
99 void CopyFromHost(
const T* host_src, std::size_t count,
100 cudaStream_t stream =
nullptr) {
101 RequireCapacity(count);
105 CUDA_CHECK(cudaMemcpyAsync(Data_, host_src, count *
sizeof(T),
106 cudaMemcpyHostToDevice, stream));
110 void CopyFromHost(
const std::vector<T>& host_src,
111 cudaStream_t stream =
nullptr) {
112 CopyFromHost(host_src.data(), host_src.size(), stream);
123 void CopyToHost(T* host_dst, std::size_t count,
124 cudaStream_t stream =
nullptr)
const {
125 RequireCapacity(count);
129 CUDA_CHECK(cudaMemcpyAsync(host_dst, Data_, count *
sizeof(T),
130 cudaMemcpyDeviceToHost, stream));
135 std::vector<T> ToHost(cudaStream_t stream =
nullptr)
const {
136 std::vector<T> host(size_);
137 CopyToHost(host.data(), size_, stream);
138 CUDA_CHECK(cudaStreamSynchronize(stream));
144 void Zero(cudaStream_t stream =
nullptr) {
148 CUDA_CHECK(cudaMemsetAsync(Data_, 0, SizeBytes(), stream));
152 void RequireCapacity(std::size_t count)
const {
154 throw std::out_of_range(
155 "DeviceBuffer transfer of " + std::to_string(count) +
156 " elements exceeds capacity " + std::to_string(size_));
161 std::size_t size_ = 0;