Neko 1.99.6
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
hip_intf.F90
Go to the documentation of this file.
1! Copyright (c) 2021-2026, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
35 use utils, only : neko_error
36 use, intrinsic :: iso_c_binding
37 implicit none
38
39#ifdef HAVE_HIP
40
42 enum, bind(c)
43 enumerator :: hipsuccess = 0
44 enumerator :: hiperrorinvalidcontext = 1
45 enumerator :: hiperrorinvalidkernelfile = 2
46 enumerator :: hiperrormemoryallocation = 3
48 enumerator :: hiperrorlaunchfailure = 5
50 enumerator :: hiperrorinvaliddevice = 7
51 enumerator :: hiperrorinvalidvalue = 8
54 enumerator :: hiperrorunknown = 11
56 enumerator :: hiperrornotready = 13
57 enumerator :: hiperrornodevice = 14
60 enumerator :: hiperrorruntimememory = 17
61 enumerator :: hiperrorruntimeother = 18
65 enumerator :: hiperrortbd = 22
66 end enum
67
69 enum, bind(c)
70 enumerator :: hipmemcpyhosttohost = 0
71 enumerator :: hipmemcpyhosttodevice = 1
72 enumerator :: hipmemcpydevicetohost = 2
73 enumerator :: hipmemcpydevicetodevice = 3
74 enumerator :: hipmemcpydefault = 4
75 end enum
76
77 interface
78 integer(c_int) function hipmalloc(ptr_d, s) &
79 bind(c, name = 'hipMalloc')
80 use, intrinsic :: iso_c_binding
81 implicit none
82 type(c_ptr) :: ptr_d
83 integer(c_size_t), value :: s
84 end function hipmalloc
85
86 integer(c_int) function hipfree(ptr_d) &
87 bind(c, name = 'hipFree')
88 use, intrinsic :: iso_c_binding
89 implicit none
90 type(c_ptr), value :: ptr_d
91 end function hipfree
92
95 integer(c_int) function hipmap(ptr_d, ptr_h, s) &
96 bind(c, name = 'hip_map')
97 use, intrinsic :: iso_c_binding
98 implicit none
99 type(c_ptr) :: ptr_d
100 type(c_ptr), value :: ptr_h
101 integer(c_size_t), value :: s
102 end function hipmap
103
106 integer(c_int) function hipmapfree(ptr_d) &
107 bind(c, name = 'hip_map_free')
108 use, intrinsic :: iso_c_binding
109 implicit none
110 type(c_ptr), value :: ptr_d
111 end function hipmapfree
112
115 integer(c_int) function hipmapmemset(ptr_d, v, s, stream) &
116 bind(c, name = 'hip_map_memset')
117 use, intrinsic :: iso_c_binding
118 implicit none
119 type(c_ptr), value :: ptr_d
120 integer(c_int), value :: v
121 integer(c_size_t), value :: s
122 type(c_ptr), value :: stream
123 end function hipmapmemset
124
128 integer(c_int) function hipmapmemcpy(ptr_dst, ptr_src, s, dir, stream) &
129 bind(c, name = 'hip_map_memcpy')
130 use, intrinsic :: iso_c_binding
131 implicit none
132 type(c_ptr), value :: ptr_dst, ptr_src, stream
133 integer(c_size_t), value :: s
134 integer(c_int), value :: dir
135 end function hipmapmemcpy
136
137 integer(c_int) function hipmemcpy(ptr_dst, ptr_src, s, dir) &
138 bind(c, name = 'hipMemcpy')
139 use, intrinsic :: iso_c_binding
140 implicit none
141 type(c_ptr), value :: ptr_dst, ptr_src
142 integer(c_size_t), value :: s
143 integer(c_int), value :: dir
144 end function hipmemcpy
145
146 integer(c_int) function hipmemcpyasync(ptr_dst, ptr_src, s, dir, stream) &
147 bind(c, name = 'hipMemcpyAsync')
148 use, intrinsic :: iso_c_binding
149 implicit none
150 type(c_ptr), value :: ptr_dst, ptr_src, stream
151 integer(c_size_t), value :: s
152 integer(c_int), value :: dir
153 end function hipmemcpyasync
154
155 integer(c_int) function hipmemsetasync(ptr, v, s, stream) &
156 bind(c, name = 'hipMemsetAsync')
157 use, intrinsic :: iso_c_binding
158 implicit none
159 type(c_ptr), value :: ptr, stream
160 integer(c_int), value :: v
161 integer(c_size_t), value :: s
162 end function hipmemsetasync
163
164 integer(c_int) function hipdevicesynchronize() &
165 bind(c, name = 'hipDeviceSynchronize')
166 use, intrinsic :: iso_c_binding
167 implicit none
168 end function hipdevicesynchronize
169
170 integer(c_int) function hipdevicereset() &
171 bind(c, name = 'hipDeviceReset')
172 use, intrinsic :: iso_c_binding
173 implicit none
174 end function hipdevicereset
175
176 subroutine hip_buffer_free_all() &
177 bind(c, name = 'hip_buffer_free_all')
178 end subroutine hip_buffer_free_all
179
180 integer(c_int) function hipdevicegetname(name, len, device) &
181 bind(c, name = 'hipDeviceGetName')
182 use, intrinsic :: iso_c_binding
183 implicit none
184 type(c_ptr), value :: name
185 integer(c_int), value :: len
186 integer(c_int), value :: device
187 end function hipdevicegetname
188
189 integer(c_int) function hipgetdevicecount(amount) &
190 bind(c, name = 'hipGetDeviceCount')
191 use, intrinsic :: iso_c_binding
192 implicit none
193 integer(c_int) :: amount
194 end function hipgetdevicecount
195
196 integer(c_int) function hipstreamcreate(stream) &
197 bind(c, name = 'hipStreamCreate')
198 use, intrinsic :: iso_c_binding
199 implicit none
200 type(c_ptr) :: stream
201 end function hipstreamcreate
202
203 integer(c_int) function hipstreamcreatewithflags(stream, flags) &
204 bind(c, name = 'hipStreamCreateWithFlags')
205 use, intrinsic :: iso_c_binding
206 implicit none
207 type(c_ptr) :: stream
208 integer(c_int), value :: flags
209 end function hipstreamcreatewithflags
210
211 integer(c_int) function hipstreamcreatewithpriority(stream, flags, prio) &
212 bind(c, name = 'hipStreamCreateWithPriority')
213 use, intrinsic :: iso_c_binding
214 implicit none
215 type(c_ptr) :: stream
216 integer(c_int), value :: flags, prio
217 end function hipstreamcreatewithpriority
218
219 integer(c_int) function hipstreamdestroy(steam) &
220 bind(c, name = 'hipStreamDestroy')
221 use, intrinsic :: iso_c_binding
222 implicit none
223 type(c_ptr), value :: steam
224 end function hipstreamdestroy
225
226 integer(c_int) function hipstreamsynchronize(stream) &
227 bind(c, name = 'hipStreamSynchronize')
228 use, intrinsic :: iso_c_binding
229 implicit none
230 type(c_ptr), value :: stream
231 end function hipstreamsynchronize
232
233 integer(c_int) function hipstreamwaitevent(stream, event, flags) &
234 bind(c, name = 'hipStreamWaitEvent')
235 use, intrinsic :: iso_c_binding
236 implicit none
237 type(c_ptr), value :: stream, event
238 integer(c_int), value :: flags
239 end function hipstreamwaitevent
240
241 integer(c_int) function hipdevicegetstreampriorityrange(low_prio, &
242 high_prio) &
243 bind(c, name = 'hipDeviceGetStreamPriorityRange')
244 use, intrinsic :: iso_c_binding
245 implicit none
246 integer(c_int) :: low_prio, high_prio
248
249 integer(c_int) function hipeventcreate(event) &
250 bind(c, name = 'hipEventCreate')
251 use, intrinsic :: iso_c_binding
252 implicit none
253 type(c_ptr) :: event
254 end function hipeventcreate
255
256 integer(c_int) function hipeventdestroy(event) &
257 bind(c, name = 'hipEventDestroy')
258 use, intrinsic :: iso_c_binding
259 implicit none
260 type(c_ptr), value :: event
261 end function hipeventdestroy
262
263 integer(c_int) function hipeventcreatewithflags(event, flags) &
264 bind(c, name = 'hipEventCreateWithFlags')
265 use, intrinsic :: iso_c_binding
266 implicit none
267 type(c_ptr) :: event
268 integer(c_int), value :: flags
269 end function hipeventcreatewithflags
270
271 integer(c_int) function hipeventrecord(event, stream) &
272 bind(c, name = 'hipEventRecord')
273 use, intrinsic :: iso_c_binding
274 implicit none
275 type(c_ptr), value :: event, stream
276 end function hipeventrecord
277
278 integer(c_int) function hipeventsynchronize(event) &
279 bind(c, name = 'hipEventSynchronize')
280 use, intrinsic :: iso_c_binding
281 implicit none
282 type(c_ptr), value :: event
283 end function hipeventsynchronize
284 end interface
285
286contains
287
288 subroutine hip_init(glb_cmd_queue, aux_cmd_queue, &
289 STRM_HIGH_PRIO, STRM_LOW_PRIO)
290 type(c_ptr), intent(inout) :: glb_cmd_queue
291 type(c_ptr), intent(inout) :: aux_cmd_queue
292 integer, intent(inout) :: STRM_HIGH_PRIO
293 integer, intent(inout) :: STRM_LOW_PRIO
294
295 if (hipdevicegetstreampriorityrange(strm_low_prio, strm_high_prio) &
296 .ne. hipsuccess) then
297 call neko_error('Error retrieving stream priority range')
298 end if
299
300 if (hipstreamcreatewithpriority(glb_cmd_queue, 1, strm_high_prio) &
301 .ne. hipsuccess) then
302 call neko_error('Error creating main stream')
303 end if
304
305 if (hipstreamcreatewithpriority(aux_cmd_queue, 1, strm_low_prio) &
306 .ne. hipsuccess) then
307 call neko_error('Error creating main stream')
308 end if
309 end subroutine hip_init
310
311 subroutine hip_finalize(glb_cmd_queue, aux_cmd_queue)
312 type(c_ptr), intent(inout) :: glb_cmd_queue
313 type(c_ptr), intent(inout) :: aux_cmd_queue
314 integer :: ierr
315
316 ! Release all device buffers held by the device layer
318
319 if (hipstreamdestroy(glb_cmd_queue) .ne. hipsuccess) then
320 call neko_error('Error destroying main stream')
321 end if
322
323 if (hipstreamdestroy(aux_cmd_queue) .ne. hipsuccess) then
324 call neko_error('Error destroying aux stream')
325 end if
326
327 ierr = hipdevicesynchronize()
328
329 ! Best-effort context teardown to release runtime-owned allocations.
330 ! Skipped in pFUnit-enabled builds: unit tests cycle device
331 ! init/finalize with MPI still up, and device-aware communication
332 ! backends (GPU-aware MPI, RCCL) cache device state from first
333 ! use; resetting the device here would leave them with dangling
334 ! handles
335#ifndef HAVE_PFUNIT
336 ierr = hipdevicereset()
337#endif
338 end subroutine hip_finalize
339
340 subroutine hip_device_name(name)
341 character(len=*), intent(inout) :: name
342 character(kind=c_char, len=1024), target :: c_name
343 integer :: end_pos
344
345 if (hipdevicegetname(c_loc(c_name), 1024, 0) .ne. hipsuccess) then
346 call neko_error('Failed to query device')
347 end if
348
349 end_pos = scan(c_name, c_null_char)
350 if (end_pos .ge. 2) then
351 name(1:end_pos-1) = c_name(1:end_pos-1)
352 end if
353
354 end subroutine hip_device_name
355
357 integer function hip_device_count()
358 type(c_ptr) :: hip_count_ptr
359 integer :: amount
360
361 if (hipgetdevicecount(amount) .ne. hipsuccess) then
362 call neko_error('Failed to query device count')
363 end if
364
365 hip_device_count = amount
366 end function hip_device_count
367
368#endif
369
370end module hip_intf
Map host memory to the device (zero-copy on unified memory architectures, e.g. MI300A,...
Definition hip_intf.F90:95
Free a device pointer obtained from hipMap (no-op for pointers aliasing host memory)
Definition hip_intf.F90:106
Copy between device/host pointers via the mapping layer (kernel-based copy under zero-copy,...
Definition hip_intf.F90:128
Memset on a device pointer obtained from hipMap (host-side memset for pointers aliasing host memory)
Definition hip_intf.F90:115
Device abstraction, common interface for various accelerators.
Definition device.F90:34
Fortran HIP interface.
Definition hip_intf.F90:34
subroutine hip_device_name(name)
Definition hip_intf.F90:341
@ hipmemcpyhosttohost
Definition hip_intf.F90:70
@ hipmemcpydevicetohost
Definition hip_intf.F90:72
@ hipmemcpydefault
Definition hip_intf.F90:74
@ hipmemcpydevicetodevice
Definition hip_intf.F90:73
@ hipmemcpyhosttodevice
Definition hip_intf.F90:71
subroutine hip_init(glb_cmd_queue, aux_cmd_queue, strm_high_prio, strm_low_prio)
Definition hip_intf.F90:290
subroutine hip_finalize(glb_cmd_queue, aux_cmd_queue)
Definition hip_intf.F90:312
@ hiperrortbd
Definition hip_intf.F90:65
@ hiperrormapbufferobjectfailed
Definition hip_intf.F90:64
@ hiperrorinvaliddevicepointer
Definition hip_intf.F90:52
@ hiperrorlaunchfailure
Definition hip_intf.F90:48
@ hiperrorpeeraccessnotenabled
Definition hip_intf.F90:59
@ hiperrorinvalidkernelfile
Definition hip_intf.F90:45
@ hiperrorpeeraccessalreadyenabled
Definition hip_intf.F90:58
@ hiperrorinvalidresourcehandle
Definition hip_intf.F90:55
@ hiperrorhostmemorynotregistered
Definition hip_intf.F90:63
@ hiperrormemoryallocation
Definition hip_intf.F90:46
@ hiperrorruntimeother
Definition hip_intf.F90:61
@ hiperrorlaunchoutofresources
Definition hip_intf.F90:49
@ hiperrorinvalidmemcpydirection
Definition hip_intf.F90:53
@ hiperrornotready
Definition hip_intf.F90:56
@ hiperrorruntimememory
Definition hip_intf.F90:60
@ hiperrornodevice
Definition hip_intf.F90:57
@ hiperrorinvalidvalue
Definition hip_intf.F90:51
@ hiperrorinitializationerror
Definition hip_intf.F90:47
@ hiperrorinvaliddevice
Definition hip_intf.F90:50
@ hiperrorinvalidcontext
Definition hip_intf.F90:44
@ hiperrorhostmemoryalreadyregistered
Definition hip_intf.F90:62
@ hiperrorunknown
Definition hip_intf.F90:54
integer function hip_device_count()
Return the number of available HIP devices.
Definition hip_intf.F90:358
Utilities.
Definition utils.f90:35