Neko 1.99.1
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
opencl_intf.F90
Go to the documentation of this file.
1! Copyright (c) 2021-2025, 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 num_types, only : i8
36 use utils, only : neko_error
37 use, intrinsic :: iso_c_binding
38 implicit none
39
40#ifdef HAVE_OPENCL
41
43 type(c_ptr), bind(c) :: glb_ctx = c_null_ptr
44
46 type(c_ptr), bind(c), target :: glb_device_id = c_null_ptr
47
49 enum, bind(c)
50 enumerator :: cl_success = 0
51 enumerator :: cl_device_not_found = -1
52 enumerator :: cl_device_not_available = -2
53 enumerator :: cl_compiler_not_available = -3
55 enumerator :: cl_out_of_resources = -5
56 enumerator :: cl_out_of_host_memory = -6
58 enumerator :: cl_mem_copy_overlap = -8
59 enumerator :: cl_image_format_mismatch = -9
61 enumerator :: cl_build_program_failure = -11
62 enumerator :: cl_map_failure = -12
63 end enum
64
66 enum, bind(c)
67 enumerator :: cl_mem_read_write = 1
68 enumerator :: cl_mem_write_only = 2
69 enumerator :: cl_mem_read_only = 4
70 enumerator :: cl_mem_use_host_ptr = 8
71 enumerator :: cl_mem_alloc_host_ptr = 16
72 enumerator :: cl_mem_host_write_only = 128
73 enumerator :: cl_mem_host_read_only = 256
74 enumerator :: cl_mem_host_no_access = 512
75 end enum
76
78 enum, bind(c)
79 enumerator :: cl_complete = 0
80 enumerator :: cl_running = 1
81 enumerator :: cl_submitted = 2
82 enumerator :: cl_queued = 3
83 end enum
84
86 enum, bind(c)
87 enumerator :: cl_false = 0
88 enumerator :: cl_true = 1
89 end enum
90
91 enum, bind(c)
92 enumerator :: cl_context_platform = int(z'1084')
93 end enum
94
96 enum, bind(c)
97 enumerator :: cl_device_name = 4139
98 end enum
99
101 integer(c_int64_t), parameter :: cl_device_type_default = 1
102 integer(c_int64_t), parameter :: cl_device_type_cpu = 2
103 integer(c_int64_t), parameter :: cl_device_type_gpu = 4
104 integer(c_int64_t), parameter :: cl_device_type_accelerator = 8
105 integer(c_int64_t), parameter :: cl_device_type_custom = 16
106 integer(c_int64_t), parameter :: cl_device_type_all = int(z'FFFFFFFF', i8)
107
109 integer(c_int64_t), parameter :: cl_queue_out_of_order_exec_mode_enable = 1
110 integer(c_int64_t), parameter :: cl_queue_profiling_enable = 2
111
112 interface
113 integer(c_int) function clgetplatformids(num_entries, platforms, &
114 num_platforms) bind(c, name = 'clGetPlatformIDs')
115 use, intrinsic :: iso_c_binding
116 implicit none
117 integer(c_int), value :: num_entries
118 type(c_ptr), value :: platforms
119 integer(c_int) :: num_platforms
120 end function clgetplatformids
121 end interface
122
123 interface
124 integer(c_int) function clgetdeviceids(platform, device_type, &
125 num_entries, devices, num_devices) bind(c, name = 'clGetDeviceIDs')
126 use, intrinsic :: iso_c_binding
127 implicit none
128 type(c_ptr), value :: platform
129 integer(c_int64_t), value :: device_type
130 integer(c_int), value :: num_entries
131 type(c_ptr), value :: devices
132 integer(c_int) :: num_devices
133 end function clgetdeviceids
134 end interface
135
136 interface
137 type (c_ptr) function clcreatecontext(properties, num_devices, devices, &
138 pfn_notify, user_data, ierr) bind(c, name = 'clCreateContext')
139 use, intrinsic :: iso_c_binding
140 implicit none
141 type(c_ptr), value :: properties
142 integer(c_int), value :: num_devices
143 type(c_ptr), value :: devices
144 type(c_funptr), value :: pfn_notify
145 type(c_ptr), value :: user_data
146 integer(c_int) :: ierr
147 end function clcreatecontext
148 end interface
149
150 interface
151 type(c_ptr) function clcreatecommandqueue(context, device, &
152 properties, ierr) bind(c, name = 'clCreateCommandQueue')
153 use, intrinsic :: iso_c_binding
154 implicit none
155 type(c_ptr), value :: context
156 type(c_ptr), value :: device
157 integer(c_int64_t), value :: properties
158 integer(c_int) :: ierr
159 end function clcreatecommandqueue
160 end interface
161
162 interface
163 type(c_ptr) function clcreatebuffer(context, flags, size, host_ptr, ierr) &
164 bind(c, name = 'clCreateBuffer')
165 use, intrinsic :: iso_c_binding
166 implicit none
167 type(c_ptr), value :: context
168 integer(c_int), value :: flags
169 integer(c_size_t), value :: size
170 type(c_ptr), value :: host_ptr
171 integer(c_int) :: ierr
172 end function clcreatebuffer
173 end interface
174
175 interface
176 type(c_ptr) function clcreateuserevent(context, ierr) &
177 bind(c, name = 'clCreateUserEvent')
178 use, intrinsic :: iso_c_binding
179 implicit none
180 type(c_ptr), value :: context
181 integer(c_int) :: ierr
182 end function clcreateuserevent
183 end interface
184
185 interface
186 integer(c_int) function clenqueuereadbuffer(queue, buffer, blocking_read, &
187 offset, size, ptr, num_events_in_wait_list, event_wait_list, event) &
188 bind(c, name = 'clEnqueueReadBuffer')
189 use, intrinsic :: iso_c_binding
190 implicit none
191 type(c_ptr), value :: queue
192 type(c_ptr), value :: buffer
193 integer(c_int), value :: blocking_read
194 integer(c_size_t), value :: offset
195 integer(c_size_t), value :: size
196 type(c_ptr), value :: ptr
197 integer(c_int), value :: num_events_in_wait_list
198 type(c_ptr), value :: event_wait_list
199 type(c_ptr), value :: event
200 end function clenqueuereadbuffer
201 end interface
202
203 interface
204 integer(c_int) function clenqueuewritebuffer(queue, buffer, &
205 blocking_write, offset, size, ptr, num_events_in_wait_list, &
206 event_wait_list, event) bind(c, name = 'clEnqueueWriteBuffer')
207 use, intrinsic :: iso_c_binding
208 implicit none
209 type(c_ptr), value :: queue
210 type(c_ptr), value :: buffer
211 integer(c_int), value :: blocking_write
212 integer(c_size_t), value :: offset
213 integer(c_size_t), value :: size
214 type(c_ptr), value :: ptr
215 integer(c_int), value :: num_events_in_wait_list
216 type(c_ptr), value :: event_wait_list
217 type(c_ptr), value :: event
218 end function clenqueuewritebuffer
219 end interface
220
221 interface
222 integer(c_int) function clenqueuecopybuffer(queue, src_buffer, &
223 dst_buffer, src_offset, dst_offset, size, num_events_in_wait_list, &
224 event_wait_list, event) bind(c, name = 'clEnqueueCopyBuffer')
225 use, intrinsic :: iso_c_binding
226 implicit none
227 type(c_ptr), value :: queue
228 type(c_ptr), value :: src_buffer
229 type(c_ptr), value :: dst_buffer
230 integer(c_size_t), value :: src_offset
231 integer(c_size_t), value :: dst_offset
232 integer(c_size_t), value :: size
233 integer(c_int), value :: num_events_in_wait_list
234 type(c_ptr), value :: event_wait_list
235 type(c_ptr), value :: event
236 end function clenqueuecopybuffer
237 end interface
238
239 interface
240 integer(c_int) function clenqueuefillbuffer(queue, buffer, &
241 pattern, pattern_size, offset, size, num_events_in_wait_list, &
242 event_wait_list, event) bind(c, name = 'clEnqueueFillBuffer')
243 use, intrinsic :: iso_c_binding
244 implicit none
245 type(c_ptr), value :: queue
246 type(c_ptr), value :: buffer
247 type(c_ptr), value :: pattern
248 integer(c_size_t), value :: pattern_size
249 integer(c_size_t), value :: offset
250 integer(c_size_t), value :: size
251 integer(c_int), value :: num_events_in_wait_list
252 type(c_ptr), value :: event_wait_list
253 type(c_ptr), value :: event
254 end function clenqueuefillbuffer
255 end interface
256
257 interface
258 integer(c_int) function clenqueuemarkerwithwaitlist &
259 (queue, num_events_in_wait_list, event_wait_list, event) &
260 bind(c, name = 'clEnqueueMarkerWithWaitList')
261 use, intrinsic :: iso_c_binding
262 implicit none
263 type(c_ptr), value :: queue
264 integer(c_int), value :: num_events_in_wait_list
265 type(c_ptr), value :: event_wait_list
266 type(c_ptr), value :: event
267 end function clenqueuemarkerwithwaitlist
268 end interface
269
270 interface
271 integer(c_int) function clenqueuemarker(cmd_queue, event) &
272 bind(c, name = 'clEnqueueMarker')
273 use, intrinsic :: iso_c_binding
274 implicit none
275 type(c_ptr), value :: cmd_queue
276 type(c_ptr), value :: event
277 end function clenqueuemarker
278 end interface
279
280 interface
281 integer(c_int) function clenqueuebarrier(cmd_queue) &
282 bind(c, name = 'clEnqueueBarrier')
283 use, intrinsic :: iso_c_binding
284 implicit none
285 type(c_ptr), value :: cmd_queue
286 end function clenqueuebarrier
287 end interface
288
289 interface
290 integer(c_int) function clenqueuewaitforevents(queue, &
291 num_events, event_list) bind(c, name = 'clEnqueueWaitForEvents')
292 use, intrinsic :: iso_c_binding
293 implicit none
294 type(c_ptr), value :: queue
295 integer(c_int), value :: num_events
296 type(c_ptr), value :: event_list
297 end function clenqueuewaitforevents
298 end interface
299
300 interface
301 integer(c_int) function clwaitforevents(num_events, event_list) &
302 bind(c, name = 'clWaitForEvents')
303 use, intrinsic :: iso_c_binding
304 implicit none
305 integer(c_int), value :: num_events
306 type(c_ptr), value :: event_list
307 end function clwaitforevents
308 end interface
309
310 interface
311 integer(c_int) function clsetusereventstatus(event, status) &
312 bind(c, name = 'clSetUserEventStatus')
313 use, intrinsic :: iso_c_binding
314 implicit none
315 type(c_ptr), value :: event
316 integer(c_int), value :: status
317 end function clsetusereventstatus
318 end interface
319
320 interface
321 integer(c_int) function clgetdeviceinfo(device, param_name, &
322 param_value_size, param_value, param_value_size_ret) &
323 bind(c, name = 'clGetDeviceInfo')
324 use, intrinsic :: iso_c_binding
325 implicit none
326 type(c_ptr), value :: device
327 integer(c_int), value :: param_name
328 integer(c_size_t), value :: param_value_size
329 type(c_ptr), value :: param_value
330 type(c_ptr), value :: param_value_size_ret
331 end function clgetdeviceinfo
332 end interface
333
334 interface
335 integer(c_int) function clreleasecontext(context) &
336 bind(c, name = 'clReleaseContext')
337 use, intrinsic :: iso_c_binding
338 implicit none
339 type(c_ptr), value :: context
340 end function clreleasecontext
341 end interface
342
343 interface
344 integer(c_int) function clreleasecommandqueue(queue) &
345 bind(c, name = 'clReleaseCommandQueue')
346 use, intrinsic :: iso_c_binding
347 implicit none
348 type(c_ptr), value :: queue
349 end function clreleasecommandqueue
350 end interface
351
352 interface
353 integer(c_int) function clreleasedevice(device) &
354 bind(c, name = 'clReleaseDevice')
355 use, intrinsic :: iso_c_binding
356 implicit none
357 type(c_ptr), value :: device
358 end function clreleasedevice
359 end interface
360
361 interface
362 integer(c_int) function clreleaseprogram(prgm) &
363 bind(c, name = 'clReleaseProgram')
364 use, intrinsic :: iso_c_binding
365 implicit none
366 type(c_ptr), value :: prgm
367 end function clreleaseprogram
368 end interface
369
370 interface
371 integer(c_int) function clreleasememobject(ptr_d) &
372 bind(c, name = 'clReleaseMemObject')
373 use, intrinsic :: iso_c_binding
374 implicit none
375 type(c_ptr), value :: ptr_d
376 end function clreleasememobject
377 end interface
378
379 interface
380 integer(c_int) function clreleaseevent(event) &
381 bind(c, name = 'clReleaseEvent')
382 use, intrinsic :: iso_c_binding
383 implicit none
384 type(c_ptr), value :: event
385 end function clreleaseevent
386 end interface
387
388 interface
389 integer(c_int) function clflush(cmd_queue) &
390 bind(c, name = 'clFlush')
391 use, intrinsic :: iso_c_binding
392 implicit none
393 type(c_ptr), value :: cmd_queue
394 end function clflush
395 end interface
396
397 interface
398 integer(c_int) function clfinish(cmd_queue) &
399 bind(c, name = 'clFinish')
400 use, intrinsic :: iso_c_binding
401 implicit none
402 type(c_ptr), value :: cmd_queue
403 end function clfinish
404 end interface
405
406contains
407
408 subroutine opencl_init(glb_cmd_queue, aux_cmd_queue, prf_cmd_queue)
409 type(c_ptr), intent(inout) :: glb_cmd_queue
410 type(c_ptr), intent(inout) :: aux_cmd_queue
411 type(c_ptr), intent(inout) :: prf_cmd_queue
412 type(c_ptr), target :: platform_id
413 integer(c_int) :: num_platforms, num_devices, ierr
414 integer(c_intptr_t) :: ctx_prop(3)
415 integer(c_int64_t), parameter :: queue_props = 0
416 integer :: i
417
418 if (clgetplatformids(1, c_loc(platform_id), &
419 num_platforms) .ne. cl_success) then
420 call neko_error('Failed to get a platform id')
421 end if
422
423 if (clgetdeviceids(platform_id, cl_device_type_gpu, 1, &
424 c_loc(glb_device_id), num_devices) .ne. cl_success) then
425 call neko_error('Failed to get a device id')
426 end if
427
428 if (c_associated(glb_ctx)) then
429 if (clreleasecontext(glb_ctx) .ne. cl_success) then
430 call neko_error('Failed to release context')
431 end if
432 end if
433
434 glb_ctx = clcreatecontext(c_null_ptr, num_devices, c_loc(glb_device_id), &
435 c_null_funptr, c_null_ptr, ierr)
436
437 if (ierr .ne. cl_success) then
438 call neko_error('Failed to create an OpenCL context')
439 end if
440
441 if (c_associated(glb_cmd_queue)) then
442 if (clreleasecommandqueue(glb_cmd_queue) .ne. cl_success) then
443 call neko_error('Faield to release command queue')
444 end if
445 end if
446
447 glb_cmd_queue = clcreatecommandqueue(glb_ctx, glb_device_id, &
448 queue_props, ierr)
449 if (ierr .ne. cl_success) then
450 call neko_error('Failed to create a command queue')
451 end if
452
453 aux_cmd_queue = clcreatecommandqueue(glb_ctx, glb_device_id, &
454 queue_props, ierr)
455 if (ierr .ne. cl_success) then
456 call neko_error('Failed to create a command queue')
457 end if
458
459 prf_cmd_queue = clcreatecommandqueue(glb_ctx, glb_device_id, &
461 if (ierr .ne. cl_success) then
462 call neko_error('Failed to create a command queue')
463 end if
464
465 end subroutine opencl_init
466
467 subroutine opencl_finalize(glb_cmd_queue, aux_cmd_queue, prf_cmd_queue)
468 type(c_ptr), intent(inout) :: glb_cmd_queue
469 type(c_ptr), intent(inout) :: aux_cmd_queue
470 type(c_ptr), intent(inout) :: prf_cmd_queue
471
472 if (c_associated(glb_ctx)) then
473 if (clreleasecontext(glb_ctx) .ne. cl_success) then
474 call neko_error('Failed to release context')
475 end if
476 glb_ctx = c_null_ptr
477 end if
478
479 if (c_associated(glb_cmd_queue)) then
480 if (clreleasecommandqueue(glb_cmd_queue) .ne. cl_success) then
481 call neko_error('Failed to release command queue')
482 end if
483 glb_cmd_queue = c_null_ptr
484 end if
485
486 if (c_associated(aux_cmd_queue)) then
487 if (clreleasecommandqueue(aux_cmd_queue) .ne. cl_success) then
488 call neko_error('Failed to release command queue')
489 end if
490 aux_cmd_queue = c_null_ptr
491 end if
492
493 if (c_associated(prf_cmd_queue)) then
494 if (clreleasecommandqueue(prf_cmd_queue) .ne. cl_success) then
495 call neko_error('Failed to release command queue')
496 end if
497 prf_cmd_queue = c_null_ptr
498 end if
499
500 if (c_associated(glb_device_id)) then
501 if (clreleasedevice(glb_device_id) .ne. cl_success) then
502 call neko_error('Failed to release device')
503 end if
504 end if
505
506 end subroutine opencl_finalize
507
508 subroutine opencl_device_name(name)
509 character(len=*), intent(inout) :: name
510 character(kind=c_char, len=1024), target :: c_name
511 integer(c_size_t), target :: name_len
512
513 if (clgetdeviceinfo(glb_device_id, cl_device_name, int(1024, i8), &
514 c_loc(c_name), c_loc(name_len)) .ne. cl_success) then
515 call neko_error('Failed to query device')
516 end if
517
518 name(1:name_len) = c_name(1:name_len)
519
520 end subroutine opencl_device_name
521
523 integer function opencl_device_count()
524 type(c_ptr), target :: platform_id
525 integer(c_int) :: num_platforms, num_devices
526
527 if (clgetplatformids(1, c_loc(platform_id), num_platforms) &
528 .ne. cl_success) then
529 call neko_error('Failed to get a platform id')
530 end if
531
532 if (clgetdeviceids(platform_id, cl_device_type_gpu, 0, &
533 c_null_ptr, num_devices) .ne. cl_success) then
534 call neko_error('Failed to get a device id')
535 end if
536
537 opencl_device_count = num_devices
538
539 end function opencl_device_count
540#endif
541
542end module opencl_intf
Generic buffer that is extended with buffers of varying rank.
Definition buffer.F90:34
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public i8
Definition num_types.f90:7
Fortran OpenCL interface.
integer(c_int64_t), parameter cl_device_type_default
Device types.
subroutine opencl_device_name(name)
integer(c_int64_t), parameter cl_device_type_gpu
subroutine opencl_finalize(glb_cmd_queue, aux_cmd_queue, prf_cmd_queue)
integer function opencl_device_count()
Return the number of OpenCL devices.
subroutine opencl_init(glb_cmd_queue, aux_cmd_queue, prf_cmd_queue)
integer(c_int64_t), parameter cl_device_type_cpu
@ cl_image_format_mismatch
@ cl_image_format_not_supported
@ cl_device_not_available
@ cl_compiler_not_available
@ cl_mem_object_allocation_failure
@ cl_build_program_failure
@ cl_profiling_info_not_available
integer(c_int64_t), parameter cl_device_type_custom
integer(c_int64_t), parameter cl_queue_profiling_enable
integer(c_int64_t), parameter cl_device_type_all
integer(c_int64_t), parameter cl_queue_out_of_order_exec_mode_enable
Queue properties.
integer(c_int64_t), parameter cl_device_type_accelerator
Utilities.
Definition utils.f90:35