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
228template <class T>
230{
231public:
232 PointerView(const PointerView& other) = default;
233
234 PointerView(const std::shared_ptr<T>& ptr)
235 : ptr_(ptr.get())
236 {
237 }
238
239 template <class Deleter>
240 PointerView(const std::unique_ptr<T, Deleter>& ptr)
241 : ptr_(ptr.get())
242 {
243 }
244
246 : ptr_(ptr)
247 {
248 }
249
250 OPM_HOST_DEVICE T* get() const
251 {
252 return ptr_;
253 }
254
255 OPM_HOST_DEVICE T& operator*() const
256 {
257 return *ptr_;
258 }
259
260 OPM_HOST_DEVICE T* operator->() const
261 {
262 return ptr_;
263 }
264
265private:
266 T* ptr_;
267};
268
269template <class T>
270PointerView<T>
271make_view(const std::shared_ptr<T>& ptr)
272{
273 return PointerView<T>(ptr);
274}
275
276template <class T, class Deleter>
277PointerView<T>
278make_view(const std::unique_ptr<T, Deleter>& ptr)
279{
280 return PointerView<T>(ptr);
281}
282} // namespace Opm::gpuistl
283#endif
A view towards a smart pointer to GPU-allocated memory.
Definition: gpu_smart_pointer.hpp:230
OPM_HOST_DEVICE T * operator->() const
Definition: gpu_smart_pointer.hpp:260
PointerView(const std::unique_ptr< T, Deleter > &ptr)
Definition: gpu_smart_pointer.hpp:240
PointerView(T *ptr)
Definition: gpu_smart_pointer.hpp:245
PointerView(const std::shared_ptr< T > &ptr)
Definition: gpu_smart_pointer.hpp:234
PointerView(const PointerView &other)=default
OPM_HOST_DEVICE T & operator*() const
Definition: gpu_smart_pointer.hpp:255
OPM_HOST_DEVICE T * get() const
Definition: gpu_smart_pointer.hpp:250
#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: autotuner.hpp:30
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:271
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