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
21
22#include <opm/common/utility/gpuDecorators.hpp>
23
24#include <cuda_runtime.h>
25
26#include <memory>
27
33namespace Opm::gpuistl
34{
35
36
47template <typename T>
48std::shared_ptr<T>
50{
51 T* ptr = nullptr;
52 OPM_GPU_SAFE_CALL(cudaMalloc(&ptr, sizeof(T)));
53 auto deleter = [](T* ptrToDelete) { OPM_GPU_WARN_IF_ERROR(cudaFree(ptrToDelete)); };
54 return std::shared_ptr<T>(ptr, deleter);
55}
56
68template <typename T>
69std::shared_ptr<T>
70make_gpu_shared_ptr(const T& value)
71{
72 auto ptr = make_gpu_shared_ptr<T>();
73 detail::gpuMemcpyHostToDevice(ptr.get(), &value, 1);
74 return ptr;
75}
76
77
88template <typename T>
89auto
91{
92 T* ptr = nullptr;
93 OPM_GPU_SAFE_CALL(cudaMalloc(&ptr, sizeof(T)));
94
95 auto deleter = [](T* ptrToDelete) { OPM_GPU_WARN_IF_ERROR(cudaFree(ptrToDelete)); };
96 return std::unique_ptr<T, decltype(deleter)>(ptr, deleter);
97}
98
110template <typename T>
111auto
112make_gpu_unique_ptr(const T& value)
113{
114 auto ptr = make_gpu_unique_ptr<T>();
115 detail::gpuMemcpyHostToDevice(ptr.get(), &value, 1);
116 return ptr;
117}
118
126template <class T>
128 void operator()(T* ptr) const noexcept
129 {
130 OPM_GPU_WARN_IF_ERROR(cudaFree(ptr));
131 }
132};
133
140template <class T>
142 void operator()(T* ptr) const noexcept
143 {
144 if (ptr != nullptr) {
145 ptr->~T();
146 OPM_GPU_WARN_IF_ERROR(cudaFree(ptr));
147 }
148 }
149};
150
166template <typename T>
167std::unique_ptr<T[], GpuArrayDeleter<T>>
168make_gpu_unique_ptr_array(std::size_t numElements)
169{
170 T* ptr = nullptr;
171 OPM_GPU_SAFE_CALL(cudaMalloc(&ptr, numElements * sizeof(T)));
172 return std::unique_ptr<T[], GpuArrayDeleter<T>>(ptr);
173}
174
193template <typename T, class... Args>
194std::unique_ptr<T, GpuManagedDeleter<T>>
196{
197 void* raw = nullptr;
198 OPM_GPU_SAFE_CALL(cudaMallocManaged(&raw, sizeof(T)));
199 T* ptr = nullptr;
200 try {
201 ptr = new (raw) T(std::forward<Args>(args)...);
202 } catch (...) {
203 OPM_GPU_WARN_IF_ERROR(cudaFree(raw));
204 throw;
205 }
206 return std::unique_ptr<T, GpuManagedDeleter<T>>(ptr);
207}
208
218template <class T>
219T
220copyFromGPU(const T* value)
221{
222 T result;
223 detail::gpuMemcpyDeviceToHost(&result, value, 1);
224 return result;
225}
226
236template <class T>
237T
238copyFromGPU(const std::shared_ptr<T>& value)
239{
240 return copyFromGPU(value.get());
241}
242
253template <class T, class Deleter>
254T
255copyFromGPU(const std::unique_ptr<T, Deleter>& value)
256{
257 return copyFromGPU(value.get());
258}
259
268template <class T>
269void
270copyToGPU(const T& value, T* ptr)
271{
272 detail::gpuMemcpyHostToDevice(ptr, &value, 1);
273}
274
283template <class T>
284void
285copyToGPU(const T& value, const std::shared_ptr<T>& ptr)
286{
287 copyToGPU(value, ptr.get());
288}
289
299template <class T, class Deleter>
300void
301copyToGPU(const T& value, const std::unique_ptr<T, Deleter>& ptr)
302{
303 copyToGPU(value, ptr.get());
304}
305
314template <class T>
316{
317public:
318 PointerView(const PointerView& other) = default;
319
320 PointerView(const std::shared_ptr<T>& ptr)
321 : ptr_(ptr.get())
322 {
323 }
324
325 template <class Deleter>
326 PointerView(const std::unique_ptr<T, Deleter>& ptr)
327 : ptr_(ptr.get())
328 {
329 }
330
332 : ptr_(ptr)
333 {
334 }
335
336 OPM_HOST_DEVICE T* get() const
337 {
338 return ptr_;
339 }
340
341 OPM_HOST_DEVICE const T& operator*() const
342 {
343 return *ptr_;
344 }
345
346 OPM_HOST_DEVICE T& operator*()
347 {
348 return *ptr_;
349 }
350
351 OPM_HOST_DEVICE T* operator->() const
352 {
353 return ptr_;
354 }
355
356private:
357 T* ptr_;
358};
359
365template <>
366class PointerView<void>
367{
368public:
369 PointerView(const PointerView& other) = default;
370
371 PointerView(const std::shared_ptr<void>& ptr)
372 : ptr_(ptr.get())
373 {
374 }
375
376 template <class Deleter>
377 PointerView(const std::unique_ptr<void, Deleter>& ptr)
378 : ptr_(ptr.get())
379 {
380 }
381
382 PointerView(void* ptr)
383 : ptr_(ptr)
384 {
385 }
386
387 OPM_HOST_DEVICE void* get() const
388 {
389 return ptr_;
390 }
391
392 OPM_HOST_DEVICE void* operator->() const
393 {
394 return ptr_;
395 }
396
397private:
398 void* ptr_;
399};
400
401template <class T>
402PointerView<T>
403make_view(const std::shared_ptr<T>& ptr)
404{
405 return PointerView<T>(ptr);
406}
407
408template <class T, class Deleter>
409PointerView<T>
410make_view(const std::unique_ptr<T, Deleter>& ptr)
411{
412 return PointerView<T>(ptr);
413}
414
419template<class T>
421public:
422 using element_type = T;
423
424 OPM_HOST_DEVICE ValueAsPointer() = default;
425
426 OPM_HOST_DEVICE explicit ValueAsPointer(const T& t) : value(t) {}
427
428 OPM_HOST_DEVICE T* operator->() {
429 return &value;
430 }
431
432 OPM_HOST_DEVICE T* get() {
433 return &value;
434 }
435
436 OPM_HOST_DEVICE const T* operator->() const {
437 return &value;
438 }
439
440 OPM_HOST_DEVICE const T* get() const {
441 return &value;
442 }
443
444 OPM_HOST_DEVICE T& operator*() {
445 return value;
446 }
447
448 OPM_HOST_DEVICE const T& operator*() const {
449 return value;
450 }
451private:
452 T value;
453};
454} // namespace Opm::gpuistl
455#endif
PointerView(const std::unique_ptr< void, Deleter > &ptr)
Definition: gpu_smart_pointer.hpp:377
PointerView(const std::shared_ptr< void > &ptr)
Definition: gpu_smart_pointer.hpp:371
PointerView(void *ptr)
Definition: gpu_smart_pointer.hpp:382
OPM_HOST_DEVICE void * operator->() const
Definition: gpu_smart_pointer.hpp:392
PointerView(const PointerView &other)=default
OPM_HOST_DEVICE void * get() const
Definition: gpu_smart_pointer.hpp:387
A view towards a smart pointer to GPU-allocated memory.
Definition: gpu_smart_pointer.hpp:316
OPM_HOST_DEVICE const T & operator*() const
Definition: gpu_smart_pointer.hpp:341
OPM_HOST_DEVICE T & operator*()
Definition: gpu_smart_pointer.hpp:346
OPM_HOST_DEVICE T * operator->() const
Definition: gpu_smart_pointer.hpp:351
PointerView(const std::unique_ptr< T, Deleter > &ptr)
Definition: gpu_smart_pointer.hpp:326
PointerView(T *ptr)
Definition: gpu_smart_pointer.hpp:331
PointerView(const std::shared_ptr< T > &ptr)
Definition: gpu_smart_pointer.hpp:320
PointerView(const PointerView &other)=default
OPM_HOST_DEVICE T * get() const
Definition: gpu_smart_pointer.hpp:336
A value stored with a pointer interface. Can be used to wrap objects in GPU kernels that were otherwi...
Definition: gpu_smart_pointer.hpp:420
OPM_HOST_DEVICE T * operator->()
Definition: gpu_smart_pointer.hpp:428
T element_type
Definition: gpu_smart_pointer.hpp:422
OPM_HOST_DEVICE T * get()
Definition: gpu_smart_pointer.hpp:432
OPM_HOST_DEVICE T & operator*()
Definition: gpu_smart_pointer.hpp:444
OPM_HOST_DEVICE ValueAsPointer(const T &t)
Definition: gpu_smart_pointer.hpp:426
OPM_HOST_DEVICE ValueAsPointer()=default
OPM_HOST_DEVICE const T & operator*() const
Definition: gpu_smart_pointer.hpp:448
OPM_HOST_DEVICE const T * operator->() const
Definition: gpu_smart_pointer.hpp:436
OPM_HOST_DEVICE const T * get() const
Definition: gpu_smart_pointer.hpp:440
#define OPM_GPU_SAFE_CALL(expression)
OPM_GPU_SAFE_CALL checks the return type of the GPU expression (function call) and throws an exceptio...
Definition: gpu_safe_call.hpp:164
#define OPM_GPU_WARN_IF_ERROR(expression)
OPM_GPU_WARN_IF_ERROR checks the return type of the GPU expression (function call) and issues a warni...
Definition: gpu_safe_call.hpp:185
void gpuMemcpyHostToDevice(T *dstDevice, const T *srcHost, std::size_t count)
gpuMemcpyHostToDevice copies count elements of type T from host to device.
Definition: gpu_memcpy.hpp:46
void gpuMemcpyDeviceToHost(T *dstHost, const T *srcDevice, std::size_t count)
gpuMemcpyDeviceToHost copies count elements of type T from device to host.
Definition: gpu_memcpy.hpp:69
A small, fixed‑dimension MiniVector class backed by std::array that can be used in both host and CUDA...
Definition: GpuFlowProblem.hpp:48
inline ::Opm::NoThermalLawManager make_view(::Opm::NoThermalLawManager &)
make_view overload for the no-op thermal manager.
Definition: GpuFlowProblem.hpp:101
void copyToGPU(const T &value, T *ptr)
Copies a value from the host to GPU-allocated memory.
Definition: gpu_smart_pointer.hpp:270
std::unique_ptr< T, GpuManagedDeleter< T > > make_gpu_managed_unique_ptr(Args &&... args)
Creates a unique pointer managing GPU unified (managed) memory for a single object.
Definition: gpu_smart_pointer.hpp:195
std::unique_ptr< T[], GpuArrayDeleter< T > > make_gpu_unique_ptr_array(std::size_t numElements)
Creates a unique pointer managing a GPU-allocated array of numElements elements.
Definition: gpu_smart_pointer.hpp:168
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:49
T copyFromGPU(const T *value)
Copies a value from GPU-allocated memory to the host.
Definition: gpu_smart_pointer.hpp:220
auto make_gpu_unique_ptr()
Creates a unique pointer managing GPU-allocated memory of the specified element type.
Definition: gpu_smart_pointer.hpp:90
Deleter that releases a GPU array allocation made with cudaMalloc.
Definition: gpu_smart_pointer.hpp:127
void operator()(T *ptr) const noexcept
Definition: gpu_smart_pointer.hpp:128
Deleter for objects living in unified (managed) GPU memory.
Definition: gpu_smart_pointer.hpp:141
void operator()(T *ptr) const noexcept
Definition: gpu_smart_pointer.hpp:142