(git:e7e05ae)
dbm_mempool.c
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* CP2K: A general program to perform molecular dynamics simulations */
3 /* Copyright 2000-2024 CP2K developers group <https://cp2k.org> */
4 /* */
5 /* SPDX-License-Identifier: BSD-3-Clause */
6 /*----------------------------------------------------------------------------*/
7 
8 #include <assert.h>
9 #include <omp.h>
10 #include <stddef.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 
14 #include "../offload/offload_library.h"
15 #include "../offload/offload_runtime.h"
16 #include "dbm_mempool.h"
17 
18 /*******************************************************************************
19  * \brief Private routine for actually allocating system memory.
20  * \author Ole Schuett
21  ******************************************************************************/
22 static void *actual_malloc(const size_t size, const bool on_device) {
23  (void)on_device; // mark used
24 
25 #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_DBM)
26  if (on_device) {
27  void *memory;
29  offloadMalloc(&memory, size);
30  assert(memory != NULL);
31  return memory;
32  }
33 #else
34  (void)on_device; // mark used
35 #endif
36 
37  void *memory = malloc(size);
38  assert(memory != NULL);
39  return memory;
40 }
41 
42 /*******************************************************************************
43  * \brief Private routine for actually freeing system memory.
44  * \author Ole Schuett
45  ******************************************************************************/
46 static void actual_free(void *memory, const bool on_device) {
47  if (memory == NULL) {
48  return;
49  }
50 
51 #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_DBM)
52  if (on_device) {
54  offloadFree(memory);
55  return;
56  }
57 #else
58  (void)on_device; // mark used
59 #endif
60 
61  free(memory);
62 }
63 
64 /*******************************************************************************
65  * \brief Private struct for storing a chunk of memory.
66  * \author Ole Schuett
67  ******************************************************************************/
68 struct dbm_memchunk {
69  bool on_device;
70  size_t size;
71  void *mem;
72  struct dbm_memchunk *next;
73 };
74 typedef struct dbm_memchunk dbm_memchunk_t;
75 
76 /*******************************************************************************
77  * \brief Private linked list of memory chunks that are available.
78  * \author Ole Schuett
79  ******************************************************************************/
81 
82 /*******************************************************************************
83  * \brief Private linked list of memory chunks that are in use.
84  * \author Ole Schuett
85  ******************************************************************************/
87 
88 /*******************************************************************************
89  * \brief Private routine for allocating host or device memory from the pool.
90  * \author Ole Schuett
91  ******************************************************************************/
92 static void *internal_mempool_malloc(const size_t size, const bool on_device) {
93  if (size == 0) {
94  return NULL;
95  }
96 
97  dbm_memchunk_t *chunk;
98 
99 #pragma omp critical(dbm_mempool_modify)
100  {
101  // Find a suitable chuck in mempool_available.
103  while (*indirect != NULL && (*indirect)->on_device != on_device) {
104  indirect = &(*indirect)->next;
105  }
106  chunk = *indirect;
107 
108  // If a chunck was found, remove it from mempool_available.
109  if (chunk != NULL) {
110  assert(chunk->on_device == on_device);
111  *indirect = chunk->next;
112  }
113 
114  // If no chunk was found, allocate a new one.
115  if (chunk == NULL) {
116  chunk = malloc(sizeof(dbm_memchunk_t));
117  chunk->on_device = on_device;
118  chunk->size = 0;
119  chunk->mem = NULL;
120  }
121 
122  // Resize chunk if needed.
123  if (chunk->size < size) {
124  actual_free(chunk->mem, chunk->on_device);
125  chunk->mem = actual_malloc(size, chunk->on_device);
126  chunk->size = size;
127  }
128 
129  // Insert chunk into mempool_allocated.
130  chunk->next = mempool_allocated_head;
131  mempool_allocated_head = chunk;
132  }
133 
134  return chunk->mem;
135 }
136 
137 /*******************************************************************************
138  * \brief Internal routine for allocating host memory from the pool.
139  * \author Ole Schuett
140  ******************************************************************************/
141 void *dbm_mempool_host_malloc(const size_t size) {
142  return internal_mempool_malloc(size, false);
143 }
144 
145 /*******************************************************************************
146  * \brief Internal routine for allocating device memory from the pool
147  * \author Ole Schuett
148  ******************************************************************************/
149 void *dbm_mempool_device_malloc(const size_t size) {
150  return internal_mempool_malloc(size, true);
151 }
152 
153 /*******************************************************************************
154  * \brief Internal routine for releasing memory back to the pool.
155  * \author Ole Schuett
156  ******************************************************************************/
157 void dbm_mempool_free(void *mem) {
158  if (mem == NULL) {
159  return;
160  }
161 
162 #pragma omp critical(dbm_mempool_modify)
163  {
164  // Find chuck in mempool_allocated.
166  while (*indirect != NULL && (*indirect)->mem != mem) {
167  indirect = &(*indirect)->next;
168  }
169  dbm_memchunk_t *chunk = *indirect;
170  assert(chunk != NULL && chunk->mem == mem);
171 
172  // Remove chuck from mempool_allocated.
173  *indirect = chunk->next;
174 
175  // Add chuck to mempool_available.
176  chunk->next = mempool_available_head;
177  mempool_available_head = chunk;
178  }
179 }
180 
181 /*******************************************************************************
182  * \brief Internal routine for freeing all memory in the pool.
183  * \author Ole Schuett
184  ******************************************************************************/
185 void dbm_mempool_clear(void) {
186  assert(omp_get_num_threads() == 1);
187  assert(mempool_allocated_head == NULL); // check for memory leak
188 
189  // while (mempool_allocated_head != NULL) {
190  // dbm_memchunk_t *chunk = mempool_allocated_head;
191  // mempool_allocated_head = chunk->next;
192  // printf("Found alloacted memory chunk of size: %lu\n", chunk->size);
193  // actual_free(chunk->mem, chunk->on_device);
194  // free(chunk);
195  //}
196 
197  // Free chunks in mempool_avavailable.
198  while (mempool_available_head != NULL) {
200  mempool_available_head = chunk->next;
201  actual_free(chunk->mem, chunk->on_device);
202  free(chunk);
203  }
204 }
205 
206 // EOF
static void actual_free(void *memory, const bool on_device)
Private routine for actually freeing system memory.
Definition: dbm_mempool.c:46
void * dbm_mempool_device_malloc(const size_t size)
Internal routine for allocating device memory from the pool.
Definition: dbm_mempool.c:149
void dbm_mempool_clear(void)
Internal routine for freeing all memory in the pool.
Definition: dbm_mempool.c:185
void dbm_mempool_free(void *mem)
Internal routine for releasing memory back to the pool.
Definition: dbm_mempool.c:157
static void * internal_mempool_malloc(const size_t size, const bool on_device)
Private routine for allocating host or device memory from the pool.
Definition: dbm_mempool.c:92
static dbm_memchunk_t * mempool_available_head
Private linked list of memory chunks that are available.
Definition: dbm_mempool.c:80
static void * actual_malloc(const size_t size, const bool on_device)
Private routine for actually allocating system memory.
Definition: dbm_mempool.c:22
void * dbm_mempool_host_malloc(const size_t size)
Internal routine for allocating host memory from the pool.
Definition: dbm_mempool.c:141
static dbm_memchunk_t * mempool_allocated_head
Private linked list of memory chunks that are in use.
Definition: dbm_mempool.c:86
subroutine, public offload_activate_chosen_device()
Activates the device selected via offload_set_chosen_device()
Definition: offload_api.F:174
Private struct for storing a chunk of memory.
Definition: dbm_mempool.c:68
void * mem
Definition: dbm_mempool.c:71
size_t size
Definition: dbm_mempool.c:70
bool on_device
Definition: dbm_mempool.c:69
struct dbm_memchunk * next
Definition: dbm_mempool.c:72