OpenPFC  0.1.4
Phase Field Crystal simulation framework
Loading...
Searching...
No Matches
gpu_vector.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2025 VTT Technical Research Centre of Finland Ltd
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
40#ifndef PFC_GPU_VECTOR_HPP
41#define PFC_GPU_VECTOR_HPP
42
43#include <cstddef>
44#include <stdexcept>
45#include <vector>
46
47// Only include CUDA headers if CUDA is enabled
48#if defined(OpenPFC_ENABLE_CUDA)
49#include <cuda_runtime.h>
50#define PFC_GPU_CUDA_AVAILABLE 1
51#else
52#define PFC_GPU_CUDA_AVAILABLE 0
53#endif
54
55namespace pfc {
56namespace gpu {
57
73template <typename T> class GPUVector {
74private:
75#if PFC_GPU_CUDA_AVAILABLE
76 T *m_device_ptr = nullptr;
77#else
78 void *m_device_ptr = nullptr; // Placeholder for non-CUDA builds
79#endif
80 size_t m_size = 0;
81
82public:
94 explicit GPUVector(size_t size) : m_size(size) {
95#if PFC_GPU_CUDA_AVAILABLE
96 if (size > 0) {
97 cudaError_t err = cudaMalloc(&m_device_ptr, size * sizeof(T));
98 if (err != cudaSuccess) {
99 throw std::runtime_error("Failed to allocate GPU memory: " +
100 std::string(cudaGetErrorString(err)));
101 }
102 }
103#else
104 // On non-CUDA systems, this should not be called
105 // But we provide a stub to allow compilation
106 if (size > 0) {
107 throw std::runtime_error("GPUVector: CUDA not enabled at compile time");
108 }
109#endif
110 }
111
116#if PFC_GPU_CUDA_AVAILABLE
117 if (m_device_ptr) {
118 cudaFree(m_device_ptr);
119 }
120#endif
121 }
122
123 // No copy (would need deep copy)
124 GPUVector(const GPUVector &) = delete;
125 GPUVector &operator=(const GPUVector &) = delete;
126
131 : m_device_ptr(other.m_device_ptr), m_size(other.m_size) {
132 other.m_device_ptr = nullptr;
133 other.m_size = 0;
134 }
135
140 if (this != &other) {
141#if PFC_GPU_CUDA_AVAILABLE
142 if (m_device_ptr) cudaFree(m_device_ptr);
143#endif
144 m_device_ptr = other.m_device_ptr;
145 m_size = other.m_size;
146 other.m_device_ptr = nullptr;
147 other.m_size = 0;
148 }
149 return *this;
150 }
151
160 T *data() {
161#if PFC_GPU_CUDA_AVAILABLE
162 return m_device_ptr;
163#else
164 return nullptr;
165#endif
166 }
167
171 const T *data() const {
172#if PFC_GPU_CUDA_AVAILABLE
173 return m_device_ptr;
174#else
175 return nullptr;
176#endif
177 }
178
182 size_t size() const { return m_size; }
183
187 bool empty() const { return m_size == 0; }
188
195 void copy_from_host(const std::vector<T> &host_data) {
196 if (host_data.size() != m_size) {
197 throw std::runtime_error("Size mismatch in copy_from_host: expected " +
198 std::to_string(m_size) + ", got " +
199 std::to_string(host_data.size()));
200 }
201#if PFC_GPU_CUDA_AVAILABLE
202 if (m_size > 0) {
203 cudaError_t err = cudaMemcpy(m_device_ptr, host_data.data(),
204 m_size * sizeof(T), cudaMemcpyHostToDevice);
205 if (err != cudaSuccess) {
206 throw std::runtime_error("Failed to copy from host to device: " +
207 std::string(cudaGetErrorString(err)));
208 }
209 }
210#else
211 throw std::runtime_error("copy_from_host: CUDA not enabled at compile time");
212#endif
213 }
214
220 void copy_to_host(std::vector<T> &host_data) const {
221 if (host_data.size() != m_size) {
222 host_data.resize(m_size);
223 }
224#if PFC_GPU_CUDA_AVAILABLE
225 if (m_size > 0) {
226 cudaError_t err = cudaMemcpy(host_data.data(), m_device_ptr,
227 m_size * sizeof(T), cudaMemcpyDeviceToHost);
228 if (err != cudaSuccess) {
229 throw std::runtime_error("Failed to copy from device to host: " +
230 std::string(cudaGetErrorString(err)));
231 }
232 }
233#else
234 throw std::runtime_error("copy_to_host: CUDA not enabled at compile time");
235#endif
236 }
237
243 std::vector<T> to_host() const {
244 std::vector<T> result(m_size);
246 return result;
247 }
248};
249
250} // namespace gpu
251} // namespace pfc
252
253#undef PFC_GPU_CUDA_AVAILABLE
254
255#endif
Simple GPU memory container (RAII)
Definition gpu_vector.hpp:73
const T * data() const
Get const pointer to GPU memory.
Definition gpu_vector.hpp:171
size_t size() const
Get the number of elements.
Definition gpu_vector.hpp:182
void copy_from_host(const std::vector< T > &host_data)
Copy data from host (CPU) to device (GPU)
Definition gpu_vector.hpp:195
~GPUVector()
Destructor - automatically frees GPU memory.
Definition gpu_vector.hpp:115
std::vector< T > to_host() const
Copy data from device to host and return as vector.
Definition gpu_vector.hpp:243
void copy_to_host(std::vector< T > &host_data) const
Copy data from device (GPU) to host (CPU)
Definition gpu_vector.hpp:220
GPUVector(GPUVector &&other) noexcept
Move constructor.
Definition gpu_vector.hpp:130
GPUVector & operator=(GPUVector &&other) noexcept
Move assignment operator.
Definition gpu_vector.hpp:139
T * data()
Get pointer to GPU memory.
Definition gpu_vector.hpp:160
bool empty() const
Check if the vector is empty.
Definition gpu_vector.hpp:187
GPUVector(size_t size)
Construct a GPUVector with the specified size.
Definition gpu_vector.hpp:94
Represents the global simulation domain (the "world").
Definition world.hpp:91
const Int3 m_size
Grid dimensions: {nx, ny, nz}.
Definition world.hpp:94