opm-simulators
PinnedMemoryHolder.hpp
1 /*
2  Copyright 2025 Equinor ASA
3 
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef OPM_SIMULATORS_LINALG_GPUISTL_PINNEDMEMORYHOLDER_HPP
21 #define OPM_SIMULATORS_LINALG_GPUISTL_PINNEDMEMORYHOLDER_HPP
22 
23 
24 #include "opm/simulators/linalg/gpuistl/detail/gpu_safe_call.hpp"
25 
26 #include <cuda_runtime.h>
27 
28 #include <fmt/format.h>
29 
30 namespace Opm
31 {
32 namespace gpuistl
33 {
34 
44  template <class T>
46  {
47  public:
56  PinnedMemoryHolder(T* ptr, std::size_t numberOfElements, unsigned int flags = cudaHostRegisterDefault)
57  : m_ptr(ptr)
58  , m_numberOfElements(numberOfElements)
59  {
60  if (m_ptr && m_numberOfElements > 0) {
61  std::size_t sizeInBytes = numberOfElements * sizeof(T);
62  OPM_GPU_SAFE_CALL(cudaHostRegister(static_cast<void*>(m_ptr), sizeInBytes, flags));
63  }
64  }
65 
70  {
71  if (m_ptr && m_numberOfElements > 0)
72  OPM_GPU_SAFE_CALL(cudaHostUnregister(static_cast<void*>(m_ptr)));
73  }
74 
75  // Disable copy constructor and copy assignment operator
76  PinnedMemoryHolder(const PinnedMemoryHolder&) = delete;
77  PinnedMemoryHolder& operator=(const PinnedMemoryHolder&) = delete;
78 
79  // Enable move constructor and move assignment operator
80  PinnedMemoryHolder(PinnedMemoryHolder&& other) noexcept
81  : m_ptr(other.m_ptr)
82  , m_numberOfElements(other.m_numberOfElements)
83  {
84  other.m_ptr = nullptr;
85  other.m_numberOfElements = 0;
86  }
87 
88  PinnedMemoryHolder& operator=(PinnedMemoryHolder&& other) noexcept
89  {
90  if (this != &other) {
91  // Unregister existing memory, if any
92  if (m_ptr && m_numberOfElements > 0) {
93  OPM_GPU_SAFE_CALL(cudaHostUnregister(static_cast<void*>(m_ptr)));
94  }
95 
96  // Transfer ownership
97  m_ptr = other.m_ptr;
98  m_numberOfElements = other.m_numberOfElements;
99 
100  // Leave other in a valid but empty state
101  other.m_ptr = nullptr;
102  other.m_numberOfElements = 0;
103  }
104  return *this;
105  }
106 
111  T* get() const
112  {
113  return m_ptr;
114  }
115 
120  std::size_t numberOfElements() const
121  {
122  return m_numberOfElements;
123  }
124 
125  private:
126  T* m_ptr;
127  std::size_t m_numberOfElements;
128  };
129 
130 } // namespace gpuistl
131 } // namespace Opm
132 
133 #endif // OPM_SIMULATORS_LINALG_GPUISTL_PINNEDMEMORYHOLDER_HPP
RAII class for pinning host memory using cudaHostRegister.
Definition: PinnedMemoryHolder.hpp:45
std::size_t numberOfElements() const
Gets the number of elements in the pinned memory region.
Definition: PinnedMemoryHolder.hpp:120
PinnedMemoryHolder(T *ptr, std::size_t numberOfElements, unsigned int flags=cudaHostRegisterDefault)
Constructs a PinnedMemoryHolder and registers the host memory.
Definition: PinnedMemoryHolder.hpp:56
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
~PinnedMemoryHolder()
Destructor.
Definition: PinnedMemoryHolder.hpp:69