Octopus
accel.F90
Go to the documentation of this file.
1!! Copyright (C) 2010-2016 X. Andrade
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
21#if defined(HAVE_CUDA)
22#define HAVE_ACCEL 1
23#endif
24
25module accel_oct_m
27 use cuda_oct_m
28 use debug_oct_m
29 use global_oct_m
30 use iso_c_binding, only: c_null_ptr, c_size_t
31 use, intrinsic :: iso_fortran_env
32 use loct_oct_m
33 use math_oct_m
35 use mpi_oct_m
37 use types_oct_m
38 use parser_oct_m
42 use string_oct_m
43
44 implicit none
45
46 private
47
48 public :: &
53 accel_t, &
56 accel_init, &
57 accel_end, &
91
92 integer, public, parameter :: &
93 ACCEL_MEM_READ_ONLY = 0, &
96
98 ! Components are public by default
99#if defined(HAVE_CUDA)
100 type(c_ptr) :: cuda_context
101#else
102 integer :: dummy
103#endif
104 end type accel_context_t
105
106 type accel_device_t
107 ! Components are public by default
108#if defined(HAVE_CUDA)
109 type(c_ptr) :: cuda_device
110#else
111 integer :: dummy
112#endif
113 end type accel_device_t
114
115 type accel_t
116 ! Components are public by default
117 type(accel_context_t) :: context
118 type(accel_device_t) :: device
119 type(c_ptr) :: cublas_handle
120 type(c_ptr) :: cuda_stream
121 type(c_ptr) :: program_map
122 integer :: max_block_size
123 integer(int64) :: shared_memory_size
124 integer(int64) :: global_memory_size
125 logical :: enabled
126 logical :: allow_CPU_only
127 logical :: cuda_mpi
128 integer :: warp_size
129 integer(int64) :: initialize_buffers
130 character(len=32) :: debug_flag
131 integer(int64) :: max_block_dim(3)
132 integer(int64) :: max_grid_dim(3)
133 end type accel_t
134
135 type accel_mem_t
136 ! Components are public by default
137 type(c_ptr) :: mem
138 integer(c_size_t) :: size = 0
139 type(type_t) :: type
140 integer :: flags = 0
141 logical :: allocated = .false.
142 end type accel_mem_t
143
144 type accel_kernel_t
145 ! Components are public by default
146#ifdef HAVE_CUDA
147 type(c_ptr) :: cuda_kernel
148 type(c_ptr) :: arguments
149#endif
150 logical :: initialized = .false.
151 type(accel_kernel_t), pointer :: next
152 integer :: arg_count
153 character(len=128) :: kernel_name
154 end type accel_kernel_t
155
156 type(accel_t), public :: accel
157
158 ! Global variables defined on device
159 type(accel_mem_t), public, save :: zM_0_buffer, zM_1_buffer
160 type(accel_mem_t), public, save :: dM_0_buffer, dM_1_buffer
161
162 ! the kernels
163 type(accel_kernel_t), public, target, save :: kernel_vpsi
164 type(accel_kernel_t), public, target, save :: kernel_vpsi_complex
165 type(accel_kernel_t), public, target, save :: kernel_vpsi_spinors
166 type(accel_kernel_t), public, target, save :: kernel_vpsi_spinors_complex
167 type(accel_kernel_t), public, target, save :: kernel_daxpy
168 type(accel_kernel_t), public, target, save :: kernel_zaxpy
169 type(accel_kernel_t), public, target, save :: kernel_copy
170 type(accel_kernel_t), public, target, save :: kernel_copy_complex_to_real
171 type(accel_kernel_t), public, target, save :: kernel_copy_real_to_complex
172 type(accel_kernel_t), public, target, save :: dpack
173 type(accel_kernel_t), public, target, save :: zpack
174 type(accel_kernel_t), public, target, save :: dunpack
175 type(accel_kernel_t), public, target, save :: zunpack
176 type(accel_kernel_t), public, target, save :: kernel_ghost_reorder
177 type(accel_kernel_t), public, target, save :: kernel_density_real
178 type(accel_kernel_t), public, target, save :: kernel_density_complex
179 type(accel_kernel_t), public, target, save :: kernel_density_spinors
180 type(accel_kernel_t), public, target, save :: kernel_phase
181 type(accel_kernel_t), public, target, save :: kernel_phase_spiral
182 type(accel_kernel_t), public, target, save :: dkernel_dot_matrix
183 type(accel_kernel_t), public, target, save :: zkernel_dot_matrix
184 type(accel_kernel_t), public, target, save :: zkernel_dot_matrix_spinors
185 type(accel_kernel_t), public, target, save :: dkernel_batch_axpy
186 type(accel_kernel_t), public, target, save :: zkernel_batch_axpy
187 type(accel_kernel_t), public, target, save :: dkernel_ax_function_py
188 type(accel_kernel_t), public, target, save :: zkernel_ax_function_py
189 type(accel_kernel_t), public, target, save :: dkernel_batch_dotp
190 type(accel_kernel_t), public, target, save :: zkernel_batch_dotp
191 type(accel_kernel_t), public, target, save :: dzmul_batch
192 type(accel_kernel_t), public, target, save :: zzmul_batch
193
194 interface accel_grid_size
196 end interface accel_grid_size
200 end interface accel_grid_size_extend_dim
202 interface accel_padded_size
204 end interface accel_padded_size
205
208 end interface accel_create_buffer
209
211 module procedure accel_kernel_run_4, accel_kernel_run_8
212 end interface accel_kernel_run
241 end interface accel_write_buffer
242
243 interface accel_read_buffer
258 end interface accel_read_buffer
261 module procedure &
285 module procedure &
291
293 module procedure &
299
300 integer :: buffer_alloc_count
301 integer(int64) :: allocated_mem
302 type(accel_kernel_t), pointer :: head
303 type(alloc_cache_t) :: memcache
304
305contains
306
307 pure logical function accel_is_enabled() result(enabled)
308#ifdef HAVE_ACCEL
309 enabled = accel%enabled
310#else
311 enabled = .false.
312#endif
313 end function accel_is_enabled
314
315 ! ------------------------------------------
316
317 pure logical function accel_allow_cpu_only() result(allow)
318#ifdef HAVE_ACCEL
319 allow = accel%allow_CPU_only
320#else
321 allow = .true.
322#endif
323 end function accel_allow_cpu_only
324
325 ! ------------------------------------------
326
327 subroutine accel_init(base_grp, namespace)
328 type(mpi_grp_t), intent(inout) :: base_grp
329 type(namespace_t), intent(in) :: namespace
330
331 logical :: disable, default, run_benchmark
332 integer :: idevice
333#ifdef HAVE_CUDA
334 integer :: dim
335#ifdef HAVE_MPI
336 character(len=256) :: sys_name
337#endif
338#endif
339
340 push_sub(accel_init)
341
342 buffer_alloc_count = 0
343
344 !%Variable DisableAccel
345 !%Type logical
346 !%Default yes
347 !%Section Execution::Accel
348 !%Description
349 !% If Octopus was compiled with CUDA support, it will
350 !% try to initialize and use an accelerator device. By setting this
351 !% variable to <tt>yes</tt> you force Octopus not to use an accelerator even it is available.
352 !%End
353 call messages_obsolete_variable(namespace, 'DisableOpenCL', 'DisableAccel')
354#ifdef HAVE_ACCEL
355 default = .false.
356#else
357 default = .true.
358#endif
359 call parse_variable(namespace, 'DisableAccel', default, disable)
360 accel%enabled = .not. disable
361
362#ifndef HAVE_ACCEL
363 if (accel%enabled) then
364 message(1) = 'Octopus was compiled without Cuda support.'
365 call messages_fatal(1)
366 end if
367#endif
368
369 if (.not. accel_is_enabled()) then
370 pop_sub(accel_init)
371 return
372 end if
373
374 call messages_obsolete_variable(namespace, 'AccelPlatform')
375 call messages_obsolete_variable(namespace, 'OpenCLPlatform', 'AccelPlatform')
376
377 !%Variable AccelDevice
378 !%Type integer
379 !%Default 0
380 !%Section Execution::Accel
381 !%Description
382 !% This variable selects the GPU that Octopus will use. You can specify a
383 !% numerical id to select a specific device.
384 !%
385 !% In case of MPI enabled runs devices are distributed in a round robin fashion,
386 !% starting at this value.
387 !%End
388 call parse_variable(namespace, 'AccelDevice', 0, idevice)
389
390 call messages_obsolete_variable(namespace, 'OpenCLDevice', 'AccelDevice')
391
392 if (idevice < 0) then
393 call messages_write('Invalid AccelDevice')
394 call messages_fatal()
395 end if
397 call messages_print_with_emphasis(msg="GPU acceleration", namespace=namespace)
399#ifdef HAVE_CUDA
400 if (idevice<0) idevice = 0
401 call cuda_init(accel%context%cuda_context, accel%device%cuda_device, accel%cuda_stream, &
402 idevice, base_grp%rank)
403#ifdef HAVE_MPI
404 call loct_sysname(sys_name)
405 write(message(1), '(A,I5,A,I5,2A)') "Rank ", base_grp%rank, " uses device number ", idevice, &
406 " on ", trim(sys_name)
407 call messages_info(1, all_nodes = .true.)
408#endif
409
410 call cublas_init(accel%cublas_handle, accel%cuda_stream)
411#endif
413
414 ! Get some device information that we will need later
415#ifdef HAVE_CUDA
416 call cuda_device_total_memory(accel%device%cuda_device, accel%global_memory_size)
417 call cuda_device_shared_memory(accel%device%cuda_device, accel%shared_memory_size)
418 call cuda_device_max_threads_per_block(accel%device%cuda_device, accel%max_block_size)
419 call cuda_device_get_warpsize(accel%device%cuda_device, accel%warp_size)
420 call cuda_device_max_block_dim_x(accel%device%cuda_device, dim)
421 accel%max_block_dim(1) = int(dim, int64)
422 call cuda_device_max_block_dim_y(accel%device%cuda_device, dim)
423 accel%max_block_dim(2) = int(dim, int64)
424 call cuda_device_max_block_dim_z(accel%device%cuda_device, dim)
425 accel%max_block_dim(3) = int(dim, int64)
426 call cuda_device_max_grid_dim_x(accel%device%cuda_device, dim)
427 accel%max_grid_dim(1) = int(dim, int64)
428 call cuda_device_max_grid_dim_y(accel%device%cuda_device, dim)
429 accel%max_grid_dim(2) = int(dim, int64)
430 call cuda_device_max_grid_dim_z(accel%device%cuda_device, dim)
431 accel%max_grid_dim(3) = int(dim, int64)
432#endif
433
434 if (base_grp%is_root()) call device_info()
435
436 ! initialize the cache used to speed up allocations
437 call alloc_cache_init(memcache, nint(0.25_real64*accel%global_memory_size, int64))
438
439 ! now initialize the kernels
441
442#if defined(HAVE_HIP)
443 accel%debug_flag = "-g"
444#elif defined(HAVE_CUDA)
445 accel%debug_flag = "-lineinfo"
446#endif
447
448 call accel_kernel_start_call(kernel_vpsi, 'vpsi.cu', "vpsi")
449 call accel_kernel_start_call(kernel_vpsi_complex, 'vpsi.cu', "vpsi_complex")
450 call accel_kernel_start_call(kernel_vpsi_spinors, 'vpsi.cu', "vpsi_spinors")
451 call accel_kernel_start_call(kernel_vpsi_spinors_complex, 'vpsi.cu', "vpsi_spinors_complex")
452 call accel_kernel_start_call(kernel_daxpy, 'axpy.cu', "axpy<double>")
453 call accel_kernel_start_call(kernel_zaxpy, 'axpy.cu', "axpy<double2>")
454 call accel_kernel_start_call(dkernel_batch_axpy, 'axpy.cu', "batch_axpy_function<double>")
455 call accel_kernel_start_call(zkernel_batch_axpy, 'axpy.cu', "batch_axpy_function<double2>")
456 call accel_kernel_start_call(dkernel_ax_function_py, 'axpy.cu', "batch_ax_function_py<double>")
457 call accel_kernel_start_call(zkernel_ax_function_py, 'axpy.cu', "batch_ax_function_py<double2>")
458 call accel_kernel_start_call(dkernel_batch_dotp, 'mesh_batch_single.cu', "dbatch_mf_dotp")
459 call accel_kernel_start_call(zkernel_batch_dotp, 'mesh_batch_single.cu', "zbatch_mf_dotp")
460 call accel_kernel_start_call(dpack, 'pack.cu', "dpack")
461 call accel_kernel_start_call(zpack, 'pack.cu', "zpack")
462 call accel_kernel_start_call(dunpack, 'pack.cu', "dunpack")
463 call accel_kernel_start_call(zunpack, 'pack.cu', "zunpack")
464 call accel_kernel_start_call(kernel_copy, 'copy.cu', "copy")
465 call accel_kernel_start_call(kernel_copy_complex_to_real, 'copy.cu', "copy_complex_to_real")
466 call accel_kernel_start_call(kernel_copy_real_to_complex, 'copy.cu', "copy_real_to_complex")
467 call accel_kernel_start_call(kernel_ghost_reorder, 'ghost.cu', "ghost_reorder")
468 call accel_kernel_start_call(kernel_density_real, 'density.cu', "density_real")
469 call accel_kernel_start_call(kernel_density_complex, 'density.cu', "density_complex")
470 call accel_kernel_start_call(kernel_density_spinors, 'density.cu', "density_spinors")
471 call accel_kernel_start_call(kernel_phase, 'phase.cu', "phase")
472 call accel_kernel_start_call(dkernel_dot_matrix, 'mesh_batch.cu', "ddot_matrix")
473 call accel_kernel_start_call(zkernel_dot_matrix, 'mesh_batch.cu', "zdot_matrix")
474 call accel_kernel_start_call(zkernel_dot_matrix_spinors, 'mesh_batch.cu', "zdot_matrix_spinors")
475
476
477 call accel_kernel_start_call(dzmul_batch, 'mul.cu', 'zmul_batch<double>')
478 call accel_kernel_start_call(zzmul_batch, 'mul.cu', 'zmul_batch<double2>')
479
480 ! Define global buffers
481 if(.not. accel_buffer_is_allocated(zm_0_buffer)) then
482 call accel_create_buffer(zm_0_buffer, accel_mem_read_only, type_cmplx, 1)
483 call accel_write_buffer(zm_0_buffer, m_z0)
484 end if
485 if(.not. accel_buffer_is_allocated(zm_1_buffer)) then
486 call accel_create_buffer(zm_1_buffer, accel_mem_read_only, type_cmplx, 1)
487 call accel_write_buffer(zm_1_buffer, m_z1)
488 end if
489 if(.not. accel_buffer_is_allocated(dm_0_buffer)) then
490 call accel_create_buffer(dm_0_buffer, accel_mem_read_only, type_float, 1)
491 call accel_write_buffer(dm_0_buffer, m_zero)
492 end if
493 if(.not. accel_buffer_is_allocated(dm_1_buffer)) then
494 call accel_create_buffer(dm_1_buffer, accel_mem_read_only, type_float, 1)
495 call accel_write_buffer(dm_1_buffer, m_one)
496 end if
497
498
499 !%Variable AccelBenchmark
500 !%Type logical
501 !%Default no
502 !%Section Execution::Accel
503 !%Description
504 !% If this variable is set to yes, Octopus will run some
505 !% routines to benchmark the performance of the accelerator device.
506 !%End
507 call parse_variable(namespace, 'AccelBenchmark', .false., run_benchmark)
508
509 call messages_obsolete_variable(namespace, 'OpenCLBenchmark', 'AccelBenchmark')
510
511 if (run_benchmark) then
513 end if
514
515 !%Variable GPUAwareMPI
516 !%Type logical
517 !%Section Execution::Accel
518 !%Description
519 !% If Octopus was compiled with GPU support and MPI support and if the MPI
520 !% implementation is GPU-aware (i.e., it supports communication using device pointers),
521 !% this switch can be set to true to use the GPU-aware MPI features. The advantage
522 !% of this approach is that it can do, e.g., peer-to-peer copies between devices without
523 !% going through the host memory.
524 !% The default is false, except when the configure switch --enable-cudampi is set, in which
525 !% case this variable is set to true.
526 !%End
527#ifdef HAVE_CUDA_MPI
528 default = .true.
529#else
530 default = .false.
531#endif
532 call parse_variable(namespace, 'GPUAwareMPI', default, accel%cuda_mpi)
533 if (accel%cuda_mpi) then
534#ifndef HAVE_CUDA_MPI
535 call messages_write("Warning: trying to use GPU-aware MPI, but we have not detected support in the linked MPI library.")
536 call messages_warning()
537#endif
538 call messages_write("Using GPU-aware MPI.")
539 call messages_info()
540 end if
541
542
543 !%Variable AllowCPUonly
544 !%Type logical
545 !%Section Execution::Accel
546 !%Description
547 !% In order to prevent waste of resources, the code will normally stop when the GPU is disabled due to
548 !% incomplete implementations or incompatibilities. AllowCPUonly = yes overrides this and allows the
549 !% code execution also in these cases.
550 !%End
551#if defined (HAVE_ACCEL)
552 default = .false.
553#else
554 default = .true.
555#endif
556 call parse_variable(namespace, 'AllowCPUonly', default, accel%allow_CPU_only)
557
558
559 !%Variable InitializeGPUBuffers
560 !%Type integer
561 !%Default no
562 !%Section Execution::Accel
563 !%Description
564 !% Initialize new GPU buffers to zero on creation (use only for debugging, as it has a performance impact!).
565 !%Option no 0
566 !% Do not initialize GPU buffers.
567 !%Option yes 1
568 !% Initialize GPU buffers to zero.
569 !%Option nan 2
570 !% Initialize GPU buffers to nan.
571 !%End
572 call parse_variable(namespace, 'InitializeGPUBuffers', option__initializegpubuffers__no, accel%initialize_buffers)
573 if (.not. varinfo_valid_option('InitializeGPUBuffers', accel%initialize_buffers)) then
574 call messages_input_error(namespace, 'InitializeGPUBuffers')
575 end if
576
577
578 call messages_print_with_emphasis(namespace=namespace)
579
580 pop_sub(accel_init)
581
582 contains
583
584 subroutine device_info()
585#ifdef HAVE_CUDA
586 integer :: version
587 character(kind=c_char) :: cval_str(257)
588#endif
589 integer :: major, minor
590 character(len=256) :: val_str
591
592 push_sub(accel_init.device_info)
593
594 call messages_new_line()
595 call messages_write('Selected device:')
596 call messages_new_line()
597
598#ifdef HAVE_CUDA
599#ifdef __HIP_PLATFORM_AMD__
600 call messages_write(' Framework : ROCm')
601#else
602 call messages_write(' Framework : CUDA')
603#endif
604#endif
605 call messages_info()
606
607#ifdef HAVE_CUDA
608 call messages_write(' Device type : GPU', new_line = .true.)
609#ifdef __HIP_PLATFORM_AMD__
610 call messages_write(' Device vendor : AMD Corporation', new_line = .true.)
611#else
612 call messages_write(' Device vendor : NVIDIA Corporation', new_line = .true.)
613#endif
614#endif
615
616#ifdef HAVE_CUDA
617 cval_str = c_null_char
618 call cuda_device_name(accel%device%cuda_device, cval_str)
619 call string_c_to_f(cval_str, val_str)
620#endif
621 call messages_write(' Device name : '//trim(val_str))
622 call messages_new_line()
623
624#ifdef HAVE_CUDA
625 call cuda_device_capability(accel%device%cuda_device, major, minor)
626#endif
627 call messages_write(' Cuda capabilities :')
628 call messages_write(major, fmt = '(i2)')
629 call messages_write('.')
630 call messages_write(minor, fmt = '(i1)')
631 call messages_new_line()
632
633 ! VERSION
634#ifdef HAVE_CUDA
635 call cuda_driver_version(version)
636 call messages_write(' Driver version : ')
637 call messages_write(version)
638#endif
639 call messages_new_line()
640
641
642 call messages_write(' Device memory :')
643 call messages_write(accel%global_memory_size, units=unit_megabytes)
644 call messages_new_line()
645
646 call messages_write(' Shared memory :')
647 call messages_write(accel%shared_memory_size, units=unit_kilobytes)
648 call messages_new_line()
649
650 call messages_write(' Max. block size :')
651 call messages_write(accel%max_block_size)
652 call messages_new_line()
653
654 call messages_info()
655
656 pop_sub(accel_init.device_info)
657 end subroutine device_info
658
659 end subroutine accel_init
660
661 ! ------------------------------------------
662 subroutine accel_end(namespace)
663 type(namespace_t), intent(in) :: namespace
664
665 integer(int64) :: hits, misses
666 real(real64) :: volume_hits, volume_misses
667 logical :: found
668 type(accel_mem_t) :: tmp
669
670 push_sub(accel_end)
671
672 if (accel_is_enabled()) then
673
674 ! Release global buffers
675 call accel_free_buffer(zm_0_buffer)
676 call accel_free_buffer(zm_1_buffer)
677 call accel_free_buffer(dm_0_buffer)
678 call accel_free_buffer(dm_1_buffer)
679
680 do
681 call alloc_cache_get(memcache, alloc_cache_any_size, found, tmp%mem)
682 if (.not. found) exit
683
684#ifdef HAVE_CUDA
685 call cuda_mem_free(tmp%mem)
686#endif
687 end do
688
689 call alloc_cache_end(memcache, hits, misses, volume_hits, volume_misses)
690
691 call messages_print_with_emphasis(msg="Acceleration-device allocation cache", namespace=namespace)
692
693 call messages_new_line()
694 call messages_write(' Number of allocations =')
695 call messages_write(hits + misses, new_line = .true.)
696 call messages_write(' Volume of allocations =')
697 call messages_write(volume_hits + volume_misses, fmt = 'f18.1', units = unit_gigabytes, align_left = .true., &
698 new_line = .true.)
699 call messages_write(' Hit ratio =')
700 if (hits + misses > 0) then
701 call messages_write(hits/real(hits + misses, real64)*100, fmt='(f6.1)', align_left = .true.)
702 else
703 call messages_write(m_zero, fmt='(f6.1)', align_left = .true.)
704 end if
705 call messages_write('%', new_line = .true.)
706 call messages_write(' Volume hit ratio =')
707 if (volume_hits + volume_misses > 0) then
708 call messages_write(volume_hits/(volume_hits + volume_misses)*100, fmt='(f6.1)', align_left = .true.)
709 else
710 call messages_write(m_zero, fmt='(f6.1)', align_left = .true.)
711 end if
712 call messages_write('%')
713 call messages_new_line()
714 call messages_info()
715
716 call messages_print_with_emphasis(namespace=namespace)
717 end if
718
720
721 if (accel_is_enabled()) then
722#ifdef HAVE_CUDA
723 call cublas_end(accel%cublas_handle)
724 if (.not. accel%cuda_mpi) then ! CUDA aware MPI finalize will do the cleanup
725 call cuda_end(accel%context%cuda_context, accel%device%cuda_device)
726 end if
727#endif
728
729 if (buffer_alloc_count /= 0) then
730 call messages_write('Accel:')
731 call messages_write(real(allocated_mem, real64) , fmt = 'f12.1', units = unit_megabytes, align_left = .true.)
732 call messages_write(' in ')
733 call messages_write(buffer_alloc_count)
734 call messages_write(' buffers were not deallocated.')
735 call messages_fatal()
736 end if
737
738 end if
739
740 pop_sub(accel_end)
741 end subroutine accel_end
742
743 ! ------------------------------------------
744
746 subroutine accel_grid_size_array_i8(n, blocksizes, gridsizes)
747 integer(int64), intent(in) :: n(:)
748 integer(int64), intent(in) :: blocksizes(:)
749 integer(int64), intent(out) :: gridsizes(:)
750
751 integer :: dim, i
752
753 dim = ubound(n, dim=1)
754 assert(dim == ubound(blocksizes, dim=1))
755 assert(dim == ubound(gridsizes, dim=1))
756
757 do i = 1, dim
758 gridsizes(i) = (n(i) + blocksizes(i) - 1_int64) / blocksizes(i)
759 gridsizes(i) = min(gridsizes(i), accel%max_grid_dim(i))
760 end do
761 end subroutine accel_grid_size_array_i8
762
763 ! ------------------------------------------
764
766 subroutine accel_grid_size_array_i4(n, blocksizes, gridsizes)
767 integer, intent(in) :: n(:)
768 integer, intent(in) :: blocksizes(:)
769 integer, intent(out) :: gridsizes(:)
770
771 integer(int64) :: gridsizes64(size(gridsizes))
772
773 call accel_grid_size_array_i8(int(n(:), int64), int(blocksizes(:), int64), gridsizes64)
774
775 gridsizes = int(gridsizes64, int32)
776 end subroutine accel_grid_size_array_i4
777
778 ! ------------------------------------------
779
781 subroutine accel_grid_size_i8(n, blocksizes, gridsizes)
782 integer(int64), intent(in) :: n
783 integer(int64), intent(in) :: blocksizes
784 integer(int64), intent(out) :: gridsizes
785
786 integer(int64) :: temp(1)
788 call accel_grid_size_array_i8( (/n/), (/blocksizes/), temp)
789
790 gridsizes = temp(1)
791 end subroutine accel_grid_size_i8
792
793 ! ------------------------------------------
794
796 subroutine accel_grid_size_i4(n, blocksizes, gridsizes)
797 integer, intent(in) :: n
798 integer, intent(in) :: blocksizes
799 integer, intent(out) :: gridsizes
800
801 integer(int64) :: temp(1)
802
803 call accel_grid_size_array_i8(int((/n/), int64), int((/blocksizes/), int64), temp)
804
805 gridsizes = int(temp(1), int32)
806 end subroutine accel_grid_size_i4
808! ------------------------------------------
809
813 subroutine accel_grid_size_extend_dim_i8(n, pack_size, gridsizes, blocksizes, kernel)
814 integer(int64), intent(in) :: n
815 integer(int64), intent(in) :: pack_size
816 integer(int64), dimension(3), intent(out) :: gridsizes
817 integer(int64), dimension(3), intent(out) :: blocksizes
818 type(accel_kernel_t), optional, intent(inout) :: kernel
819
820 integer(int64) :: bsize, dim2, dim3
821 integer(int64), dimension(3) :: nn
823 if(present(kernel)) then
824 bsize = accel_kernel_block_size(kernel)/pack_size
825 else
826 bsize = accel_max_block_size()/pack_size
827 end if
828
829 dim3 = n/(accel_max_size_per_dim(2)*bsize) + 1
830 dim2 = min(accel_max_size_per_dim(2)*bsize, pad(n, bsize))
831
832 nn = (/pack_size, dim2, dim3/)
833 blocksizes = (/pack_size, bsize, 1_int64/)
834
835 call accel_grid_size(nn, blocksizes, gridsizes)
836 end subroutine accel_grid_size_extend_dim_i8
838 ! ------------------------------------------
839
843 subroutine accel_grid_size_extend_dim_i4(n, pack_size, gridsizes, blocksizes, kernel)
844 integer, intent(in) :: n
845 integer, intent(in) :: pack_size
846 integer, dimension(3), intent(out) :: gridsizes
847 integer, dimension(3), intent(out) :: blocksizes
848 type(accel_kernel_t), optional, intent(inout) :: kernel
849
850 integer(int64) :: gridsizes64(3), blocksizes64(3)
851
852 call accel_grid_size_extend_dim_i8(int(n, int64), int(pack_size, int64), &
853 gridsizes64, blocksizes64, kernel=kernel)
855 gridsizes = int(gridsizes64, int32)
856 blocksizes = int(blocksizes64, int32)
857 end subroutine accel_grid_size_extend_dim_i4
858
859 ! ------------------------------------------
860
861 integer(int64) function accel_padded_size_i8(nn) result(psize)
862 integer(int64), intent(in) :: nn
863
864 integer(int64) :: modnn, bsize
865
866 psize = nn
867
868 if (accel_is_enabled()) then
869
870 bsize = accel_max_block_size()
871
872 psize = nn
873 modnn = mod(nn, bsize)
874 if (modnn /= 0) psize = psize + bsize - modnn
875
876 end if
877
878 end function accel_padded_size_i8
879
880 ! ------------------------------------------
881
882 integer(int32) function accel_padded_size_i4(nn) result(psize)
883 integer(int32), intent(in) :: nn
885 psize = int(accel_padded_size_i8(int(nn, int64)), int32)
886
887 end function accel_padded_size_i4
888
889 ! ------------------------------------------
890
891 subroutine accel_create_buffer_4(this, flags, type, size, set_zero, async)
892 type(accel_mem_t), intent(inout) :: this
893 integer, intent(in) :: flags
894 type(type_t), intent(in) :: type
895 integer, intent(in) :: size
896 logical, optional, intent(in) :: set_zero
897 logical, optional, intent(in) :: async
898
899 call accel_create_buffer_8(this, flags, type, int(size, int64), set_zero, async)
900 end subroutine accel_create_buffer_4
901
902 ! ------------------------------------------
903
904 subroutine accel_create_buffer_8(this, flags, type, size, set_zero, async)
905 type(accel_mem_t), intent(inout) :: this
906 integer, intent(in) :: flags
907 type(type_t), intent(in) :: type
908 integer(int64), intent(in) :: size
909 logical, optional, intent(in) :: set_zero
910 logical, optional, intent(in) :: async
911
912 integer(int64) :: fsize
913 logical :: found
914 integer(int64) :: initialize_buffers
915
916 push_sub(accel_create_buffer_8)
917
918 this%type = type
919 this%size = size
920 this%flags = flags
921 fsize = int(size, int64)*types_get_size(type)
922 this%allocated = .true.
924 if (fsize > 0) then
925
926 call alloc_cache_get(memcache, fsize, found, this%mem)
927
928 if (.not. found) then
929#ifdef HAVE_CUDA
930 if(optional_default(async, .false.)) then
931 call cuda_mem_alloc_async(this%mem, fsize)
932 else
933 call cuda_mem_alloc(this%mem, fsize)
934 end if
935#endif
936 end if
937
938 buffer_alloc_count = buffer_alloc_count + 1
939 allocated_mem = allocated_mem + fsize
940
941 end if
942
943 if (present(set_zero)) then
944 initialize_buffers = merge(option__initializegpubuffers__yes, option__initializegpubuffers__no, set_zero)
945 else
946 initialize_buffers = accel%initialize_buffers
947 end if
948 select case (initialize_buffers)
949 case (option__initializegpubuffers__yes)
950 call accel_set_buffer_to(this, type, int(z'00', int8), size, async=async)
951 case (option__initializegpubuffers__nan)
952 call accel_set_buffer_to(this, type, int(z'FF', int8), size, async=async)
953 end select
954
955 pop_sub(accel_create_buffer_8)
956 end subroutine accel_create_buffer_8
957
958 ! ------------------------------------------
959
960 subroutine accel_free_buffer(this, async)
961 type(accel_mem_t), intent(inout) :: this
962 logical, optional, intent(in) :: async
963
964 logical :: put
965 integer(int64) :: fsize
966
967 push_sub(accel_free_buffer)
968
969 if (this%size > 0) then
970
971 fsize = int(this%size, int64)*types_get_size(this%type)
972
973 call alloc_cache_put(memcache, fsize, this%mem, put)
974
975 if (.not. put) then
976#ifdef HAVE_CUDA
977 if (optional_default(async, .false.)) then
978 call cuda_mem_free_async(this%mem)
979 else
980 call cuda_mem_free(this%mem)
981 end if
982#endif
983 end if
984
985 buffer_alloc_count = buffer_alloc_count - 1
986 allocated_mem = allocated_mem + fsize
987
988 end if
989
990 this%size = 0
991 this%flags = 0
992
993 this%allocated = .false.
994
995 pop_sub(accel_free_buffer)
996 end subroutine accel_free_buffer
997
998 ! ------------------------------------------
999
1003 subroutine accel_move_buffer(buffer_from, buffer_to)
1004 type(accel_mem_t), intent(inout) :: buffer_from
1005 type(accel_mem_t), intent(inout) :: buffer_to
1006
1007 push_sub(accel_move_buffer)
1008
1009 ! Can not move an allocated buffer, the destination buffer should be empty
1010 assert(.not. accel_buffer_is_allocated(buffer_to))
1011
1012 buffer_to%mem = buffer_from%mem
1013 buffer_to%size = buffer_from%size
1014 buffer_to%type = buffer_from%type
1015 buffer_to%flags = buffer_from%flags
1016 buffer_to%allocated = buffer_from%allocated
1017
1018 call accel_detach_buffer(buffer_from)
1019
1020 pop_sub(accel_move_buffer)
1021 end subroutine accel_move_buffer
1022
1023 ! ------------------------------------------
1024
1029 subroutine accel_detach_buffer(this)
1030 type(accel_mem_t), intent(inout) :: this
1031
1032 push_sub(accel_detach_buffer)
1033
1034 this%mem = c_null_ptr
1035 this%size = 0
1036 this%type = type_none
1037 this%flags = 0
1038 this%allocated = .false.
1039
1040 pop_sub(accel_detach_buffer)
1041 end subroutine accel_detach_buffer
1042
1043 ! ------------------------------------------------------
1045 ! Check if the temporary buffers are the right size, if not reallocate them
1046 subroutine accel_ensure_buffer_size(buffer, flags, type, required_size, set_zero, async)
1047 type(accel_mem_t), intent(inout) :: buffer
1048 integer, intent(in) :: flags
1049 type(type_t), intent(in) :: type
1050 integer, intent(in) :: required_size
1051 logical, intent(in) :: set_zero
1052 logical, optional, intent(in) :: async
1053
1054 push_sub(accel_ensure_buffer_size)
1055
1056
1057 if (accel_buffer_is_allocated(buffer) .and. buffer%size < required_size) then
1058 call accel_free_buffer(buffer, async=optional_default(async, .false.))
1059 end if
1060
1061 if (.not. accel_buffer_is_allocated(buffer)) then
1062 call accel_create_buffer(buffer, flags, type, required_size, set_zero=set_zero, async=optional_default(async, .false.))
1063 end if
1064
1066 end subroutine accel_ensure_buffer_size
1067
1068 ! ------------------------------------------
1069
1070 logical pure function accel_buffer_is_allocated(this) result(allocated)
1071 type(accel_mem_t), intent(in) :: this
1072
1073 allocated = this%allocated
1074 end function accel_buffer_is_allocated
1075
1076 ! -----------------------------------------
1077
1078 subroutine accel_finish()
1079 ! no push_sub, called too frequently
1080
1081 if (accel_is_enabled()) then
1082#ifdef HAVE_CUDA
1084#endif
1085 end if
1086 end subroutine accel_finish
1088 ! ------------------------------------------
1089
1090 subroutine accel_set_kernel_arg_buffer(kernel, narg, buffer)
1091 type(accel_kernel_t), intent(inout) :: kernel
1092 integer, intent(in) :: narg
1093 type(accel_mem_t), intent(in) :: buffer
1094
1095 assert(accel_buffer_is_allocated(buffer))
1096
1097 ! no push_sub, called too frequently
1098#ifdef HAVE_CUDA
1099 call cuda_kernel_set_arg_buffer(kernel%arguments, buffer%mem, narg)
1100#endif
1101
1102 end subroutine accel_set_kernel_arg_buffer
1103
1104 ! ------------------------------------------
1105
1112 subroutine accel_kernel_run_8(kernel, gridsizes, blocksizes, shared_memory_size)
1113 type(accel_kernel_t), intent(inout) :: kernel
1114 integer(int64), intent(in) :: gridsizes(:)
1115 integer(int64), intent(in) :: blocksizes(:)
1116 integer(int64), optional, intent(in) :: shared_memory_size
1117
1118 integer :: dim
1119 integer(int64) :: gsizes(1:3)
1120 integer(int64) :: bsizes(1:3)
1121
1122 ! no push_sub, called too frequently
1123
1124 ! CUDA needs all dimensions
1125 gsizes = 1
1126 bsizes = 1
1127
1128 dim = ubound(gridsizes, dim=1)
1129
1130 assert(dim == ubound(blocksizes, dim=1))
1132 ! if one size is zero, there is nothing to do
1133 if (any(gridsizes == 0)) return
1134
1135 assert(all(blocksizes > 0))
1136
1137 gsizes(1:dim) = gridsizes(1:dim)
1138 bsizes(1:dim) = blocksizes(1:dim)
1139
1140#ifdef HAVE_CUDA
1141 ! Maximum dimension of a block
1142 if (any(bsizes(1:3) > accel%max_block_dim(1:3))) then
1143 message(1) = "Maximum dimension of a block too large in kernel "//trim(kernel%kernel_name)
1144 message(2) = "The following conditions should be fulfilled:"
1145 write(message(3), "(A, I8, A, I8)") "Dim 1: ", bsizes(1), " <= ", accel%max_block_dim(1)
1146 write(message(4), "(A, I8, A, I8)") "Dim 2: ", bsizes(2), " <= ", accel%max_block_dim(2)
1147 write(message(5), "(A, I8, A, I8)") "Dim 3: ", bsizes(3), " <= ", accel%max_block_dim(3)
1148 message(6) = "This is an internal error, please contact the developers."
1149 call messages_fatal(6)
1150 end if
1151
1152
1153 ! Maximum number of threads per block
1154 if (product(bsizes) > accel_max_block_size()) then
1155 message(1) = "Maximum number of threads per block too large in kernel "//trim(kernel%kernel_name)
1156 message(2) = "The following condition should be fulfilled:"
1157 write(message(3), "(I8, A, I8)") product(bsizes), " <= ", accel_max_block_size()
1158 message(4) = "This is an internal error, please contact the developers."
1159 call messages_fatal(4)
1160 end if
1161
1162 ! Maximum dimensions of the grid of thread block
1163 if (any(gsizes(1:3) > accel%max_grid_dim(1:3))) then
1164 message(1) = "Maximum dimension of grid too large in kernel "//trim(kernel%kernel_name)
1165 message(2) = "The following conditions should be fulfilled:"
1166 write(message(3), "(A, I8, A, I10)") "Dim 1: ", gsizes(1), " <= ", accel%max_grid_dim(1)
1167 write(message(4), "(A, I8, A, I10)") "Dim 2: ", gsizes(2), " <= ", accel%max_grid_dim(2)
1168 write(message(5), "(A, I8, A, I10)") "Dim 3: ", gsizes(3), " <= ", accel%max_grid_dim(3)
1169 message(6) = "This is an internal error, please contact the developers."
1170 call messages_fatal(6)
1171 end if
1172
1173 if(present(shared_memory_size)) then
1174
1175 if (shared_memory_size > accel%shared_memory_size) then
1176 message(1) = "Shared memory too large in kernel "//trim(kernel%kernel_name)
1177 message(2) = "The following condition should be fulfilled:"
1178 message(3) = "Requested shared memory <= Available shared memory"
1179 write(message(4), '(a,f12.6,a)') "Requested shared memory: ", real(shared_memory_size, real64) /1024.0, " Kb"
1180 write(message(5), '(a,f12.6,a)') "Available shared memory: ", real(accel%shared_memory_size, real64) /1024.0, " Kb"
1181 message(6) = "This is an internal error, please contact the developers."
1182 call messages_fatal(6)
1183 else if (shared_memory_size <= 0) then
1184 message(1) = "Invalid shared memory size in kernel "//trim(kernel%kernel_name)
1185 write(message(2), '(a,f12.6,a)') "Shared memory size requested: ", real(shared_memory_size, real64) /1024.0, " Kb"
1186 message(3) = "This is an internal error, please contact the developers."
1187 call messages_fatal(3)
1188 end if
1189 end if
1190
1191 call cuda_launch_kernel(kernel%cuda_kernel, gsizes(1), bsizes(1), &
1192 optional_default(shared_memory_size, 0_int64), kernel%arguments)
1193#endif
1194
1195 end subroutine accel_kernel_run_8
1196
1197 ! -----------------------------------------------
1198
1204
1205 subroutine accel_kernel_run_4(kernel, gridsizes, blocksizes, shared_memory_size)
1206 type(accel_kernel_t), intent(inout) :: kernel
1207 integer, intent(in) :: gridsizes(:)
1208 integer, intent(in) :: blocksizes(:)
1209 integer(int64), optional, intent(in) :: shared_memory_size
1210
1211 call accel_kernel_run_8(kernel, int(gridsizes, int64), int(blocksizes, int64), shared_memory_size)
1212
1213 end subroutine accel_kernel_run_4
1214
1215 ! -----------------------------------------------
1216
1217 integer pure function accel_max_block_size() result(max_block_size)
1218 max_block_size = accel%max_block_size
1219 end function accel_max_block_size
1220
1221 ! -----------------------------------------------
1222
1223 integer function accel_kernel_block_size(kernel) result(block_size)
1224 type(accel_kernel_t), intent(inout) :: kernel
1225
1226#ifdef HAVE_CUDA
1227 integer :: max_block_size
1228#endif
1229
1230 block_size = 0
1231
1232#ifdef HAVE_CUDA
1233 call cuda_kernel_max_threads_per_block(kernel%cuda_kernel, max_block_size)
1234 if (debug%info .and. max_block_size /= accel%max_block_size) then
1235 write(message(1), "(A, I5, A)") "A kernel can use only less threads per block (", max_block_size, ")", &
1236 "than available on the device (", accel%max_block_size, ")"
1237 call messages_info(1)
1238 end if
1239
1240 ! recommended number of threads per block is 256 according to the CUDA best practice guide
1241 ! see https://docs.nvidia.com/cuda/cuda-c-best-practices-guide/index.html#thread-and-block-heuristics
1242 block_size = 256
1243
1244 ! make sure we do not use more threads per block than available for this kernel
1245 block_size = min(block_size, max_block_size)
1246#endif
1247
1248 end function accel_kernel_block_size
1249
1250 ! ----------------------------------------------------
1251
1253 subroutine accel_copy_buffer(dest, src, type, nval, offset_dest, offset_src, async)
1254 type(accel_mem_t), intent(inout) :: dest
1255 type(accel_mem_t), intent(in) :: src
1256 type(type_t), intent(in) :: type
1257 integer(int64), intent(in) :: nval
1258 integer(int64), optional, intent(in) :: offset_dest
1259 integer(int64), optional, intent(in) :: offset_src
1260 logical, optional, intent(in) :: async
1261
1262 integer(int64) :: type_size, offset_dest_, offset_src_
1263
1265 call profiling_in("ACCEL_COPY_BUFFER")
1266
1267 if (nval == 0) then
1268 call profiling_out("ACCEL_COPY_BUFFER")
1269 pop_sub(accel_copy_buffer)
1270 return
1271 end if
1272 assert(nval > 0)
1273
1274 type_size = types_get_size(type)
1275
1276 offset_dest_ = 0_int64
1277 if (present(offset_dest)) offset_dest_ = offset_dest*type_size
1278 offset_src_ = 0_int64
1279 if (present(offset_src)) offset_src_ = offset_src*type_size
1280
1281 assert(offset_dest_ + nval*type_size <= int(dest%size, int64)*types_get_size(dest%type))
1282 assert(offset_src_ + nval*type_size <= int(src%size, int64)*types_get_size(src%type))
1283
1284 call cuda_memcpy_dtod(dest%mem, src%mem, nval*type_size, offset_dest_, offset_src_)
1285
1286 if (.not. optional_default(async, .false.)) call accel_finish()
1287
1288 call profiling_out("ACCEL_COPY_BUFFER")
1289 pop_sub(accel_copy_buffer)
1290 end subroutine accel_copy_buffer
1291
1292 ! ----------------------------------------------------
1293
1294 subroutine accel_set_buffer_to(buffer, type, val, nval, offset, async)
1295 type(accel_mem_t), intent(inout) :: buffer
1296 type(type_t), intent(in) :: type
1297 integer(int8), intent(in) :: val
1298 integer(int64), intent(in) :: nval
1299 integer(int64), optional, intent(in) :: offset
1300 logical, optional, intent(in) :: async
1301
1302 integer(int64) :: nval_, offset_, type_size
1303
1304 push_sub(accel_set_buffer_to)
1306 if (nval == 0) then
1307 pop_sub(accel_set_buffer_to)
1308 return
1309 end if
1310 assert(nval > 0)
1311
1312 if (present(offset)) then
1313 assert(offset >= 0)
1314 if(offset > buffer%size) then
1315 pop_sub(accel_set_buffer_to)
1316 return
1317 end if
1318 end if
1319
1320 type_size = types_get_size(type)
1322 nval_ = nval*type_size
1323
1324 offset_ = 0_int64
1325 if (present(offset)) offset_ = offset*type_size
1326
1327 call cuda_mem_set_async(buffer%mem, val, nval_, offset_)
1328 if(.not. optional_default(async, .false.)) call accel_finish()
1329
1330 pop_sub(accel_set_buffer_to)
1331 end subroutine accel_set_buffer_to
1332
1333 ! ----------------------------------------------------
1334
1335 subroutine accel_set_buffer_to_zero_i8(buffer, type, nval, offset, async)
1336 type(accel_mem_t), intent(inout) :: buffer
1337 type(type_t), intent(in) :: type
1338 integer(int64), intent(in) :: nval
1339 integer(int64), optional, intent(in) :: offset
1340 logical, optional, intent(in) :: async
1343
1344 call accel_set_buffer_to(buffer, type, int(z'00', int8), nval, offset, async)
1345
1347 end subroutine accel_set_buffer_to_zero_i8
1348
1349 ! ----------------------------------------------------
1350
1351 subroutine accel_set_buffer_to_zero_i4(buffer, type, nval, offset, async)
1352 type(accel_mem_t), intent(inout) :: buffer
1353 type(type_t), intent(in) :: type
1354 integer(int32), intent(in) :: nval
1355 integer(int32), optional, intent(in) :: offset
1356 logical, optional, intent(in) :: async
1357
1359
1360 if (present(offset)) then
1361 call accel_set_buffer_to_zero_i8(buffer, type, int(nval, int64), int(offset, int64), async=async)
1362 else
1363 call accel_set_buffer_to_zero_i8(buffer, type, int(nval, int64), async=async)
1364 end if
1365
1367 end subroutine accel_set_buffer_to_zero_i4
1368
1369 ! ----------------------------------------------------
1370
1371 subroutine accel_check_bandwidth()
1372 integer :: itime
1373 integer, parameter :: times = 10
1374 integer :: size
1375 real(real64) :: time, stime
1376 real(real64) :: read_bw, write_bw
1377 type(accel_mem_t) :: buff
1378 real(real64), allocatable :: data(:)
1379
1380 call messages_new_line()
1381 call messages_write('Info: Benchmarking the bandwidth between main memory and device memory')
1382 call messages_new_line()
1383 call messages_info()
1384
1385 call messages_write(' Buffer size Read bw Write bw')
1386 call messages_new_line()
1387 call messages_write(' [MiB] [MiB/s] [MiB/s]')
1388 call messages_info()
1389
1390 size = 15000
1391 do
1392 safe_allocate(data(1:size))
1393 call accel_create_buffer(buff, accel_mem_read_write, type_float, size)
1394
1395 stime = loct_clock()
1396 do itime = 1, times
1397 call accel_write_buffer(buff, size, data)
1398 call accel_finish()
1399 end do
1400 time = (loct_clock() - stime)/real(times, real64)
1401
1402 write_bw = real(size, real64) *8.0_real64/time
1403
1404 stime = loct_clock()
1405 do itime = 1, times
1406 call accel_read_buffer(buff, size, data)
1407 end do
1408 call accel_finish()
1409
1410 time = (loct_clock() - stime)/real(times, real64)
1411 read_bw = real(size, real64) *8.0_real64/time
1412
1413 call messages_write(size*8.0_real64/1024.0_real64**2)
1414 call messages_write(write_bw/1024.0_real64**2, fmt = '(f10.1)')
1415 call messages_write(read_bw/1024.0_real64**2, fmt = '(f10.1)')
1416 call messages_info()
1417
1418 call accel_free_buffer(buff)
1419
1420 safe_deallocate_a(data)
1422 size = int(size*2.0)
1423
1424 if (size > 50000000) exit
1425 end do
1426 end subroutine accel_check_bandwidth
1427
1428 !------------------------------------------------------------
1429
1430 subroutine accel_kernel_global_init()
1431
1432 push_sub(accel_kernel_global_init)
1433
1434 nullify(head)
1435
1436 call cuda_program_map_init(accel%program_map)
1437
1438 call accel_kernel_list()
1439
1441 end subroutine accel_kernel_global_init
1442
1443 !------------------------------------------------------------
1444
1451 subroutine accel_kernel_list()
1452
1453 push_sub(accel_kernel_list)
1454
1455 call accel_program_add('axpy.cu', 'axpy<double>')
1456 call accel_program_add('axpy.cu', 'axpy<double2>')
1457 call accel_program_add('axpy.cu', 'axpby<double>')
1458 call accel_program_add('axpy.cu', 'axpby<double2>')
1459 call accel_program_add('axpy.cu', 'scal2v<double>')
1460 call accel_program_add('axpy.cu', 'scal2v<double2>')
1461 call accel_program_add('axpy.cu', 'scal2v_conj<double2>')
1462 call accel_program_add('axpy.cu', 'axpy_vec<double>')
1463 call accel_program_add('axpy.cu', 'axpy_vec<double2>')
1464 call accel_program_add('axpy.cu', 'scal_vec<double>')
1465 call accel_program_add('axpy.cu', 'scal_vec<double2>')
1466 call accel_program_add('axpy.cu', 'xpay_vec<double>')
1467 call accel_program_add('axpy.cu', 'xpay_vec<double2>')
1468 call accel_program_add('axpy.cu', 'batch_axpy_function<double>')
1469 call accel_program_add('axpy.cu', 'batch_axpy_function<double2>')
1470 call accel_program_add('axpy.cu', 'batch_ax_function_py<double>')
1471 call accel_program_add('axpy.cu', 'batch_ax_function_py<double2>')
1472
1473 call accel_program_add('batch_mul.cu', 'dmul_batch')
1474 call accel_program_add('batch_mul.cu', 'dmul_mf')
1475 call accel_program_add('batch_mul.cu', 'zmul_batch')
1476 call accel_program_add('batch_mul.cu', 'zmul_batch_conj')
1477 call accel_program_add('batch_mul.cu', 'zmul_mf')
1478 call accel_program_add('batch_mul.cu', 'zmul_mf_conj')
1479 call accel_program_add('batch_mul.cu', 'zmul_mf_z')
1480 call accel_program_add('batch_mul.cu', 'zmul_mf_z_conj')
1481
1482 call accel_program_add('boundaries.cu', 'boundaries_periodic')
1483 call accel_program_add('boundaries.cu', 'boundaries_periodic_corr')
1484 call accel_program_add('boundaries.cu', 'boundaries_periodic_recv')
1485 call accel_program_add('boundaries.cu', 'boundaries_periodic_recv_corr')
1486 call accel_program_add('boundaries.cu', 'boundaries_periodic_send')
1487
1488 call accel_program_add('copy.cu', 'add_with_map')
1489 call accel_program_add('copy.cu', 'copy')
1490 call accel_program_add('copy.cu', 'copy_complex_to_real')
1491 call accel_program_add('copy.cu', 'copy_real_to_complex')
1492 call accel_program_add('copy.cu', 'copy_with_map')
1493
1494 call accel_program_add('curl.cu', 'curl<double>')
1495 call accel_program_add('curl.cu', 'curl<double2>')
1496
1497 call accel_program_add('density.cu', 'current_accumulate')
1498 call accel_program_add('density.cu', 'density_complex')
1499 call accel_program_add('density.cu', 'density_real')
1500 call accel_program_add('density.cu', 'density_spinors')
1501
1502 call accel_program_add('dftu_projector.cu', 'dftu_pos_mat_elem')
1503 call accel_program_add('dftu_projector.cu', 'dftu_pos_mat_elem_cmplx')
1504 call accel_program_add('dftu_projector.cu', 'dftu_pos_mat_elem_cmplx_submesh')
1505 call accel_program_add('dftu_projector.cu', 'dftu_pos_mat_elem_phase')
1506 call accel_program_add('dftu_projector.cu', 'dftu_pos_mat_elem_submesh')
1507 call accel_program_add('dftu_projector.cu', 'dftu_projector_bra')
1508 call accel_program_add('dftu_projector.cu', 'dftu_projector_bra_cmplx')
1509 call accel_program_add('dftu_projector.cu', 'dftu_projector_bra_cmplx_submesh')
1510 call accel_program_add('dftu_projector.cu', 'dftu_projector_bra_submesh')
1511 call accel_program_add('dftu_projector.cu', 'dftu_projector_ket')
1512 call accel_program_add('dftu_projector.cu', 'dftu_projector_ket_cmplx')
1513 call accel_program_add('dftu_projector.cu', 'dftu_projector_ket_cmplx_submesh')
1514 call accel_program_add('dftu_projector.cu', 'dftu_projector_ket_submesh')
1515
1516 call accel_program_add('exchange_local.cu', 'exchange_accumulate_batch<double>')
1517 call accel_program_add('exchange_local.cu', 'exchange_accumulate_return_batch<double>')
1518 call accel_program_add('exchange_local.cu', 'exchange_codensity_batch<double>')
1519 call accel_program_add('exchange_local.cu', 'exchange_accumulate_batch<double2>')
1520 call accel_program_add('exchange_local.cu', 'exchange_accumulate_return_batch<double2>')
1521 call accel_program_add('exchange_local.cu', 'exchange_codensity_batch<double2>')
1522
1523 call accel_program_add('forces.cu', 'density_gradient<double>')
1524 call accel_program_add('forces.cu', 'density_gradient<double2>')
1525
1526 call accel_program_add('get_points.cu', 'get_selected_points')
1527
1528 call accel_program_add('ghost.cu', 'ghost_reorder')
1529
1530 call accel_program_add('mesh_batch.cu', 'ddot_matrix')
1531 call accel_program_add('mesh_batch.cu', 'zdot_matrix')
1532 call accel_program_add('mesh_batch.cu', 'zdot_matrix_spinors')
1533
1534 call accel_program_add('mesh_batch_single.cu', 'dbatch_dotpv_partial')
1535 call accel_program_add('mesh_batch_single.cu', 'dbatch_dotpv_reduce')
1536 call accel_program_add('mesh_batch_single.cu', 'dbatch_mf_dotp')
1537 call accel_program_add('mesh_batch_single.cu', 'zbatch_dotpv_partial')
1538 call accel_program_add('mesh_batch_single.cu', 'zbatch_dotpv_reduce')
1539 call accel_program_add('mesh_batch_single.cu', 'zbatch_mf_dotp')
1540
1541 call accel_program_add('mesh_interpolate.cu', 'mesh_interpolate<double>')
1542 call accel_program_add('mesh_interpolate.cu', 'mesh_interpolate<double2>')
1543
1544 call accel_program_add('mesh_to_cube.cu', 'cube_to_mesh_batch<double>')
1545 call accel_program_add('mesh_to_cube.cu', 'mesh_to_cube_batch<double>')
1546 call accel_program_add('mesh_to_cube.cu', 'cube_to_mesh_batch<double2>')
1547 call accel_program_add('mesh_to_cube.cu', 'mesh_to_cube_batch<double2>')
1548
1549 call accel_program_add('mul.cu', 'zmul_batch<double>')
1550 call accel_program_add('mul.cu', 'zmul_batch<double2>')
1551
1552 call accel_program_add('operate.cu', 'operate')
1553 call accel_program_add('operate.cu', 'operate_map')
1554 call accel_program_add('operate.cu', 'operate_map_antisym')
1555 call accel_program_add('operate.cu', 'operate_map_sym')
1556
1557 call accel_program_add('pack.cu', 'dpack')
1558 call accel_program_add('pack.cu', 'dunpack')
1559 call accel_program_add('pack.cu', 'zpack')
1560 call accel_program_add('pack.cu', 'zunpack')
1561
1562 call accel_program_add('pes.cu', 'zpes_flux_sph_integrate')
1563 call accel_program_add('pes.cu', 'zpes_flux_sph_integxx')
1564 call accel_program_add('pes.cu', 'zpes_flux_sph_integxx_2')
1565
1566 call accel_program_add('phase.cu', 'phase')
1567 call accel_program_add('phase.cu', 'phase_hamiltonian')
1568 call accel_program_add('phase.cu', 'update_phases')
1569
1570 call accel_program_add('phase_spiral.cu', 'phase_spiral_apply')
1571
1572 call accel_program_add('pml.cu', 'pml_apply')
1573 call accel_program_add('pml.cu', 'pml_apply_new')
1574 call accel_program_add('pml.cu', 'pml_copy')
1575 call accel_program_add('pml.cu', 'pml_update_conv')
1576 call accel_program_add('pml.cu', 'pml_update_new')
1577
1578 call accel_program_add('points.cu', 'get_points')
1579 call accel_program_add('points.cu', 'set_points')
1580
1581 call accel_program_add('projector.cu', 'projector_bra_force<double>')
1582 call accel_program_add('projector.cu', 'projector_bra_force_phase<double>')
1583 call accel_program_add('projector.cu', 'projector_bra_gather<double>')
1584 call accel_program_add('projector.cu', 'projector_bra_scatter_real<double>')
1585 call accel_program_add('projector.cu', 'projector_ket<double>')
1586 call accel_program_add('projector.cu', 'projector_ket_phase<double>')
1587 call accel_program_add('projector.cu', 'projector_ket_phase_spiral<double>')
1588 call accel_program_add('projector.cu', 'dprojector_mix')
1589 call accel_program_add('projector.cu', 'projector_r_vnl_bra<double>')
1590 call accel_program_add('projector.cu', 'projector_r_vnl_bra_phase<double>')
1591 call accel_program_add('projector.cu', 'projector_r_vnl_ket<double>')
1592 call accel_program_add('projector.cu', 'projector_r_vnl_ket_phase<double>')
1593 call accel_program_add('projector.cu', 'projector_bra_phase_gather')
1594 call accel_program_add('projector.cu', 'projector_bra_phase_spiral_gather')
1595 call accel_program_add('projector.cu', 'projector_bra_force<double2>')
1596 call accel_program_add('projector.cu', 'projector_bra_force_phase<double2>')
1597 call accel_program_add('projector.cu', 'projector_bra_gather<double2>')
1598 call accel_program_add('projector.cu', 'projector_bra_scatter_complex<double2>')
1599 call accel_program_add('projector.cu', 'projector_bra_scatter_real<double2>')
1600 call accel_program_add('projector.cu', 'projector_ket<double2>')
1601 call accel_program_add('projector.cu', 'projector_ket_phase<double2>')
1602 call accel_program_add('projector.cu', 'projector_ket_phase_spiral<double2>')
1603 call accel_program_add('projector.cu', 'zprojector_mix')
1604 call accel_program_add('projector.cu', 'projector_r_vnl_bra<double2>')
1605 call accel_program_add('projector.cu', 'projector_r_vnl_bra_phase<double2>')
1606 call accel_program_add('projector.cu', 'projector_r_vnl_ket<double2>')
1607 call accel_program_add('projector.cu', 'projector_r_vnl_ket_phase<double2>')
1608
1609 call accel_program_add('projector_commutator.cu', 'projector_commutator_bra<double>')
1610 call accel_program_add('projector_commutator.cu', 'projector_commutator_bra_phase<double>')
1611 call accel_program_add('projector_commutator.cu', 'projector_commutator_ket<double>')
1612 call accel_program_add('projector_commutator.cu', 'projector_commutator_ket_phase<double>')
1613 call accel_program_add('projector_commutator.cu', 'dprojector_mix_commutator')
1614 call accel_program_add('projector_commutator.cu', 'projector_commutator_bra<double2>')
1615 call accel_program_add('projector_commutator.cu', 'projector_commutator_bra_phase<double2>')
1616 call accel_program_add('projector_commutator.cu', 'projector_commutator_ket<double2>')
1617 call accel_program_add('projector_commutator.cu', 'projector_commutator_ket_phase<double2>')
1618 call accel_program_add('projector_commutator.cu', 'zprojector_mix_commutator')
1619
1620 call accel_program_add('split.cu', 'merge_complex')
1621 call accel_program_add('split.cu', 'split_complex')
1622
1623 call accel_program_add('symmetrize_batch.cu', 'symmetrizer_apply_single_batch<double>')
1624 call accel_program_add('symmetrize_batch.cu', 'symmetrizer_apply_single_batch<double2>')
1625
1626 call accel_program_add('uvw_to_xyz.cu', 'uvw_to_xyz')
1627
1628 call accel_program_add('vpsi.cu', 'vpsi')
1629 call accel_program_add('vpsi.cu', 'vpsi_complex')
1630 call accel_program_add('vpsi.cu', 'vpsi_spinors')
1631 call accel_program_add('vpsi.cu', 'vpsi_spinors_complex')
1632
1633 call accel_program_add('xc_dens_block.cu', 'xc_dens_apply_corrections')
1634 call accel_program_add('xc_dens_block.cu', 'xc_dens_extract_block')
1635
1636 pop_sub(accel_kernel_list)
1637 end subroutine accel_kernel_list
1638
1639 !------------------------------------------------------------
1640
1646 subroutine accel_program_add(file_name, name)
1647 character(len=*), intent(in) :: file_name
1648 character(len=*), intent(in) :: name
1649
1650 push_sub(accel_program_add)
1651
1652 call cuda_program_register(accel%program_map, string_f_to_c(trim(file_name)), &
1653 string_f_to_c(trim(name)))
1654
1655 pop_sub(accel_program_add)
1656 end subroutine accel_program_add
1657
1658 !------------------------------------------------------------
1659
1660 subroutine accel_kernel_global_end()
1661 type(accel_kernel_t), pointer :: next_head
1662
1663 push_sub(accel_kernel_global_end)
1664
1665 do
1666 if (.not. associated(head)) exit
1667 next_head => head%next
1669 head => next_head
1670 end do
1671
1672 if (accel_is_enabled()) then
1673 call cuda_program_map_end(accel%program_map)
1674 end if
1675
1677 end subroutine accel_kernel_global_end
1678
1679 !------------------------------------------------------------
1686 subroutine accel_kernel_build(this, file_name, kernel_name, flags)
1687 type(accel_kernel_t), intent(inout) :: this
1688 character(len=*), intent(in) :: file_name
1689 character(len=*), intent(in) :: kernel_name
1690 character(len=*), optional, intent(in) :: flags
1691
1692#ifdef HAVE_CUDA
1693 character(len=1000) :: all_flags
1694#endif
1695
1696 push_sub(accel_kernel_build)
1697
1698 call profiling_in("ACCEL_COMPILE", exclude = .true.)
1699
1700#ifdef HAVE_CUDA
1701 all_flags = '-I'//trim(conf%share)//'/kernels/'//" "//trim(accel%debug_flag)
1702
1703 if (present(flags)) then
1704 all_flags = trim(all_flags)//' '//trim(flags)
1705 end if
1706
1707 call cuda_program_build(accel%program_map, accel%device%cuda_device, &
1708 string_f_to_c(trim(file_name)), string_f_to_c(trim(all_flags)))
1709
1710 call cuda_program_get_kernel(this%cuda_kernel, accel%program_map, &
1711 string_f_to_c(trim(file_name)), string_f_to_c(trim(all_flags)), &
1712 string_f_to_c(trim(kernel_name)))
1713 call cuda_alloc_arg_array(this%arguments)
1714#endif
1715
1716 this%initialized = .true.
1717 this%kernel_name = trim(kernel_name)
1718
1719 call profiling_out("ACCEL_COMPILE")
1720
1721 pop_sub(accel_kernel_build)
1722 end subroutine accel_kernel_build
1723
1724 !------------------------------------------------------------
1726 subroutine accel_kernel_end(this)
1727 type(accel_kernel_t), intent(inout) :: this
1728
1729 push_sub(accel_kernel_end)
1730
1731#ifdef HAVE_CUDA
1732 call cuda_free_arg_array(this%arguments)
1733 call cuda_release_kernel(this%cuda_kernel)
1734 ! modules are not released here, since they are not associated to a kernel
1735#endif
1736
1737 this%initialized = .false.
1738
1739 pop_sub(accel_kernel_end)
1740 end subroutine accel_kernel_end
1741
1742 !------------------------------------------------------------
1743
1744 subroutine accel_kernel_start_call(this, file_name, kernel_name, flags)
1745 type(accel_kernel_t), target, intent(inout) :: this
1746 character(len=*), intent(in) :: file_name
1747 character(len=*), intent(in) :: kernel_name
1748 character(len=*), optional, intent(in) :: flags
1749
1750 push_sub(accel_kernel_start_call)
1751
1752 if (.not. this%initialized) then
1753 call accel_kernel_build(this, file_name, kernel_name, flags)
1754 this%next => head
1755 head => this
1756 end if
1757
1759 end subroutine accel_kernel_start_call
1760
1761 !--------------------------------------------------------------
1762
1763 integer(int64) pure function accel_global_memory_size() result(size)
1764
1765 size = accel%global_memory_size
1766
1767 end function accel_global_memory_size
1768
1769 !--------------------------------------------------------------
1770
1771 integer(int64) pure function accel_shared_memory_size() result(size)
1772
1773 size = accel%shared_memory_size
1774
1775 end function accel_shared_memory_size
1776 !--------------------------------------------------------------
1778 integer pure function accel_max_size_per_dim(dim) result(size)
1779 integer, intent(in) :: dim
1780
1781 size = 0
1782#ifdef HAVE_CUDA
1783 size = 32768
1784 if (dim == 1) size = 2**30
1785#endif
1786 end function accel_max_size_per_dim
1787
1788 ! ------------------------------------------------------
1790 subroutine accel_set_stream(stream_number)
1791 integer, intent(in) :: stream_number
1792
1793 push_sub(accel_set_stream)
1794
1795 if (accel_is_enabled()) then
1796#ifdef HAVE_CUDA
1797 call cuda_set_stream(accel%cuda_stream, stream_number)
1798 call cublas_set_stream(accel%cublas_handle, accel%cuda_stream)
1799#endif
1800 end if
1801
1802 pop_sub(accel_set_stream)
1803 end subroutine accel_set_stream
1805 ! ------------------------------------------------------
1806
1807 subroutine accel_get_stream(stream_number)
1808 integer, intent(inout) :: stream_number
1809
1810 push_sub(accel_get_stream)
1811
1812 if (accel_is_enabled()) then
1813#ifdef HAVE_CUDA
1814 call cuda_get_stream(stream_number)
1815#endif
1816 end if
1817
1818 pop_sub(accel_get_stream)
1819 end subroutine accel_get_stream
1820
1821 ! ------------------------------------------------------
1822
1825
1826 if (accel_is_enabled()) then
1827#ifdef HAVE_CUDA
1828 call cuda_synchronize_all_streams()
1829#endif
1830 end if
1831
1833 end subroutine accel_synchronize_all_streams
1834
1835 function daccel_get_pointer_with_offset(buffer, offset) result(buffer_offset)
1836 type(c_ptr), intent(in) :: buffer
1837 integer(int64), intent(in) :: offset
1838 type(c_ptr) :: buffer_offset
1839
1841#ifdef HAVE_CUDA
1842 call cuda_get_pointer_with_offset(buffer, offset, buffer_offset)
1843#else
1844 ! this is needed to make the compiler happy for non-GPU compilations
1845 buffer_offset = buffer
1846#endif
1849
1850 function zaccel_get_pointer_with_offset(buffer, offset) result(buffer_offset)
1851 type(c_ptr), intent(in) :: buffer
1852 integer(int64), intent(in) :: offset
1853 type(c_ptr) :: buffer_offset
1854
1856#ifdef HAVE_CUDA
1857 call cuda_get_pointer_with_offset(buffer, 2_int64*offset, buffer_offset)
1858#else
1859 ! this is needed to make the compiler happy for non-GPU compilations
1860 buffer_offset = buffer
1861#endif
1864
1865 subroutine accel_clean_pointer(buffer)
1866 type(c_ptr), intent(in) :: buffer
1867
1868 push_sub(accel_clean_pointer)
1869#ifdef HAVE_CUDA
1870 call cuda_clean_pointer(buffer)
1871#endif
1872 pop_sub(accel_clean_pointer)
1873 end subroutine accel_clean_pointer
1874
1878 subroutine accel_get_unfolded_size(size, grid_size, thread_block_size)
1879 integer(int64), intent(in) :: size
1880 integer(int64), intent(out) :: grid_size
1881 integer(int64), intent(out) :: thread_block_size
1882
1883 push_sub(accel_get_unfolded_size)
1884#ifdef __HIP_PLATFORM_AMD__
1885 ! not benefitial for AMD chips
1886 grid_size = 1_int64
1887 thread_block_size = size
1888#else
1889 grid_size = size
1890 thread_block_size = accel%warp_size
1891#endif
1893 end subroutine accel_get_unfolded_size
1894
1895#include "undef.F90"
1896#include "real.F90"
1897#include "accel_inc.F90"
1898
1899#include "undef.F90"
1900#include "complex.F90"
1901#include "accel_inc.F90"
1902
1903#include "undef.F90"
1904#include "integer.F90"
1905#include "accel_inc.F90"
1906
1907#include "undef.F90"
1908#include "integer8.F90"
1909#include "accel_inc.F90"
1910
1911end module accel_oct_m
1912
1913!! Local Variables:
1914!! mode: f90
1915!! coding: utf-8
1916!! End:
subroutine device_info()
Definition: accel.F90:647
subroutine accel_grid_size_i4(n, blocksizes, gridsizes)
Computes the grid size for a given problem size and block size (32-bit version).
Definition: accel.F90:838
subroutine laccel_get_device_pointer_3l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:6147
subroutine zaccel_get_device_pointer_2l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:3936
subroutine, public accel_clean_pointer(buffer)
Definition: accel.F90:1820
subroutine accel_kernel_global_end()
Definition: accel.F90:1631
subroutine zaccel_write_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:3114
subroutine, public accel_get_unfolded_size(size, grid_size, thread_block_size)
Get unfolded size: some kernels (e.g. projectors) unfold the array across warps as an optimization....
Definition: accel.F90:1833
subroutine laccel_read_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:5943
subroutine laccel_read_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:5702
type(accel_kernel_t), target, save, public dzmul_batch
Definition: accel.F90:286
subroutine iaccel_write_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:4176
pure logical function, public accel_allow_cpu_only()
Definition: accel.F90:413
subroutine daccel_get_device_pointer_1(host_pointer, device_pointer, dimensions)
Definition: accel.F90:2750
subroutine zaccel_read_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:3756
subroutine daccel_read_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:2472
subroutine zaccel_get_device_pointer_1(host_pointer, device_pointer, dimensions)
Definition: accel.F90:3843
subroutine laccel_read_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:5726
type(accel_kernel_t), target, save, public dkernel_batch_dotp
Definition: accel.F90:284
subroutine zaccel_create_blas_alpha_beta_buffer(this, data, async)
Definition: accel.F90:3985
subroutine daccel_write_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:2230
subroutine laccel_write_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:5301
subroutine daccel_write_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:2202
subroutine laccel_get_device_pointer_1(host_pointer, device_pointer, dimensions)
Definition: accel.F90:6030
subroutine zaccel_read_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:3593
subroutine zaccel_read_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:3425
integer function, public accel_kernel_block_size(kernel)
Definition: accel.F90:1210
subroutine zaccel_write_buffer_single(this, data, async)
Definition: accel.F90:3011
subroutine daccel_read_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:2391
subroutine iaccel_get_device_pointer_3l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:5053
subroutine zaccel_read_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:3484
subroutine laccel_get_device_pointer_2(host_pointer, device_pointer, dimensions)
Definition: accel.F90:6054
subroutine iaccel_write_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:4388
subroutine zaccel_write_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:3389
subroutine accel_grid_size_array_i8(n, blocksizes, gridsizes)
Computes the grid size for a given problem size and block size (64-bit version).
Definition: accel.F90:788
subroutine laccel_write_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:5542
subroutine zaccel_read_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:3515
subroutine iaccel_write_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:4157
subroutine zaccel_release_blas_alpha_beta_buffer(this, data, async)
Definition: accel.F90:4012
subroutine laccel_write_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:5379
subroutine, public accel_free_buffer(this, async)
Definition: accel.F90:1002
subroutine daccel_write_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:2045
subroutine iaccel_write_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:4315
subroutine, public accel_kernel_start_call(this, file_name, kernel_name, flags)
Definition: accel.F90:1699
subroutine iaccel_write_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:4207
subroutine zaccel_write_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:3164
subroutine iaccel_release_blas_alpha_beta_buffer(this, data, async)
Definition: accel.F90:5105
subroutine iaccel_read_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:4789
subroutine zaccel_write_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:3260
subroutine, public accel_get_stream(stream_number)
Definition: accel.F90:1762
subroutine accel_create_buffer_4(this, flags, type, size, set_zero, async)
Definition: accel.F90:933
subroutine zaccel_read_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:3642
subroutine iaccel_write_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:4285
integer(int64) pure function, public accel_global_memory_size()
Definition: accel.F90:1718
subroutine daccel_read_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:2446
subroutine laccel_write_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:5251
type(accel_kernel_t), target, save, public zkernel_ax_function_py
Definition: accel.F90:283
subroutine daccel_read_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:2372
subroutine daccel_write_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:1990
subroutine zaccel_set_kernel_arg_data(kernel, narg, data)
Definition: accel.F90:3827
subroutine daccel_get_device_pointer_3l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:2867
subroutine iaccel_read_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:4608
subroutine daccel_get_device_pointer_2l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:2843
integer(int64) function accel_padded_size_i8(nn)
Definition: accel.F90:903
subroutine accel_check_bandwidth()
Definition: accel.F90:1342
subroutine iaccel_write_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:4416
subroutine daccel_read_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:2697
subroutine laccel_read_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:5612
subroutine daccel_write_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:1931
subroutine iaccel_create_blas_alpha_beta_buffer(this, data, async)
Definition: accel.F90:5078
subroutine zaccel_read_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:3623
subroutine iaccel_get_device_pointer_1l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:5004
subroutine, public accel_finish()
Definition: accel.F90:1120
subroutine laccel_write_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:5510
subroutine accel_kernel_global_init()
Definition: accel.F90:1401
subroutine zaccel_read_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:3696
subroutine daccel_read_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:2500
subroutine accel_kernel_run_4(kernel, gridsizes, blocksizes, shared_memory_size)
Run a kernel with 4-byte integer sizes.
Definition: accel.F90:1192
subroutine zaccel_write_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:3064
subroutine iaccel_get_device_pointer_1(host_pointer, device_pointer, dimensions)
Definition: accel.F90:4936
subroutine laccel_read_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:5977
subroutine, public accel_copy_buffer(dest, src, type, nval, offset_dest, offset_src, async)
Copy nval elements of the given type between two device buffers.
Definition: accel.F90:1224
subroutine accel_grid_size_extend_dim_i4(n, pack_size, gridsizes, blocksizes, kernel)
Helper function to compute the grid for the kernels that relies on the batch size (pack_size) and the...
Definition: accel.F90:885
subroutine laccel_create_blas_alpha_beta_buffer(this, data, async)
Definition: accel.F90:6172
subroutine, public accel_ensure_buffer_size(buffer, flags, type, required_size, set_zero, async)
Definition: accel.F90:1088
subroutine accel_set_buffer_to(buffer, type, val, nval, offset, async)
Definition: accel.F90:1265
subroutine, public accel_move_buffer(buffer_from, buffer_to)
Move the buffer memory from the first buffer to the second.
Definition: accel.F90:1045
subroutine, public accel_detach_buffer(this)
Clear a buffer handle without freeing device memory.
Definition: accel.F90:1071
subroutine laccel_set_kernel_arg_data(kernel, narg, data)
Definition: accel.F90:6014
subroutine iaccel_write_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:4257
subroutine daccel_write_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:1971
subroutine daccel_read_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:2530
subroutine zaccel_read_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:3465
subroutine iaccel_write_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:4448
subroutine daccel_read_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:2422
subroutine laccel_write_buffer_single(this, data, async)
Definition: accel.F90:5198
subroutine laccel_read_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:5780
subroutine daccel_get_device_pointer_2(host_pointer, device_pointer, dimensions)
Definition: accel.F90:2774
subroutine accel_kernel_run_8(kernel, gridsizes, blocksizes, shared_memory_size)
Run a kernel with 8-byte integer sizes.
Definition: accel.F90:1154
subroutine iaccel_read_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:4754
subroutine zaccel_write_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:3222
subroutine zaccel_write_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:3241
subroutine accel_set_buffer_to_zero_i8(buffer, type, nval, offset, async)
Definition: accel.F90:1306
subroutine zaccel_get_device_pointer_1l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:3911
logical pure function, public accel_buffer_is_allocated(this)
Definition: accel.F90:1112
integer, parameter, public accel_mem_read_write
Definition: accel.F90:187
subroutine daccel_create_blas_alpha_beta_buffer(this, data, async)
Definition: accel.F90:2892
subroutine accel_kernel_end(this)
Definition: accel.F90:1681
type(accel_kernel_t), target, save, public dkernel_ax_function_py
Definition: accel.F90:282
subroutine laccel_write_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:5482
subroutine zaccel_write_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:3355
subroutine zaccel_get_device_pointer_2(host_pointer, device_pointer, dimensions)
Definition: accel.F90:3867
subroutine daccel_write_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:2021
subroutine laccel_read_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:5848
type(c_ptr) function, public daccel_get_pointer_with_offset(buffer, offset)
Definition: accel.F90:1790
subroutine iaccel_write_buffer_single(this, data, async)
Definition: accel.F90:4104
subroutine iaccel_get_device_pointer_2(host_pointer, device_pointer, dimensions)
Definition: accel.F90:4960
integer pure function, public accel_max_size_per_dim(dim)
Definition: accel.F90:1733
subroutine zaccel_read_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:3539
subroutine iaccel_read_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:4518
subroutine daccel_read_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:2332
subroutine iaccel_read_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:4735
subroutine accel_grid_size_array_i4(n, blocksizes, gridsizes)
Computes the grid size for a given problem size and block size (32-bit version).
Definition: accel.F90:808
subroutine iaccel_read_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:4849
subroutine laccel_write_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:5325
subroutine laccel_write_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:5409
subroutine zaccel_write_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:3083
subroutine laccel_read_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:5810
subroutine laccel_get_device_pointer_2l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:6123
subroutine iaccel_get_device_pointer_3(host_pointer, device_pointer, dimensions)
Definition: accel.F90:4982
subroutine zaccel_write_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:3138
subroutine zaccel_write_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:3295
subroutine daccel_set_kernel_arg_data(kernel, narg, data)
Definition: accel.F90:2734
subroutine iaccel_read_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:4558
subroutine accel_grid_size_extend_dim_i8(n, pack_size, gridsizes, blocksizes, kernel)
Helper function to compute the grid for the kernels that relies on the batch size (pack_size) and the...
Definition: accel.F90:855
subroutine, public accel_kernel_build(this, file_name, kernel_name, flags)
Compile the program that contains a given kernel.
Definition: accel.F90:1657
subroutine, public accel_init(base_grp, namespace)
Definition: accel.F90:423
subroutine, public accel_end(namespace)
Definition: accel.F90:704
subroutine laccel_write_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:5211
subroutine daccel_write_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:2099
subroutine zaccel_read_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:3565
subroutine, public accel_synchronize_all_streams()
Definition: accel.F90:1778
subroutine, public accel_set_stream(stream_number)
Definition: accel.F90:1745
subroutine laccel_read_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:5671
subroutine daccel_release_blas_alpha_beta_buffer(this, data, async)
Definition: accel.F90:2919
subroutine iaccel_read_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:4817
subroutine iaccel_read_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:4632
subroutine laccel_get_device_pointer_1l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:6098
subroutine iaccel_read_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:4716
subroutine accel_grid_size_i8(n, blocksizes, gridsizes)
Computes the grid size for a given problem size and block size (64-bit version).
Definition: accel.F90:823
subroutine iaccel_write_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:4482
integer(int32) function accel_padded_size_i4(nn)
Definition: accel.F90:924
subroutine accel_set_buffer_to_zero_i4(buffer, type, nval, offset, async)
Definition: accel.F90:1322
subroutine daccel_write_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:2296
type(accel_kernel_t), target, save, public zkernel_batch_dotp
Definition: accel.F90:285
subroutine laccel_write_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:5428
subroutine iaccel_get_device_pointer_2l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:5029
subroutine iaccel_write_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:4353
pure logical function, public accel_is_enabled()
Definition: accel.F90:403
subroutine zaccel_read_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:3790
subroutine daccel_write_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:2129
subroutine iaccel_write_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:4231
subroutine daccel_write_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:2167
subroutine iaccel_write_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:4334
integer, parameter, public accel_mem_write_only
Definition: accel.F90:187
subroutine zaccel_write_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:3323
subroutine daccel_read_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:2603
subroutine laccel_write_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:5576
subroutine laccel_read_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:5829
subroutine daccel_read_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:2549
subroutine laccel_read_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:5911
subroutine daccel_write_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:2071
subroutine daccel_get_device_pointer_1l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:2818
subroutine laccel_release_blas_alpha_beta_buffer(this, data, async)
Definition: accel.F90:6199
subroutine iaccel_read_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:4577
subroutine laccel_write_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:5351
subroutine laccel_write_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:5270
subroutine daccel_write_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:2262
subroutine laccel_write_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:5447
subroutine zaccel_get_device_pointer_3(host_pointer, device_pointer, dimensions)
Definition: accel.F90:3889
type(c_ptr) function, public zaccel_get_pointer_with_offset(buffer, offset)
Definition: accel.F90:1805
subroutine iaccel_read_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:4883
subroutine laccel_read_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:5883
subroutine daccel_write_buffer_single(this, data, async)
Definition: accel.F90:1918
subroutine daccel_write_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:2148
subroutine zaccel_write_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:3024
type(accel_t), public accel
Definition: accel.F90:251
subroutine laccel_get_device_pointer_3(host_pointer, device_pointer, dimensions)
Definition: accel.F90:6076
subroutine iaccel_read_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:4686
integer(int64) pure function, public accel_shared_memory_size()
Definition: accel.F90:1726
integer pure function, public accel_max_block_size()
Definition: accel.F90:1204
subroutine iaccel_set_kernel_arg_data(kernel, narg, data)
Definition: accel.F90:4920
subroutine daccel_read_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:2568
subroutine iaccel_read_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:4658
subroutine iaccel_write_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:4117
subroutine zaccel_get_device_pointer_3l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:3960
subroutine accel_create_buffer_8(this, flags, type, size, set_zero, async)
Definition: accel.F90:946
subroutine laccel_read_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:5652
subroutine daccel_read_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:2663
subroutine daccel_read_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:2631
subroutine accel_program_add(file_name, name)
Register a kernel for later retrieval.
Definition: accel.F90:1617
subroutine accel_set_kernel_arg_buffer(kernel, narg, buffer)
Definition: accel.F90:1132
subroutine accel_kernel_list()
The kernels each source provides.
Definition: accel.F90:1422
subroutine laccel_read_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:5752
subroutine zaccel_read_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:3661
subroutine zaccel_write_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:3192
subroutine daccel_get_device_pointer_3(host_pointer, device_pointer, dimensions)
Definition: accel.F90:2796
type(accel_kernel_t), pointer head
Definition: accel.F90:397
subroutine zaccel_read_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:3724
subroutine, public alloc_cache_put(alloc_cache, size, loc, put)
subroutine, public alloc_cache_get(alloc_cache, size, found, loc)
integer(int64), parameter, public alloc_cache_any_size
real(real64), parameter, public m_zero
Definition: global.F90:200
complex(real64), parameter, public m_z0
Definition: global.F90:210
complex(real64), parameter, public m_z1
Definition: global.F90:211
real(real64), parameter, public m_one
Definition: global.F90:201
System information (time, memory, sysname)
Definition: loct.F90:117
subroutine string_c_to_f(c_string, f_string)
convert a C string to a Fortran string
Definition: loct.F90:258
subroutine, public loct_sysname(name)
Definition: loct.F90:332
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:898
character(len=512), private msg
Definition: messages.F90:167
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1000
subroutine, public messages_new_line()
Definition: messages.F90:1089
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:691
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
type(type_t), parameter, public type_cmplx
Definition: types.F90:136
integer pure function, public types_get_size(this)
Definition: types.F90:154
type(type_t), parameter, public type_float
Definition: types.F90:135
type(type_t), parameter, public type_none
Definition: types.F90:134
This module defines the unit system, used for input and output.
type(unit_t), public unit_gigabytes
For larger amounts of data (natural code units are bytes)
type(unit_t), public unit_megabytes
For large amounts of data (natural code units are bytes)
type(unit_t), public unit_kilobytes
For small amounts of data (natural code units are bytes)
int true(void)