OpenMPCD
DeviceMemoryManager.hpp
Go to the documentation of this file.
1 /**
2  * @file
3  * Defines the OpenMPCD::CUDA::DeviceMemoryManager class.
4  */
5 
6 #ifndef OPENMPCD_CUDA_DEVICEMEMORYMANAGER_HPP
7 #define OPENMPCD_CUDA_DEVICEMEMORYMANAGER_HPP
8 
10 
11 #include <set>
12 
13 namespace OpenMPCD
14 {
15 namespace CUDA
16 {
17 
18 /**
19  * Class for managing memory on the CUDA Device.
20  */
22 {
23  public:
24  /**
25  * The constructor.
26  * The autofree feature is disabled by default.
27  */
29 
30  private:
31  DeviceMemoryManager(const DeviceMemoryManager&); ///< The copy constructor.
32 
33  public:
34  /**
35  * The destructor.
36  * If there are Device buffers which have not been freed,
37  * and the autofree flag has not been set,
38  * prints corresponding warning messages to `stderr`.
39  */
41 
42  public:
43  /**
44  * Allocates Device memory for the given number of instances of the supplied type.
45  * The returned pointer points to at least instanceCount * sizeof(Pointee) bytes of allocated Device memory.
46  *
47  * Memory allocated through this function is registered with this
48  * instance. Unless the memory is freed via a call to this instance's
49  * `freeMemory`, or the autofree flag is set via `setAutofree`, this
50  * instance will, during destruction, print error messages about every
51  * unfreed allocation in the destructor.
52  *
53  * @throw OpenMPCD::MemoryManagementException
54  * Throws if the buffer could not be allocated.
55  *
56  * @tparam Pointee The pointee type.
57  *
58  * @param[in] instanceCount The number of instances the returned buffer
59  * should fit at a minimum. If `0`, `nullptr`
60  * is returned.
61  */
62  template<typename Pointee> Pointee* allocateMemory(const unsigned int instanceCount)
63  {
64  return static_cast<Pointee*>(allocateMemoryInternal(instanceCount * sizeof(Pointee)));
65  }
66 
67  /**
68  * Allocates Device memory for the given number of instances of the supplied type.
69  * After a successful call, the given pointer points to at least instanceCount * sizeof(Pointee) bytes
70  * of allocated Device memory.
71  *
72  * Memory allocated through this function is registered with this
73  * instance. Unless the memory is freed via a call to this instance's
74  * `freeMemory`, or the autofree flag is set via `setAutofree`, this
75  * instance will, during destruction, print error messages about every
76  * unfreed allocation in the destructor.
77  *
78  * @throw OpenMPCD::NULLPointerException
79  * If `OPENMPCD_DEBUG` is defined, throws if `pointerToPointer` is
80  * `nullptr`.
81  * @throw OpenMPCD::MemoryManagementException
82  * Throws if the buffer could not be allocated.
83  *
84  * @tparam Pointee The pointee type.
85  *
86  * @param[out] pointerToPointer A valid pointer to the pointer that is
87  * to be set. Will be set to `nullptr` if
88  * `instanceCount == 0`.
89  * @param[in] instanceCount The number of instances the returned buffer should fit at a minimum.
90  */
91  template<typename Pointee> void allocateMemory(Pointee** pointerToPointer, const unsigned int instanceCount)
92  {
93  #ifdef OPENMPCD_DEBUG
94  if(pointerToPointer == NULL)
95  OPENMPCD_THROW(NULLPointerException, "pointerToPointer");
96  #endif
97 
98  *pointerToPointer = allocateMemory<Pointee>(instanceCount);
99  }
100 
101  /**
102  * Allocates Device memory for the given number of instances of the
103  * supplied type.
104  * The returned pointer points to at least
105  * `instanceCount * sizeof(Pointee)` bytes of allocated Device memory.
106  *
107  * Memory allocated through this function is not registered with this
108  * instance, in contrast to `allocateMemory`.
109  *
110  * @throw OpenMPCD::MemoryManagementException
111  * Throws if the buffer could not be allocated.
112  *
113  * @tparam Pointee The pointee type.
114  *
115  * @param[in] instanceCount The number of instances the returned buffer
116  * should fit at a minimum. If `0`, `nullptr`
117  * is returned.
118  */
119  template<typename Pointee>
120  static
121  Pointee* allocateMemoryUnregistered(const unsigned int instanceCount)
122  {
123  return
124  static_cast<Pointee*>(
125  allocateMemoryInternalUnregistered(
126  instanceCount * sizeof(Pointee)));
127  }
128 
129  /**
130  * Allocates Device memory for the given number of instances of the
131  * supplied type.
132  * After a successful call, the given pointer points to at least
133  * `instanceCount * sizeof(Pointee)` bytes of allocated Device memory.
134  *
135  * Memory allocated through this function is not registered with this
136  * instance, in contrast to `allocateMemory`.
137  *
138  * @throw OpenMPCD::NULLPointerException
139  * If `OPENMPCD_DEBUG` is defined, throws if `pointerToPointer` is
140  * `nullptr`.
141  * @throw OpenMPCD::MemoryManagementException
142  * Throws if the buffer could not be allocated.
143  *
144  * @tparam Pointee The pointee type.
145  *
146  * @param[out] pointerToPointer A valid pointer to the pointer that is
147  * to be set. Will be set to `nullptr` if
148  * `instanceCount == 0`.
149  * @param[in] instanceCount The number of instances the returned
150  * buffer should fit at a minimum.
151  */
152  template<typename Pointee>
153  static
155  Pointee** pointerToPointer, const unsigned int instanceCount)
156  {
157  #ifdef OPENMPCD_DEBUG
158  if(pointerToPointer == NULL)
159  OPENMPCD_THROW(NULLPointerException, "pointerToPointer");
160  #endif
161 
162  *pointerToPointer =
163  allocateMemoryUnregistered<Pointee>(instanceCount);
164  }
165 
166  /**
167  * Frees the Device memory pointed to by the given pointer.
168  *
169  * @throw OpenMPCD::MemoryManagementException
170  * Throws if the given non-`nullptr` pointer has not been
171  * allocated through and registered with this instance, i.e. if
172  * the given pointer has not been created via a call to
173  * `allocateMemory`.
174  *
175  * @param[in] pointer The pointer to free. If it is `nullptr`, nothing
176  * happens.
177  */
178  void freeMemory(void* const pointer);
179 
180  /**
181  * Frees the Device memory pointed to by the given pointer.
182  *
183  * Note that one should not use this function with pointers allocated
184  * in a way that the pointer is registered with an instance of this
185  * class, e.g. via `allocateMemory`, since otherwise, that memory is
186  * either going to be freed twice, or a (spurious) warning about unfreed
187  * memory may be produced.
188  *
189  * @throw OpenMPCD::MemoryManagementException
190  * If `OPENMPCD_DEBUG` is defined, throws if
191  * `pointer != nullptr && !isDeviceMemoryPointer(pointer)`.
192  *
193  * @param[in] pointer The pointer to free. If it is `nullptr`, nothing
194  * happens.
195  */
196  static void freeMemoryUnregistered(void* const pointer);
197 
198  /**
199  * Sets, or unsets, the autofree flag.
200  *
201  * If the autofree flag is set, all reserved device memory is freed
202  * upon destruction of this instance, without raising warnings or
203  * errors.
204  *
205  * @param[in] enable Whether to enable the autofree feature.
206  */
207  void setAutofree(const bool enable)
208  {
209  autofree = enable;
210  }
211 
212  /**
213  * Returns whether the given pointer is a pointer to CUDA Device memory.
214  *
215  * Returns `false` if `ptr == nullptr`.
216  *
217  * @throw OpenMPCD::Exception Throws on an error.
218  *
219  * @param[in] ptr The pointer to check.
220  */
221  static bool isDeviceMemoryPointer(const void* const ptr);
222 
223  /**
224  * Returns whether the given pointer is a pointer to Host memory.
225  *
226  * If this function returns true, it does necessarily not mean that it
227  * is permissible to dereference the pointer.
228  *
229  * Returns `false` if `ptr == nullptr`.
230  *
231  * @throw OpenMPCD::Exception Throws on an error.
232  *
233  * @param[in] ptr The pointer to check.
234  */
235  static bool isHostMemoryPointer(const void* const ptr);
236 
237  /**
238  * Copies `count` elements of type `T` from the Host to the Device.
239  *
240  * @throw OpenMPCD::NULLPointerException
241  * If OPENMPCD_DEBUG is defined, throws if `src == nullptr`.
242  * @throw OpenMPCD::NULLPointerException
243  * If OPENMPCD_DEBUG is defined, throws if `dest == nullptr`
244  * @throw OpenMPCD::InvalidArgumentException
245  * If OPENMPCD_DEBUG is defined,
246  * throws if `src` is not a Host pointer.
247  * @throw OpenMPCD::InvalidArgumentException
248  * If OPENMPCD_DEBUG is defined,
249  * throws if `dest` is not a Device pointer.
250  *
251  * @tparam T The type of elements to copy.
252  *
253  * @param[in] src The source to copy from.
254  * @param[out] dest The destination to copy to.
255  * @param[in] count The number of elements of type `T` to copy.
256  */
257  template<typename T>
258  static void copyElementsFromHostToDevice(
259  const T* const src, T* const dest, const std::size_t count);
260 
261  /**
262  * Copies `count` elements of type `T` from the Device to the Host.
263  *
264  * @throw OpenMPCD::NULLPointerException
265  * If OPENMPCD_DEBUG is defined, throws if `src == nullptr`.
266  * @throw OpenMPCD::NULLPointerException
267  * If OPENMPCD_DEBUG is defined, throws if `dest == nullptr`
268  * @throw OpenMPCD::InvalidArgumentException
269  * If OPENMPCD_DEBUG is defined,
270  * throws if `src` is not a Device pointer.
271  * @throw OpenMPCD::InvalidArgumentException
272  * If OPENMPCD_DEBUG is defined,
273  * throws if `dest` is not a Host pointer.
274  *
275  * @tparam T The type of elements to copy.
276  *
277  * @param[in] src The source to copy from.
278  * @param[out] dest The destination to copy to.
279  * @param[in] count The number of elements of type `T` to copy.
280  */
281  template<typename T>
282  static void copyElementsFromDeviceToHost(
283  const T* const src, T* const dest, const std::size_t count);
284 
285  /**
286  * Copies `count` elements of type `T` from the Device to the Device.
287  *
288  * @throw OpenMPCD::NULLPointerException
289  * If OPENMPCD_DEBUG is defined, throws if `src == nullptr`.
290  * @throw OpenMPCD::NULLPointerException
291  * If OPENMPCD_DEBUG is defined, throws if `dest == nullptr`
292  * @throw OpenMPCD::InvalidArgumentException
293  * If OPENMPCD_DEBUG is defined,
294  * throws if `src` is not a Device pointer.
295  * @throw OpenMPCD::InvalidArgumentException
296  * If OPENMPCD_DEBUG is defined,
297  * throws if `dest` is not a Device pointer.
298  *
299  * @tparam T The type of elements to copy.
300  *
301  * @param[in] src The source to copy from.
302  * @param[out] dest The destination to copy to.
303  * @param[in] count The number of elements of type `T` to copy.
304  */
305  template<typename T>
306  static void copyElementsFromDeviceToDevice(
307  const T* const src, T* const dest, const std::size_t count);
308 
309  /**
310  * Writes zero-bytes to the given Device memory region.
311  *
312  * @throw OpenMPCD::NULLPointerException
313  * If OPENMPCD_DEBUG is defined, throws if `start == nullptr`
314  * @throw OpenMPCD::InvalidArgumentException
315  * If OPENMPCD_DEBUG is defined,
316  * throws if `start` is not a Device pointer.
317  *
318  * @tparam T The type of elements pointed to by `start`.
319  *
320  * @param[in] start
321  * The first element to write zero-bytes to.
322  * @param[in] numberOfElements
323  * The number of elements of type `T` to write zero-bytes to.
324  */
325  template<typename T>
326  static void zeroMemory(
327  T* const start, const std::size_t numberOfElements);
328 
329  /**
330  * Returns whether the `count` elements of type `T` at `host` in Host
331  * memory have the same byte-wise representation as the `count` elements
332  * at `device` on the CUDA Device.
333  *
334  * @throw OpenMPCD::NULLPointerException
335  * If OPENMPCD_DEBUG is defined, throws if `src == nullptr`.
336  * @throw OpenMPCD::NULLPointerException
337  * If OPENMPCD_DEBUG is defined, throws if `dest == nullptr`
338  * @throw OpenMPCD::InvalidArgumentException
339  * If OPENMPCD_DEBUG is defined,
340  * throws if `host` is not a Host pointer.
341  * @throw OpenMPCD::InvalidArgumentException
342  * If OPENMPCD_DEBUG is defined,
343  * throws if `device` is not a Device pointer.
344  * @throw OpenMPCD::InvalidArgumentException
345  * If OPENMPCD_DEBUG is defined, throws if `count == 0`.
346  *
347  * @tparam T The type of elements to copy.
348  *
349  * @param[in] host Pointer to the data on the Host.
350  * @param[out] device Pointer to the data on the CUDA Device.
351  * @param[in] count The number of elements of type `T` to compare,
352  * which must not be `0`.
353  */
354  template<typename T>
356  const T* const host, const T* const device,
357  const std::size_t count);
358 
359  private:
360  /**
361  * Allocates Device memory for the given number of instances of the
362  * supplied type, and registers it with this instance.
363  * The returned pointer points to at least
364  * `instanceCount * sizeof(Pointee)` bytes of allocated Device memory.
365  *
366  * @throw OpenMPCD::MemoryManagementException
367  * Throws if the buffer could not be allocated.
368  *
369  * @param[in] bufferSize The number of bytes to allocate at a minimum.
370  * If `0`, `nullptr` is returned.
371  */
372  void* allocateMemoryInternal(const std::size_t bufferSize);
373 
374  /**
375  * Allocates Device memory for the given number of instances of the
376  * supplied type, without registering it with this instance.
377  * The returned pointer points to at least
378  * `instanceCount * sizeof(Pointee)` bytes of allocated Device memory.
379  *
380  * @throw OpenMPCD::MemoryManagementException
381  * Throws if the buffer could not be allocated.
382  *
383  * @param[in] bufferSize The number of bytes to allocate at a minimum.
384  * If `0`, `nullptr` is returned.
385  */
386  static
387  void* allocateMemoryInternalUnregistered(const std::size_t bufferSize);
388 
389  private:
390  /**
391  * The assignment operator.
392  */
393  const DeviceMemoryManager operator=(const DeviceMemoryManager&);
394 
395  private:
396  std::set<const void*> allocatedBuffers; ///< Holds all pointers that are currently allocated.
397  bool autofree; ///< Whether to free all memory upon destruction of this instance.
398 }; //class DeviceMemoryManager
399 } //namespace CUDA
400 } //namespace OpenMPCD
401 
403 
404 #endif
Exceptions.hpp
OPENMPCD_THROW
#define OPENMPCD_THROW(ExceptionType, message)
Throws the given ExceptionType, passing the given message along with file and line number information...
Definition: Exceptions.hpp:22
OpenMPCD::CUDA::DeviceMemoryManager
Class for managing memory on the CUDA Device.
Definition: DeviceMemoryManager.hpp:21
OpenMPCD::CUDA::DeviceMemoryManager::isDeviceMemoryPointer
static bool isDeviceMemoryPointer(const void *const ptr)
Returns whether the given pointer is a pointer to CUDA Device memory.
Definition: DeviceMemoryManager.cpp:81
OpenMPCD::CUDA::DeviceMemoryManager::DeviceMemoryManager
DeviceMemoryManager()
The constructor.
Definition: DeviceMemoryManager.cpp:12
OpenMPCD::CUDA::DeviceMemoryManager::copyElementsFromHostToDevice
static void copyElementsFromHostToDevice(const T *const src, T *const dest, const std::size_t count)
Copies count elements of type T from the Host to the Device.
Definition: ImplementationDetails/DeviceMemoryManager.hpp:22
OpenMPCD::CUDA::DeviceMemoryManager::~DeviceMemoryManager
~DeviceMemoryManager()
The destructor.
Definition: DeviceMemoryManager.cpp:17
OpenMPCD::CUDA::DeviceMemoryManager::isHostMemoryPointer
static bool isHostMemoryPointer(const void *const ptr)
Returns whether the given pointer is a pointer to Host memory.
Definition: DeviceMemoryManager.cpp:105
OpenMPCD::CUDA::DeviceMemoryManager::setAutofree
void setAutofree(const bool enable)
Sets, or unsets, the autofree flag.
Definition: DeviceMemoryManager.hpp:207
OpenMPCD::CUDA::DeviceMemoryManager::allocateMemoryUnregistered
static Pointee * allocateMemoryUnregistered(const unsigned int instanceCount)
Allocates Device memory for the given number of instances of the supplied type.
Definition: DeviceMemoryManager.hpp:121
OpenMPCD::CUDA::DeviceMemoryManager::freeMemoryUnregistered
static void freeMemoryUnregistered(void *const pointer)
Frees the Device memory pointed to by the given pointer.
Definition: DeviceMemoryManager.cpp:53
OpenMPCD::CUDA::DeviceMemoryManager::copyElementsFromDeviceToDevice
static void copyElementsFromDeviceToDevice(const T *const src, T *const dest, const std::size_t count)
Copies count elements of type T from the Device to the Device.
Definition: ImplementationDetails/DeviceMemoryManager.hpp:66
OpenMPCD::CUDA::DeviceMemoryManager::freeMemory
void freeMemory(void *const pointer)
Frees the Device memory pointed to by the given pointer.
Definition: DeviceMemoryManager.cpp:40
OpenMPCD::CUDA::DeviceMemoryManager::zeroMemory
static void zeroMemory(T *const start, const std::size_t numberOfElements)
Writes zero-bytes to the given Device memory region.
Definition: ImplementationDetails/DeviceMemoryManager.hpp:88
OpenMPCD::CUDA::DeviceMemoryManager::allocateMemory
Pointee * allocateMemory(const unsigned int instanceCount)
Allocates Device memory for the given number of instances of the supplied type.
Definition: DeviceMemoryManager.hpp:62
DeviceMemoryManager.hpp
OpenMPCD::CUDA::DeviceMemoryManager::allocateMemory
void allocateMemory(Pointee **pointerToPointer, const unsigned int instanceCount)
Allocates Device memory for the given number of instances of the supplied type.
Definition: DeviceMemoryManager.hpp:91
OpenMPCD::CUDA::DeviceMemoryManager::allocateMemoryUnregistered
static void allocateMemoryUnregistered(Pointee **pointerToPointer, const unsigned int instanceCount)
Allocates Device memory for the given number of instances of the supplied type.
Definition: DeviceMemoryManager.hpp:154
OpenMPCD::CUDA::DeviceMemoryManager::copyElementsFromDeviceToHost
static void copyElementsFromDeviceToHost(const T *const src, T *const dest, const std::size_t count)
Copies count elements of type T from the Device to the Host.
Definition: ImplementationDetails/DeviceMemoryManager.hpp:44
OpenMPCD::CUDA::DeviceMemoryManager::elementMemoryEqualOnHostAndDevice
static bool elementMemoryEqualOnHostAndDevice(const T *const host, const T *const device, const std::size_t count)
Returns whether the count elements of type T at host in Host memory have the same byte-wise represent...
Definition: ImplementationDetails/DeviceMemoryManager.hpp:104
OpenMPCD::NULLPointerException
NULL-pointer exception.
Definition: Exceptions.hpp:96