(git:d3d49ac)
Loading...
Searching...
No Matches
offload_api.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: BSD-3-Clause !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Fortran API for the offload package, which is written in C.
10!> \author Ole Schuett
11! **************************************************************************************************
13 USE iso_c_binding, ONLY: &
14 c_associated, c_char, c_funloc, c_funptr, c_f_pointer, c_int, c_null_char, c_null_ptr, &
15 c_ptr, c_size_t
16 USE kinds, ONLY: dp,&
17 int_8
19#include "../base/base_uses.f90"
20
21 IMPLICIT NONE
22
23 PRIVATE
24
25 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'offload_api'
26
27 PUBLIC :: offload_init
34
36 REAL(kind=dp), DIMENSION(:), CONTIGUOUS, POINTER :: host_buffer => null()
37 TYPE(c_ptr) :: c_ptr = c_null_ptr
38 END TYPE offload_buffer_type
39
40CONTAINS
41
42! **************************************************************************************************
43!> \brief allocate pinned memory.
44!> \param buffer address of the buffer
45!> \param length length of the buffer
46!> \return 0
47! **************************************************************************************************
48 FUNCTION offload_malloc_pinned_mem(buffer, length) RESULT(res)
49 TYPE(c_ptr) :: buffer
50 INTEGER(C_SIZE_T), VALUE :: length
51 INTEGER :: res
52
53 INTERFACE
54 FUNCTION offload_malloc_pinned_mem_c(buffer, length) &
55 BIND(C, name="offload_host_malloc")
56 IMPORT c_size_t, c_ptr, c_int
57 TYPE(c_ptr) :: buffer
58 INTEGER(C_SIZE_T), VALUE :: length
59 INTEGER(KIND=C_INT) :: offload_malloc_pinned_mem_c
60 END FUNCTION offload_malloc_pinned_mem_c
61 END INTERFACE
62
63 res = offload_malloc_pinned_mem_c(buffer, length)
64 END FUNCTION offload_malloc_pinned_mem
65
66! **************************************************************************************************
67!> \brief free pinned memory
68!> \param buffer address of the buffer
69!> \return 0
70! **************************************************************************************************
71 FUNCTION offload_free_pinned_mem(buffer) RESULT(res)
72 TYPE(c_ptr), VALUE :: buffer
73 INTEGER :: res
74
75 INTERFACE
76 FUNCTION offload_free_pinned_mem_c(buffer) &
77 BIND(C, name="offload_host_free")
78 IMPORT c_ptr, c_int
79 INTEGER(KIND=C_INT) :: offload_free_pinned_mem_c
80 TYPE(c_ptr), VALUE :: buffer
81 END FUNCTION offload_free_pinned_mem_c
82 END INTERFACE
83
84 res = offload_free_pinned_mem_c(buffer)
85 END FUNCTION offload_free_pinned_mem
86
87! **************************************************************************************************
88!> \brief Initialize runtime.
89!> \return ...
90!> \author Rocco Meli
91! **************************************************************************************************
92 SUBROUTINE offload_init()
93 INTERFACE
94 SUBROUTINE offload_init_c() &
95 BIND(C, name="offload_init")
96 END SUBROUTINE offload_init_c
97 END INTERFACE
98
99 CALL offload_init_c()
100
101 END SUBROUTINE offload_init
102
103! **************************************************************************************************
104!> \brief Returns the number of available devices.
105!> \return ...
106!> \author Ole Schuett
107! **************************************************************************************************
108 FUNCTION offload_get_device_count() RESULT(count)
109 INTEGER :: count
110
111 INTERFACE
112 FUNCTION offload_get_device_count_c() &
113 BIND(C, name="offload_get_device_count")
114 IMPORT :: c_int
115 INTEGER(KIND=C_INT) :: offload_get_device_count_c
116 END FUNCTION offload_get_device_count_c
117 END INTERFACE
118
119 count = offload_get_device_count_c()
120
121 END FUNCTION offload_get_device_count
122
123! **************************************************************************************************
124!> \brief Selects the chosen device to be used.
125!> \param device_id ...
126!> \author Ole Schuett
127! **************************************************************************************************
128 SUBROUTINE offload_set_chosen_device(device_id)
129 INTEGER, INTENT(IN) :: device_id
130
131 INTERFACE
132 SUBROUTINE offload_set_chosen_device_c(device_id) &
133 BIND(C, name="offload_set_chosen_device")
134 IMPORT :: c_int
135 INTEGER(KIND=C_INT), VALUE :: device_id
136 END SUBROUTINE offload_set_chosen_device_c
137 END INTERFACE
138
139 CALL offload_set_chosen_device_c(device_id=device_id)
140
141 END SUBROUTINE offload_set_chosen_device
142
143! **************************************************************************************************
144!> \brief Returns the chosen device.
145!> \return ...
146!> \author Ole Schuett
147! **************************************************************************************************
148 FUNCTION offload_get_chosen_device() RESULT(device_id)
149 INTEGER :: device_id
150
151 INTERFACE
152 FUNCTION offload_get_chosen_device_c() &
153 BIND(C, name="offload_get_chosen_device")
154 IMPORT :: c_int
155 INTEGER(KIND=C_INT) :: offload_get_chosen_device_c
156 END FUNCTION offload_get_chosen_device_c
157 END INTERFACE
158
159 device_id = offload_get_chosen_device_c()
160
161 IF (device_id < 0) THEN
162 cpabort("No offload device has been chosen.")
163 END IF
164
165 END FUNCTION offload_get_chosen_device
166
167! **************************************************************************************************
168!> \brief Activates the device selected via offload_set_chosen_device()
169!> \author Ole Schuett
170! **************************************************************************************************
172
173 INTERFACE
174 SUBROUTINE offload_activate_chosen_device_c() &
175 BIND(C, name="offload_activate_chosen_device")
176 END SUBROUTINE offload_activate_chosen_device_c
177 END INTERFACE
178
179 CALL offload_activate_chosen_device_c()
180
181 END SUBROUTINE offload_activate_chosen_device
182
183! **************************************************************************************************
184!> \brief Starts a timing range.
185!> \param routineN ...
186!> \author Ole Schuett
187! **************************************************************************************************
188 SUBROUTINE offload_timeset(routineN)
189 CHARACTER(LEN=*), INTENT(IN) :: routinen
190
191 INTERFACE
192 SUBROUTINE offload_timeset_c(message) BIND(C, name="offload_timeset")
193 IMPORT :: c_char
194 CHARACTER(kind=C_CHAR), DIMENSION(*), INTENT(IN) :: message
195 END SUBROUTINE offload_timeset_c
196 END INTERFACE
197
198 CALL offload_timeset_c(trim(routinen)//c_null_char)
199
200 END SUBROUTINE offload_timeset
201
202! **************************************************************************************************
203!> \brief Ends a timing range.
204!> \author Ole Schuett
205! **************************************************************************************************
206 SUBROUTINE offload_timestop()
207
208 INTERFACE
209 SUBROUTINE offload_timestop_c() BIND(C, name="offload_timestop")
210 END SUBROUTINE offload_timestop_c
211 END INTERFACE
212
213 CALL offload_timestop_c()
214
215 END SUBROUTINE offload_timestop
216
217! **************************************************************************************************
218!> \brief Gets free and total device memory.
219!> \param free ...
220!> \param total ...
221!> \author Ole Schuett
222! **************************************************************************************************
223 SUBROUTINE offload_mem_info(free, total)
224 INTEGER(KIND=int_8), INTENT(OUT) :: free, total
225
226 INTEGER(KIND=C_SIZE_T) :: my_free, my_total
227 INTERFACE
228 SUBROUTINE offload_mem_info_c(free, total) BIND(C, name="offload_mem_info")
229 IMPORT :: c_size_t
230 INTEGER(KIND=C_SIZE_T) :: free, total
231 END SUBROUTINE offload_mem_info_c
232 END INTERFACE
233
234 CALL offload_mem_info_c(my_free, my_total)
235
236 ! On 32-bit architectures this converts from int_4 to int_8.
237 free = my_free
238 total = my_total
239
240 END SUBROUTINE offload_mem_info
241
242! **************************************************************************************************
243!> \brief Allocates a buffer of given length, ie. number of elements.
244!> \param length ...
245!> \param buffer ...
246!> \author Ole Schuett
247! **************************************************************************************************
248 SUBROUTINE offload_create_buffer(length, buffer)
249 INTEGER, INTENT(IN) :: length
250 TYPE(offload_buffer_type), INTENT(INOUT) :: buffer
251
252 CHARACTER(LEN=*), PARAMETER :: routinen = 'offload_create_buffer'
253
254 INTEGER :: handle
255 TYPE(c_ptr) :: host_buffer_c
256 INTERFACE
257 SUBROUTINE offload_create_buffer_c(length, buffer) &
258 BIND(C, name="offload_create_buffer")
259 IMPORT :: c_ptr, c_int
260 INTEGER(KIND=C_INT), VALUE :: length
261 TYPE(c_ptr) :: buffer
262 END SUBROUTINE offload_create_buffer_c
263 END INTERFACE
264 INTERFACE
265 FUNCTION offload_get_buffer_host_pointer_c(buffer) &
266 BIND(C, name="offload_get_buffer_host_pointer")
267 IMPORT :: c_ptr
268 TYPE(c_ptr), VALUE :: buffer
269 TYPE(c_ptr) :: offload_get_buffer_host_pointer_c
270 END FUNCTION offload_get_buffer_host_pointer_c
271 END INTERFACE
272
273 CALL timeset(routinen, handle)
274
275 IF (ASSOCIATED(buffer%host_buffer)) THEN
276 IF (SIZE(buffer%host_buffer) == 0) DEALLOCATE (buffer%host_buffer)
277 IF (ASSOCIATED(buffer%host_buffer)) NULLIFY (buffer%host_buffer)
278 END IF
279
280 CALL offload_create_buffer_c(length=length, buffer=buffer%c_ptr)
281 cpassert(c_associated(buffer%c_ptr))
282
283 IF (length == 0) THEN
284 ! While C_F_POINTER usually accepts a NULL pointer it's not standard compliant.
285 ALLOCATE (buffer%host_buffer(0))
286 ELSE
287 host_buffer_c = offload_get_buffer_host_pointer_c(buffer%c_ptr)
288 cpassert(c_associated(host_buffer_c))
289 CALL c_f_pointer(host_buffer_c, buffer%host_buffer, shape=[length])
290 END IF
291
292 CALL timestop(handle)
293 END SUBROUTINE offload_create_buffer
294
295! **************************************************************************************************
296!> \brief Deallocates given buffer.
297!> \param buffer ...
298!> \author Ole Schuett
299! **************************************************************************************************
300 SUBROUTINE offload_free_buffer(buffer)
301 TYPE(offload_buffer_type), INTENT(INOUT) :: buffer
302
303 CHARACTER(LEN=*), PARAMETER :: routinen = 'offload_free_buffer'
304
305 INTEGER :: handle
306 INTERFACE
307 SUBROUTINE offload_free_buffer_c(buffer) &
308 BIND(C, name="offload_free_buffer")
309 IMPORT :: c_ptr
310 TYPE(c_ptr), VALUE :: buffer
311 END SUBROUTINE offload_free_buffer_c
312 END INTERFACE
313
314 CALL timeset(routinen, handle)
315
316 IF (c_associated(buffer%c_ptr)) THEN
317
318 CALL offload_free_buffer_c(buffer%c_ptr)
319
320 buffer%c_ptr = c_null_ptr
321
322 IF (SIZE(buffer%host_buffer) == 0) THEN
323 DEALLOCATE (buffer%host_buffer)
324 ELSE
325 NULLIFY (buffer%host_buffer)
326 END IF
327 END IF
328
329 CALL timestop(handle)
330 END SUBROUTINE offload_free_buffer
331
332! **************************************************************************************************
333!> \brief Print allocation statistics.
334!> \param mpi_comm ...
335!> \param output_unit ...
336!> \author Ole Schuett
337! **************************************************************************************************
338 SUBROUTINE offload_mempool_stats_print(mpi_comm, output_unit)
339 TYPE(mp_comm_type), INTENT(IN) :: mpi_comm
340 INTEGER, INTENT(IN) :: output_unit
341
342 INTERFACE
343 SUBROUTINE offload_mempool_stats_print_c(mpi_comm, print_func, output_unit) &
344 BIND(C, name="offload_mempool_stats_print")
345 IMPORT :: c_funptr, c_int
346 INTEGER(KIND=C_INT), VALUE :: mpi_comm
347 TYPE(c_funptr), VALUE :: print_func
348 INTEGER(KIND=C_INT), VALUE :: output_unit
349 END SUBROUTINE offload_mempool_stats_print_c
350 END INTERFACE
351
352 ! Since Fortran units groups can't be used from C, we pass a function pointer instead.
353 CALL offload_mempool_stats_print_c(mpi_comm=mpi_comm%get_handle(), &
354 print_func=c_funloc(print_func), &
355 output_unit=output_unit)
356
357 END SUBROUTINE offload_mempool_stats_print
358
359! **************************************************************************************************
360!> \brief Callback to write to a Fortran output unit (called by C-side).
361!> \param msg to be printed.
362!> \param msglen number of characters excluding the terminating character.
363!> \param output_unit used for output.
364!> \author Hans Pabst
365! **************************************************************************************************
366 SUBROUTINE print_func(msg, msglen, output_unit) BIND(C, name="offload_api_print_func")
367 CHARACTER(KIND=C_CHAR), INTENT(IN) :: msg(*)
368 INTEGER(KIND=C_INT), INTENT(IN), VALUE :: msglen, output_unit
369
370 IF (output_unit <= 0) RETURN ! Omit to print the message.
371 WRITE (output_unit, fmt="(100A)", advance="NO") msg(1:msglen)
372 END SUBROUTINE print_func
373END MODULE offload_api
static void print_func(const char *msg, int msglen, int output_unit)
Wrapper for printf, passed to dbm_library_print_stats.
Definition dbm_miniapp.c:25
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public int_8
Definition kinds.F:54
integer, parameter, public dp
Definition kinds.F:34
Interface to the message passing library MPI.
Fortran API for the offload package, which is written in C.
Definition offload_api.F:12
subroutine, public offload_set_chosen_device(device_id)
Selects the chosen device to be used.
subroutine, public offload_free_buffer(buffer)
Deallocates given buffer.
subroutine, public offload_activate_chosen_device()
Activates the device selected via offload_set_chosen_device()
subroutine, public offload_timestop()
Ends a timing range.
integer function, public offload_free_pinned_mem(buffer)
free pinned memory
Definition offload_api.F:72
subroutine, public offload_timeset(routinen)
Starts a timing range.
integer function, public offload_get_device_count()
Returns the number of available devices.
subroutine, public offload_create_buffer(length, buffer)
Allocates a buffer of given length, ie. number of elements.
integer function, public offload_malloc_pinned_mem(buffer, length)
allocate pinned memory.
Definition offload_api.F:49
subroutine, public offload_init()
Initialize runtime.
Definition offload_api.F:93
subroutine, public offload_mem_info(free, total)
Gets free and total device memory.
subroutine, public offload_mempool_stats_print(mpi_comm, output_unit)
Print allocation statistics.
integer function, public offload_get_chosen_device()
Returns the chosen device.