opm-simulators
gpu_smart_pointer.hpp
Go to the documentation of this file.
1 /*
2  Copyright 2025 Equinor ASA
3  This file is part of the Open Porous Media project (OPM).
4  OPM is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8  OPM is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12  You should have received a copy of the GNU General Public License
13  along with OPM. If not, see <http://www.gnu.org/licenses/>.
14 */
15 
16 #ifndef OPM_SIMULATORS_LINALG_GPUISTL_GPU_SMART_POINTER_HPP
17 #define OPM_SIMULATORS_LINALG_GPUISTL_GPU_SMART_POINTER_HPP
18 
19 #include <cuda_runtime.h>
20 
21 #include <memory>
22 
23 #include <opm/common/utility/gpuDecorators.hpp>
24 #include <opm/simulators/linalg/gpuistl/detail/gpu_safe_call.hpp>
25 #include <opm/simulators/linalg/gpuistl/detail/is_gpu_pointer.hpp>
26 
32 namespace Opm::gpuistl
33 {
34 
35 
46 template <typename T>
47 std::shared_ptr<T>
49 {
50  T* ptr = nullptr;
51  OPM_GPU_SAFE_CALL(cudaMalloc(&ptr, sizeof(T)));
52  auto deleter = [](T* ptrToDelete) { OPM_GPU_WARN_IF_ERROR(cudaFree(ptrToDelete)); };
53  return std::shared_ptr<T>(ptr, deleter);
54 }
55 
67 template <typename T>
68 std::shared_ptr<T>
69 make_gpu_shared_ptr(const T& value)
70 {
71  auto ptr = make_gpu_shared_ptr<T>();
72  OPM_GPU_SAFE_CALL(cudaMemcpy(ptr.get(), &value, sizeof(T), cudaMemcpyHostToDevice));
73  return ptr;
74 }
75 
76 
87 template <typename T>
88 auto
90 {
91  T* ptr = nullptr;
92  OPM_GPU_SAFE_CALL(cudaMalloc(&ptr, sizeof(T)));
93 
94  auto deleter = [](T* ptrToDelete) { OPM_GPU_WARN_IF_ERROR(cudaFree(ptrToDelete)); };
95  return std::unique_ptr<T, decltype(deleter)>(ptr, deleter);
96 }
97 
109 template <typename T>
110 auto
111 make_gpu_unique_ptr(const T& value)
112 {
113  auto ptr = make_gpu_unique_ptr<T>();
114  OPM_GPU_SAFE_CALL(cudaMemcpy(ptr.get(), &value, sizeof(T), cudaMemcpyHostToDevice));
115  return ptr;
116 }
117 
127 template <class T>
128 T
129 copyFromGPU(const T* value)
130 {
131 #ifndef NDEBUG
132  OPM_ERROR_IF(!Opm::gpuistl::detail::isGPUPointer(value), "The pointer is not associated with GPU memory.");
133 #endif
134  T result;
135  OPM_GPU_SAFE_CALL(cudaMemcpy(&result, value, sizeof(T), cudaMemcpyDeviceToHost));
136  return result;
137 }
138 
148 template <class T>
149 T
150 copyFromGPU(const std::shared_ptr<T>& value)
151 {
152  return copyFromGPU(value.get());
153 }
154 
165 template <class T, class Deleter>
166 T
167 copyFromGPU(const std::unique_ptr<T, Deleter>& value)
168 {
169  return copyFromGPU(value.get());
170 }
171 
180 template <class T>
181 void
182 copyToGPU(const T& value, T* ptr)
183 {
184 #ifndef NDEBUG
185  OPM_ERROR_IF(!Opm::gpuistl::detail::isGPUPointer(ptr), "The pointer is not associated with GPU memory.");
186 #endif
187  OPM_GPU_SAFE_CALL(cudaMemcpy(ptr, &value, sizeof(T), cudaMemcpyHostToDevice));
188 }
189 
198 template <class T>
199 void
200 copyToGPU(const T& value, const std::shared_ptr<T>& ptr)
201 {
202  copyToGPU(value, ptr.get());
203 }
204 
214 template <class T, class Deleter>
215 void
216 copyToGPU(const T& value, const std::unique_ptr<T, Deleter>& ptr)
217 {
218  copyToGPU(value, ptr.get());
219 }
220 
229 template <class T>
231 {
232 public:
233  PointerView(const PointerView& other) = default;
234 
235  PointerView(const std::shared_ptr<T>& ptr)
236  : ptr_(ptr.get())
237  {
238  }
239 
240  template <class Deleter>
241  PointerView(const std::unique_ptr<T, Deleter>& ptr)
242  : ptr_(ptr.get())
243  {
244  }
245 
246  PointerView(T* ptr)
247  : ptr_(ptr)
248  {
249  }
250 
251  OPM_HOST_DEVICE T* get() const
252  {
253  return ptr_;
254  }
255 
256  OPM_HOST_DEVICE const T& operator*() const
257  {
258  return *ptr_;
259  }
260 
261  OPM_HOST_DEVICE T& operator*()
262  {
263  return *ptr_;
264  }
265 
266  OPM_HOST_DEVICE T* operator->() const
267  {
268  return ptr_;
269  }
270 
271 private:
272  T* ptr_;
273 };
274 
280 template <>
281 class PointerView<void>
282 {
283 public:
284  PointerView(const PointerView& other) = default;
285 
286  PointerView(const std::shared_ptr<void>& ptr)
287  : ptr_(ptr.get())
288  {
289  }
290 
291  template <class Deleter>
292  PointerView(const std::unique_ptr<void, Deleter>& ptr)
293  : ptr_(ptr.get())
294  {
295  }
296 
297  PointerView(void* ptr)
298  : ptr_(ptr)
299  {
300  }
301 
302  OPM_HOST_DEVICE void* get() const
303  {
304  return ptr_;
305  }
306 
307  OPM_HOST_DEVICE void* operator->() const
308  {
309  return ptr_;
310  }
311 
312 private:
313  void* ptr_;
314 };
315 
316 template <class T>
318 make_view(const std::shared_ptr<T>& ptr)
319 {
320  return PointerView<T>(ptr);
321 }
322 
323 template <class T, class Deleter>
324 PointerView<T>
325 make_view(const std::unique_ptr<T, Deleter>& ptr)
326 {
327  return PointerView<T>(ptr);
328 }
329 
334 template<class T>
336 public:
337  using element_type = T;
338 
339  ValueAsPointer(const T& t) : value(t) {}
340 
341  OPM_HOST_DEVICE T* operator->() {
342  return &value;
343  }
344 
345  OPM_HOST_DEVICE T* get() {
346  return &value;
347  }
348 
349  OPM_HOST_DEVICE const T* operator->() const {
350  return &value;
351  }
352 
353  OPM_HOST_DEVICE const T* get() const {
354  return &value;
355  }
356 
357  OPM_HOST_DEVICE T& operator*() {
358  return value;
359  }
360 
361  OPM_HOST_DEVICE const T& operator*() const {
362  return value;
363  }
364 private:
365  T value;
366 };
367 } // namespace Opm::gpuistl
368 #endif
A view towards a smart pointer to GPU-allocated memory.
Definition: gpu_smart_pointer.hpp:230
auto make_gpu_unique_ptr()
Creates a unique pointer managing GPU-allocated memory of the specified element type.
Definition: gpu_smart_pointer.hpp:89
T copyFromGPU(const T *value)
Copies a value from GPU-allocated memory to the host.
Definition: gpu_smart_pointer.hpp:129
A small, fixed‑dimension MiniVector class backed by std::array that can be used in both host and CUD...
Definition: AmgxInterface.hpp:37
A value stored with a pointer interface.
Definition: gpu_smart_pointer.hpp:335
bool isGPUPointer(const T *ptr)
Checks whether the given pointer is associated with GPU device memory.
Definition: is_gpu_pointer.hpp:40
std::shared_ptr< T > make_gpu_shared_ptr()
Creates a shared pointer managing GPU-allocated memory of the specified element type.
Definition: gpu_smart_pointer.hpp:48
void copyToGPU(const T &value, T *ptr)
Copies a value from the host to GPU-allocated memory.
Definition: gpu_smart_pointer.hpp:182