Loading...
Searching...
No Matches
buffer.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * GPUDeviceBuffer — RAII wrapper for GPU unified (managed) memory.
5 *
6 * Templated on element type T. Uses GPUDeviceBackend::allocate_unified()
7 * for allocation and GPUDeviceBackend::deallocate() for deallocation.
8 *
9 * Stores a std::shared_ptr<GPUDeviceBackend> to guarantee that the
10 * backend outlives all buffers — critical for correct destruction order.
11 *
12 * No CUDA headers. No Metal headers. Uses the backend abstraction only.
13 */
14
16
17#include <complex>
18#include <cstddef>
19#include <memory>
20#include <stdexcept>
21#include <utility>
22
23/**
24 * Layout compatibility assertions for GPU interop — complex types must be
25 * layout-compatible with float[2] / double[2] for BLAS and FFT libraries.
26 */
27static_assert(sizeof(std::complex<float>) == 2 * sizeof(float),
28 "complex<float> must be layout-compatible with float[2]");
29static_assert(sizeof(std::complex<double>) == 2 * sizeof(double),
30 "complex<double> must be layout-compatible with double[2]");
31
32namespace q3 {
33namespace execution {
34namespace gpu {
35namespace device {
36
37template <typename T> class GPUDeviceBuffer {
38 public:
39 /**
40 * Construct a buffer of the given number of elements.
41 *
42 * @param element_count Number of elements of type T to allocate.
43 * If zero, no allocation is performed and data() returns nullptr.
44 * @param backend Shared pointer to the GPU device backend.
45 * Must not be null.
46 * @throws std::runtime_error If allocation fails (e.g., out of GPU memory).
47 */
48 GPUDeviceBuffer(size_t element_count, std::shared_ptr<GPUDeviceBackend> backend)
49 : element_count_(element_count), backend_(std::move(backend)), data_(nullptr) {
50 if (!backend_) {
51 throw std::runtime_error("GPUDeviceBuffer: backend must not be null");
52 }
53 if (element_count_ > 0) {
54 data_ = static_cast<T*>(backend_->allocate_unified(element_count_ * sizeof(T)));
55 }
56 }
57
58 // Non-copyable — unified memory pointers cannot be meaningfully duplicated.
61
62 /**
63 * Move constructor. Transfers ownership of the allocation.
64 * The source buffer is left in a valid but empty state.
65 */
67 : element_count_(other.element_count_)
68 , backend_(std::move(other.backend_))
69 , data_(other.data_) {
70 other.element_count_ = 0;
71 other.data_ = nullptr;
72 }
73
74 /**
75 * Move assignment operator. Releases the current allocation (if any)
76 * before taking ownership of the source's allocation.
77 */
79 if (this != &other) {
80 release();
81 element_count_ = other.element_count_;
82 backend_ = std::move(other.backend_);
83 data_ = other.data_;
84 other.element_count_ = 0;
85 other.data_ = nullptr;
86 }
87 return *this;
88 }
89
91 release();
92 }
93
94 /**
95 * Raw pointer to the underlying unified memory.
96 * Returns nullptr if the buffer was zero-sized or moved-from.
97 */
98 T* data() noexcept {
99 return data_;
100 }
101
102 /**
103 * Raw const pointer to the underlying unified memory.
104 */
105 const T* data() const noexcept {
106 return data_;
107 }
108
109 /**
110 * Number of elements of type T in this buffer.
111 */
112 size_t size() const noexcept {
113 return element_count_;
114 }
115
116 /**
117 * Total size of the allocation in bytes.
118 */
119 size_t size_bytes() const noexcept {
120 return element_count_ * sizeof(T);
121 }
122
123 private:
124 void release() noexcept {
125 if (data_ && backend_) {
126 backend_->deallocate(data_);
127 data_ = nullptr;
128 }
129 element_count_ = 0;
130 }
131
132 size_t element_count_;
133 std::shared_ptr<GPUDeviceBackend> backend_;
134 T* data_;
135};
136
137} // namespace device
138} // namespace gpu
139} // namespace execution
140} // namespace q3
GPUDeviceBuffer & operator=(const GPUDeviceBuffer &)=delete
const T * data() const noexcept
Definition buffer.hpp:105
GPUDeviceBuffer(size_t element_count, std::shared_ptr< GPUDeviceBackend > backend)
Definition buffer.hpp:48
GPUDeviceBuffer & operator=(GPUDeviceBuffer &&other) noexcept
Definition buffer.hpp:78
GPUDeviceBuffer(const GPUDeviceBuffer &)=delete
GPUDeviceBuffer(GPUDeviceBuffer &&other) noexcept
Definition buffer.hpp:66