(git:0de0cc2)
offload_api.F
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 ! **************************************************************************************************
9 !> \brief Fortran API for the offload package, which is written in C.
10 !> \author Ole Schuett
11 ! **************************************************************************************************
13  USE iso_c_binding, ONLY: c_associated,&
14  c_char,&
15  c_f_pointer,&
16  c_int,&
17  c_null_char,&
18  c_null_ptr,&
19  c_ptr,&
20  c_size_t
21  USE kinds, ONLY: dp,&
22  int_8
23 #include "../base/base_uses.f90"
24 
25  IMPLICIT NONE
26 
27  PRIVATE
28 
29  CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'offload_api'
30 
31  PUBLIC :: offload_init
32  PUBLIC :: offload_get_device_count
35  PUBLIC :: offload_buffer_type, offload_create_buffer, offload_free_buffer
37 
38  TYPE offload_buffer_type
39  REAL(KIND=dp), DIMENSION(:), CONTIGUOUS, POINTER :: host_buffer => null()
40  TYPE(C_PTR) :: c_ptr = c_null_ptr
41  END TYPE offload_buffer_type
42 
43 CONTAINS
44 
45 ! **************************************************************************************************
46 !> \brief allocate pinned memory.
47 !> \param buffer address of the buffer
48 !> \param length length of the buffer
49 !> \return 0
50 ! **************************************************************************************************
51  FUNCTION offload_malloc_pinned_mem(buffer, length) RESULT(res)
52  TYPE(c_ptr) :: buffer
53  INTEGER(C_SIZE_T), VALUE :: length
54  INTEGER :: res
55 
56  INTERFACE
57  FUNCTION offload_malloc_pinned_mem_c(buffer, length) &
58  BIND(C, name="offload_host_malloc")
59  IMPORT c_size_t, c_ptr, c_int
60  TYPE(c_ptr) :: buffer
61  INTEGER(C_SIZE_T), VALUE :: length
62  INTEGER(KIND=C_INT) :: offload_malloc_pinned_mem_c
63  END FUNCTION offload_malloc_pinned_mem_c
64  END INTERFACE
65 
66  res = offload_malloc_pinned_mem_c(buffer, length)
67  END FUNCTION offload_malloc_pinned_mem
68 
69 ! **************************************************************************************************
70 !> \brief free pinned memory
71 !> \param buffer address of the buffer
72 !> \return 0
73 ! **************************************************************************************************
74  FUNCTION offload_free_pinned_mem(buffer) RESULT(res)
75  TYPE(c_ptr), VALUE :: buffer
76  INTEGER :: res
77 
78  INTERFACE
79  FUNCTION offload_free_pinned_mem_c(buffer) &
80  BIND(C, name="offload_host_free")
81  IMPORT c_ptr, c_int
82  INTEGER(KIND=C_INT) :: offload_free_pinned_mem_c
83  TYPE(c_ptr), VALUE :: buffer
84  END FUNCTION offload_free_pinned_mem_c
85  END INTERFACE
86 
87  res = offload_free_pinned_mem_c(buffer)
88  END FUNCTION offload_free_pinned_mem
89 
90 ! **************************************************************************************************
91 !> \brief Initialize runtime.
92 !> \return ...
93 !> \author Rocco Meli
94 ! **************************************************************************************************
95  SUBROUTINE offload_init()
96  INTERFACE
97  SUBROUTINE offload_init_c() &
98  BIND(C, name="offload_init")
99  END SUBROUTINE offload_init_c
100  END INTERFACE
101 
102  CALL offload_init_c()
103 
104  END SUBROUTINE offload_init
105 
106 ! **************************************************************************************************
107 !> \brief Returns the number of available devices.
108 !> \return ...
109 !> \author Ole Schuett
110 ! **************************************************************************************************
111  FUNCTION offload_get_device_count() RESULT(count)
112  INTEGER :: count
113 
114  INTERFACE
115  FUNCTION offload_get_device_count_c() &
116  BIND(C, name="offload_get_device_count")
117  IMPORT :: c_int
118  INTEGER(KIND=C_INT) :: offload_get_device_count_c
119  END FUNCTION offload_get_device_count_c
120  END INTERFACE
121 
122  count = offload_get_device_count_c()
123 
124  END FUNCTION offload_get_device_count
125 
126 ! **************************************************************************************************
127 !> \brief Selects the chosen device to be used.
128 !> \param device_id ...
129 !> \author Ole Schuett
130 ! **************************************************************************************************
131  SUBROUTINE offload_set_chosen_device(device_id)
132  INTEGER, INTENT(IN) :: device_id
133 
134  INTERFACE
135  SUBROUTINE offload_set_chosen_device_c(device_id) &
136  BIND(C, name="offload_set_chosen_device")
137  IMPORT :: c_int
138  INTEGER(KIND=C_INT), VALUE :: device_id
139  END SUBROUTINE offload_set_chosen_device_c
140  END INTERFACE
141 
142  CALL offload_set_chosen_device_c(device_id=device_id)
143 
144  END SUBROUTINE offload_set_chosen_device
145 
146 ! **************************************************************************************************
147 !> \brief Returns the chosen device.
148 !> \return ...
149 !> \author Ole Schuett
150 ! **************************************************************************************************
151  FUNCTION offload_get_chosen_device() RESULT(device_id)
152  INTEGER :: device_id
153 
154  INTERFACE
155  FUNCTION offload_get_chosen_device_c() &
156  BIND(C, name="offload_get_chosen_device")
157  IMPORT :: c_int
158  INTEGER(KIND=C_INT) :: offload_get_chosen_device_c
159  END FUNCTION offload_get_chosen_device_c
160  END INTERFACE
161 
162  device_id = offload_get_chosen_device_c()
163 
164  IF (device_id < 0) &
165  cpabort("No offload device has been chosen.")
166 
167  END FUNCTION offload_get_chosen_device
168 
169 ! **************************************************************************************************
170 !> \brief Activates the device selected via offload_set_chosen_device()
171 !> \author Ole Schuett
172 ! **************************************************************************************************
174 
175  INTERFACE
176  SUBROUTINE offload_activate_chosen_device_c() &
177  BIND(C, name="offload_activate_chosen_device")
178  END SUBROUTINE offload_activate_chosen_device_c
179  END INTERFACE
180 
181  CALL offload_activate_chosen_device_c()
182 
183  END SUBROUTINE offload_activate_chosen_device
184 
185 ! **************************************************************************************************
186 !> \brief Starts a timing range.
187 !> \param routineN ...
188 !> \author Ole Schuett
189 ! **************************************************************************************************
190  SUBROUTINE offload_timeset(routineN)
191  CHARACTER(LEN=*), INTENT(IN) :: routinen
192 
193  INTERFACE
194  SUBROUTINE offload_timeset_c(message) BIND(C, name="offload_timeset")
195  IMPORT :: c_char
196  CHARACTER(kind=C_CHAR), DIMENSION(*), INTENT(IN) :: message
197  END SUBROUTINE offload_timeset_c
198  END INTERFACE
199 
200  CALL offload_timeset_c(trim(routinen)//c_null_char)
201 
202  END SUBROUTINE offload_timeset
203 
204 ! **************************************************************************************************
205 !> \brief Ends a timing range.
206 !> \author Ole Schuett
207 ! **************************************************************************************************
208  SUBROUTINE offload_timestop()
209 
210  INTERFACE
211  SUBROUTINE offload_timestop_c() BIND(C, name="offload_timestop")
212  END SUBROUTINE offload_timestop_c
213  END INTERFACE
214 
215  CALL offload_timestop_c()
216 
217  END SUBROUTINE offload_timestop
218 
219 ! **************************************************************************************************
220 !> \brief Gets free and total device memory.
221 !> \param free ...
222 !> \param total ...
223 !> \author Ole Schuett
224 ! **************************************************************************************************
225  SUBROUTINE offload_mem_info(free, total)
226  INTEGER(KIND=int_8), INTENT(OUT) :: free, total
227 
228  INTEGER(KIND=C_SIZE_T) :: my_free, my_total
229  INTERFACE
230  SUBROUTINE offload_mem_info_c(free, total) BIND(C, name="offload_mem_info")
231  IMPORT :: c_size_t
232  INTEGER(KIND=C_SIZE_T) :: free, total
233  END SUBROUTINE offload_mem_info_c
234  END INTERFACE
235 
236  CALL offload_mem_info_c(my_free, my_total)
237 
238  ! On 32-bit architectures this converts from int_4 to int_8.
239  free = my_free
240  total = my_total
241 
242  END SUBROUTINE offload_mem_info
243 
244 ! **************************************************************************************************
245 !> \brief Allocates a buffer of given length, ie. number of elements.
246 !> \param length ...
247 !> \param buffer ...
248 !> \author Ole Schuett
249 ! **************************************************************************************************
250  SUBROUTINE offload_create_buffer(length, buffer)
251  INTEGER, INTENT(IN) :: length
252  TYPE(offload_buffer_type), INTENT(INOUT) :: buffer
253 
254  CHARACTER(LEN=*), PARAMETER :: routinen = 'offload_create_buffer'
255 
256  INTEGER :: handle
257  TYPE(c_ptr) :: host_buffer_c
258  INTERFACE
259  SUBROUTINE offload_create_buffer_c(length, buffer) &
260  BIND(C, name="offload_create_buffer")
261  IMPORT :: c_ptr, c_int
262  INTEGER(KIND=C_INT), VALUE :: length
263  TYPE(c_ptr) :: buffer
264  END SUBROUTINE offload_create_buffer_c
265  END INTERFACE
266  INTERFACE
267 
268  FUNCTION offload_get_buffer_host_pointer_c(buffer) &
269  BIND(C, name="offload_get_buffer_host_pointer")
270  IMPORT :: c_ptr
271  TYPE(c_ptr), VALUE :: buffer
272  TYPE(c_ptr) :: offload_get_buffer_host_pointer_c
273  END FUNCTION offload_get_buffer_host_pointer_c
274  END INTERFACE
275 
276  CALL timeset(routinen, handle)
277 
278  IF (ASSOCIATED(buffer%host_buffer)) THEN
279  IF (SIZE(buffer%host_buffer) == 0) DEALLOCATE (buffer%host_buffer)
280  END IF
281 
282  CALL offload_create_buffer_c(length=length, buffer=buffer%c_ptr)
283  cpassert(c_associated(buffer%c_ptr))
284 
285  IF (length == 0) THEN
286  ! While C_F_POINTER usually accepts a NULL pointer it's not standard compliant.
287  ALLOCATE (buffer%host_buffer(0))
288  ELSE
289  host_buffer_c = offload_get_buffer_host_pointer_c(buffer%c_ptr)
290  cpassert(c_associated(host_buffer_c))
291  CALL c_f_pointer(host_buffer_c, buffer%host_buffer, shape=(/length/))
292  END IF
293 
294  CALL timestop(handle)
295  END SUBROUTINE offload_create_buffer
296 
297 ! **************************************************************************************************
298 !> \brief Deallocates given buffer.
299 !> \param buffer ...
300 !> \author Ole Schuett
301 ! **************************************************************************************************
302  SUBROUTINE offload_free_buffer(buffer)
303  TYPE(offload_buffer_type), INTENT(INOUT) :: buffer
304 
305  CHARACTER(LEN=*), PARAMETER :: routinen = 'offload_free_buffer'
306 
307  INTEGER :: handle
308  INTERFACE
309  SUBROUTINE offload_free_buffer_c(buffer) &
310  BIND(C, name="offload_free_buffer")
311  IMPORT :: c_ptr
312  TYPE(c_ptr), VALUE :: buffer
313  END SUBROUTINE offload_free_buffer_c
314  END INTERFACE
315 
316  CALL timeset(routinen, handle)
317 
318  IF (c_associated(buffer%c_ptr)) THEN
319 
320  CALL offload_free_buffer_c(buffer%c_ptr)
321 
322  buffer%c_ptr = c_null_ptr
323 
324  IF (SIZE(buffer%host_buffer) == 0) THEN
325  DEALLOCATE (buffer%host_buffer)
326  ELSE
327  NULLIFY (buffer%host_buffer)
328  END IF
329  END IF
330 
331  CALL timestop(handle)
332  END SUBROUTINE offload_free_buffer
333 END MODULE offload_api
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
Fortran API for the offload package, which is written in C.
Definition: offload_api.F:12
subroutine, public offload_timeset(routineN)
Starts a timing range.
Definition: offload_api.F:191
subroutine, public offload_set_chosen_device(device_id)
Selects the chosen device to be used.
Definition: offload_api.F:132
subroutine, public offload_free_buffer(buffer)
Deallocates given buffer.
Definition: offload_api.F:303
subroutine, public offload_activate_chosen_device()
Activates the device selected via offload_set_chosen_device()
Definition: offload_api.F:174
subroutine, public offload_timestop()
Ends a timing range.
Definition: offload_api.F:209
integer function, public offload_free_pinned_mem(buffer)
free pinned memory
Definition: offload_api.F:75
integer function, public offload_get_device_count()
Returns the number of available devices.
Definition: offload_api.F:112
subroutine, public offload_create_buffer(length, buffer)
Allocates a buffer of given length, ie. number of elements.
Definition: offload_api.F:251
integer function, public offload_malloc_pinned_mem(buffer, length)
allocate pinned memory.
Definition: offload_api.F:52
subroutine, public offload_init()
Initialize runtime.
Definition: offload_api.F:96
subroutine, public offload_mem_info(free, total)
Gets free and total device memory.
Definition: offload_api.F:226
integer function, public offload_get_chosen_device()
Returns the chosen device.
Definition: offload_api.F:152