Neko 1.99.9
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
198 integer(c_int) function hip_device_mp_count() &
199 bind(c, name = 'hip_device_mp_count')
200 use, intrinsic :: iso_c_binding
201 implicit none
202 end function hip_device_mp_count
203
206 integer(c_size_t) function hip_device_total_mem() &
207 bind(c, name = 'hip_device_total_mem')
208 use, intrinsic :: iso_c_binding
209 implicit none
210 end function hip_device_total_mem
211
212 integer(c_int) function hipstreamcreate(stream) &
213 bind(c, name = 'hipStreamCreate')
214 use, intrinsic :: iso_c_binding
215 implicit none
216 type(c_ptr) :: stream
217 end function hipstreamcreate
218
219 integer(c_int) function hipstreamcreatewithflags(stream, flags) &
220 bind(c, name = 'hipStreamCreateWithFlags')
221 use, intrinsic :: iso_c_binding
222 implicit none
223 type(c_ptr) :: stream
224 integer(c_int), value :: flags
225 end function hipstreamcreatewithflags
226
227 integer(c_int) function hipstreamcreatewithpriority(stream, flags, prio) &
228 bind(c, name = 'hipStreamCreateWithPriority')
229 use, intrinsic :: iso_c_binding
230 implicit none
231 type(c_ptr) :: stream
232 integer(c_int), value :: flags, prio
233 end function hipstreamcreatewithpriority
234
235 integer(c_int) function hipstreamdestroy(steam) &
236 bind(c, name = 'hipStreamDestroy')
237 use, intrinsic :: iso_c_binding
238 implicit none
239 type(c_ptr), value :: steam
240 end function hipstreamdestroy
241
242 integer(c_int) function hipstreamsynchronize(stream) &
243 bind(c, name = 'hipStreamSynchronize')
244 use, intrinsic :: iso_c_binding
245 implicit none
246 type(c_ptr), value :: stream
247 end function hipstreamsynchronize
248
249 integer(c_int) function hipstreamwaitevent(stream, event, flags) &
250 bind(c, name = 'hipStreamWaitEvent')
251 use, intrinsic :: iso_c_binding
252 implicit none
253 type(c_ptr), value :: stream, event
254 integer(c_int), value :: flags
255 end function hipstreamwaitevent
256
257 integer(c_int) function hipdevicegetstreampriorityrange(low_prio, &
258 high_prio) &
259 bind(c, name = 'hipDeviceGetStreamPriorityRange')
260 use, intrinsic :: iso_c_binding
261 implicit none
262 integer(c_int) :: low_prio, high_prio
264
265 integer(c_int) function hipeventcreate(event) &
266 bind(c, name = 'hipEventCreate')
267 use, intrinsic :: iso_c_binding
268 implicit none
269 type(c_ptr) :: event
270 end function hipeventcreate
271
272 integer(c_int) function hipeventdestroy(event) &
273 bind(c, name = 'hipEventDestroy')
274 use, intrinsic :: iso_c_binding
275 implicit none
276 type(c_ptr), value :: event
277 end function hipeventdestroy
278
279 integer(c_int) function hipeventcreatewithflags(event, flags) &
280 bind(c, name = 'hipEventCreateWithFlags')
281 use, intrinsic :: iso_c_binding
282 implicit none
283 type(c_ptr) :: event
284 integer(c_int), value :: flags
285 end function hipeventcreatewithflags
286
287 integer(c_int) function hipeventrecord(event, stream) &
288 bind(c, name = 'hipEventRecord')
289 use, intrinsic :: iso_c_binding
290 implicit none
291 type(c_ptr), value :: event, stream
292 end function hipeventrecord
293
294 integer(c_int) function hipeventsynchronize(event) &
295 bind(c, name = 'hipEventSynchronize')
296 use, intrinsic :: iso_c_binding
297 implicit none
298 type(c_ptr), value :: event
299 end function hipeventsynchronize
300 end interface
301
302contains
303
304 subroutine hip_init(glb_cmd_queue, aux_cmd_queue, &
305 STRM_HIGH_PRIO, STRM_LOW_PRIO)
306 type(c_ptr), intent(inout) :: glb_cmd_queue
307 type(c_ptr), intent(inout) :: aux_cmd_queue
308 integer, intent(inout) :: STRM_HIGH_PRIO
309 integer, intent(inout) :: STRM_LOW_PRIO
310
311 if (hipdevicegetstreampriorityrange(strm_low_prio, strm_high_prio) &
312 .ne. hipsuccess) then
313 call neko_error('Error retrieving stream priority range')
314 end if
315
316 if (hipstreamcreatewithpriority(glb_cmd_queue, 1, strm_high_prio) &
317 .ne. hipsuccess) then
318 call neko_error('Error creating main stream')
319 end if
320
321 if (hipstreamcreatewithpriority(aux_cmd_queue, 1, strm_low_prio) &
322 .ne. hipsuccess) then
323 call neko_error('Error creating main stream')
324 end if
325 end subroutine hip_init
326
327 subroutine hip_finalize(glb_cmd_queue, aux_cmd_queue)
328 type(c_ptr), intent(inout) :: glb_cmd_queue
329 type(c_ptr), intent(inout) :: aux_cmd_queue
330 integer :: ierr
331
332 ! Release all device buffers held by the device layer
334
335 if (hipstreamdestroy(glb_cmd_queue) .ne. hipsuccess) then
336 call neko_error('Error destroying main stream')
337 end if
338
339 if (hipstreamdestroy(aux_cmd_queue) .ne. hipsuccess) then
340 call neko_error('Error destroying aux stream')
341 end if
342
343 ierr = hipdevicesynchronize()
344
345 ! Best-effort context teardown to release runtime-owned allocations.
346 ! Skipped in pFUnit-enabled builds: unit tests cycle device
347 ! init/finalize with MPI still up, and device-aware communication
348 ! backends (GPU-aware MPI, RCCL) cache device state from first
349 ! use; resetting the device here would leave them with dangling
350 ! handles
351#ifndef HAVE_PFUNIT
352 ierr = hipdevicereset()
353#endif
354 end subroutine hip_finalize
355
356 subroutine hip_device_name(name)
357 character(len=*), intent(inout) :: name
358 character(kind=c_char, len=1024), target :: c_name
359 integer :: end_pos
360
361 if (hipdevicegetname(c_loc(c_name), 1024, 0) .ne. hipsuccess) then
362 call neko_error('Failed to query device')
363 end if
364
365 end_pos = scan(c_name, c_null_char)
366 if (end_pos .ge. 2) then
367 name(1:end_pos-1) = c_name(1:end_pos-1)
368 end if
369
370 end subroutine hip_device_name
371
373 integer function hip_device_count()
374 type(c_ptr) :: hip_count_ptr
375 integer :: amount
376
377 if (hipgetdevicecount(amount) .ne. hipsuccess) then
378 call neko_error('Failed to query device count')
379 end if
380
381 hip_device_count = amount
382 end function hip_device_count
383
384#endif
385
386end module hip_intf
Number of compute units of the current device (0 if unknown), see device/hip/props....
Definition hip_intf.F90:198
Total memory of the current device in bytes (0 if unknown), see device/hip/props.hip.
Definition hip_intf.F90:206
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:357
@ 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:306
subroutine hip_finalize(glb_cmd_queue, aux_cmd_queue)
Definition hip_intf.F90:328
@ 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:374
Utilities.
Definition utils.f90:35