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>
26
32namespace Opm::gpuistl
33{
34
35
46template <typename T>
47std::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
67template <typename T>
68std::shared_ptr<T>
69make_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
87template <typename T>
88auto
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
109template <typename T>
110auto
111make_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
127template <class T>
128T
129copyFromGPU(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
148template <class T>
149T
150copyFromGPU(const std::shared_ptr<T>& value)
151{
152 return copyFromGPU(value.get());
153}
154
165template <class T, class Deleter>
166T
167copyFromGPU(const std::unique_ptr<T, Deleter>& value)
168{
169 return copyFromGPU(value.get());
170}
171
180template <class T>
181void
182copyToGPU(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
198template <class T>
199void
200copyToGPU(const T& value, const std::shared_ptr<T>& ptr)
201{
202 copyToGPU(value, ptr.get());
203}
204
214template <class T, class Deleter>
215void
216copyToGPU(const T& value, const std::unique_ptr<T, Deleter>& ptr)
217{
218 copyToGPU(value, ptr.get());
219}
220
229template <class T>
231{
232public:
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
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
271private:
272 T* ptr_;
273};
274
280template <>
281class PointerView<void>
282{
283public:
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
312private:
313 void* ptr_;
314};
315
316template <class T>
317PointerView<T>
318make_view(const std::shared_ptr<T>& ptr)
319{
320 return PointerView<T>(ptr);
321}
322
323template <class T, class Deleter>
324PointerView<T>
325make_view(const std::unique_ptr<T, Deleter>& ptr)
326{
327 return PointerView<T>(ptr);
328}
329
334template<class T>
336public:
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 }
364private:
365 T value;
366};
367} // namespace Opm::gpuistl
368#endif
PointerView(const std::unique_ptr< void, Deleter > &ptr)
Definition: gpu_smart_pointer.hpp:292
PointerView(const std::shared_ptr< void > &ptr)
Definition: gpu_smart_pointer.hpp:286
PointerView(void *ptr)
Definition: gpu_smart_pointer.hpp:297
OPM_HOST_DEVICE void * operator->() const
Definition: gpu_smart_pointer.hpp:307
PointerView(const PointerView &other)=default
OPM_HOST_DEVICE void * get() const
Definition: gpu_smart_pointer.hpp:302
A view towards a smart pointer to GPU-allocated memory.
Definition: gpu_smart_pointer.hpp:231
OPM_HOST_DEVICE const T & operator*() const
Definition: gpu_smart_pointer.hpp:256
OPM_HOST_DEVICE T & operator*()
Definition: gpu_smart_pointer.hpp:261
OPM_HOST_DEVICE T * operator->() const
Definition: gpu_smart_pointer.hpp:266
PointerView(const std::unique_ptr< T, Deleter > &ptr)
Definition: gpu_smart_pointer.hpp:241
PointerView(T *ptr)
Definition: gpu_smart_pointer.hpp:246
PointerView(const std::shared_ptr< T > &ptr)
Definition: gpu_smart_pointer.hpp:235
PointerView(const PointerView &other)=default
OPM_HOST_DEVICE T * get() const
Definition: gpu_smart_pointer.hpp:251
A value stored with a pointer interface. Can be used to wrap objects in GPU kernels that were otherwi...
Definition: gpu_smart_pointer.hpp:335
ValueAsPointer(const T &t)
Definition: gpu_smart_pointer.hpp:339
OPM_HOST_DEVICE T * operator->()
Definition: gpu_smart_pointer.hpp:341
T element_type
Definition: gpu_smart_pointer.hpp:337
OPM_HOST_DEVICE T * get()
Definition: gpu_smart_pointer.hpp:345
OPM_HOST_DEVICE T & operator*()
Definition: gpu_smart_pointer.hpp:357
OPM_HOST_DEVICE const T & operator*() const
Definition: gpu_smart_pointer.hpp:361
OPM_HOST_DEVICE const T * operator->() const
Definition: gpu_smart_pointer.hpp:349
OPM_HOST_DEVICE const T * get() const
Definition: gpu_smart_pointer.hpp:353
#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:150
#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:171
bool isGPUPointer(const T *ptr)
Checks whether the given pointer is associated with GPU device memory.
Definition: is_gpu_pointer.hpp:40
Definition: AmgxInterface.hpp:38
void copyToGPU(const T &value, T *ptr)
Copies a value from the host to GPU-allocated memory.
Definition: gpu_smart_pointer.hpp:182
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
PointerView< T > make_view(const std::shared_ptr< T > &ptr)
Definition: gpu_smart_pointer.hpp:318
T copyFromGPU(const T *value)
Copies a value from GPU-allocated memory to the host.
Definition: gpu_smart_pointer.hpp:129
auto make_gpu_unique_ptr()
Creates a unique pointer managing GPU-allocated memory of the specified element type.
Definition: gpu_smart_pointer.hpp:89