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, &
89
90 integer, public, parameter :: &
91 ACCEL_MEM_READ_ONLY = 0, &
94
96 ! Components are public by default
97#if defined(HAVE_CUDA)
98 type(c_ptr) :: cuda_context
99#else
100 integer :: dummy
101#endif
102 end type accel_context_t
103
104 type accel_device_t
105 ! Components are public by default
106#if defined(HAVE_CUDA)
107 type(c_ptr) :: cuda_device
108#else
109 integer :: dummy
110#endif
111 end type accel_device_t
112
113 type accel_t
114 ! Components are public by default
115 type(accel_context_t) :: context
116 type(accel_device_t) :: device
117 type(c_ptr) :: cuda_stream
118 type(c_ptr) :: program_map
119 integer :: max_block_size
120 integer(int64) :: shared_memory_size
121 integer(int64) :: global_memory_size
122 logical :: enabled
123 logical :: allow_CPU_only
124 logical :: cuda_mpi
125 integer :: warp_size
126 integer(int64) :: initialize_buffers
127 character(len=32) :: debug_flag
128 integer(int64) :: max_block_dim(3)
129 integer(int64) :: max_grid_dim(3)
130 end type accel_t
131
132 type accel_mem_t
133 ! Components are public by default
134 type(c_ptr) :: mem
135 integer(c_size_t) :: size = 0
136 type(type_t) :: type
137 integer :: flags = 0
138 logical :: allocated = .false.
139 end type accel_mem_t
140
141 type accel_kernel_t
142 ! Components are public by default
143#ifdef HAVE_CUDA
144 type(c_ptr) :: cuda_kernel
145 type(c_ptr) :: arguments
146#endif
147 logical :: initialized = .false.
148 type(accel_kernel_t), pointer :: next
149 integer :: arg_count
150 character(len=128) :: kernel_name
151 end type accel_kernel_t
152
153 type(accel_t), public :: accel
154
155 ! the kernels
156 type(accel_kernel_t), public, target, save :: kernel_vpsi
157 type(accel_kernel_t), public, target, save :: kernel_vpsi_complex
158 type(accel_kernel_t), public, target, save :: kernel_vpsi_spinors
159 type(accel_kernel_t), public, target, save :: kernel_vpsi_spinors_complex
160 type(accel_kernel_t), public, target, save :: kernel_daxpy
161 type(accel_kernel_t), public, target, save :: kernel_zaxpy
162 type(accel_kernel_t), public, target, save :: kernel_copy
163 type(accel_kernel_t), public, target, save :: kernel_copy_complex_to_real
164 type(accel_kernel_t), public, target, save :: kernel_copy_real_to_complex
165 type(accel_kernel_t), public, target, save :: dpack
166 type(accel_kernel_t), public, target, save :: zpack
167 type(accel_kernel_t), public, target, save :: dunpack
168 type(accel_kernel_t), public, target, save :: zunpack
169 type(accel_kernel_t), public, target, save :: kernel_ghost_reorder
170 type(accel_kernel_t), public, target, save :: kernel_density_real
171 type(accel_kernel_t), public, target, save :: kernel_density_complex
172 type(accel_kernel_t), public, target, save :: kernel_density_spinors
173 type(accel_kernel_t), public, target, save :: kernel_phase
174 type(accel_kernel_t), public, target, save :: kernel_phase_spiral
175 type(accel_kernel_t), public, target, save :: zkernel_dot_matrix_spinors
176 type(accel_kernel_t), public, target, save :: dzmul_batch
177 type(accel_kernel_t), public, target, save :: zzmul_batch
178
179 interface accel_grid_size
181 end interface accel_grid_size
182
186
187 interface accel_padded_size
189 end interface accel_padded_size
191 interface accel_create_buffer
193 end interface accel_create_buffer
194
196 module procedure accel_kernel_run_4, accel_kernel_run_8
197 end interface accel_kernel_run
198
201 end interface accel_set_buffer_to_zero
202
203 interface accel_write_buffer
226 end interface accel_write_buffer
228 interface accel_read_buffer
243 end interface accel_read_buffer
246 module procedure &
270 integer(int64) :: allocated_mem
271 type(accel_kernel_t), pointer :: head
273
274contains
275
276 pure logical function accel_is_enabled() result(enabled)
277#ifdef HAVE_ACCEL
278 enabled = accel%enabled
279#else
280 enabled = .false.
281#endif
282 end function accel_is_enabled
283
284 ! ------------------------------------------
285
286 pure logical function accel_allow_cpu_only() result(allow)
287#ifdef HAVE_ACCEL
288 allow = accel%allow_CPU_only
289#else
290 allow = .true.
291#endif
292 end function accel_allow_cpu_only
293
294 ! ------------------------------------------
295
296 subroutine accel_init(base_grp, namespace)
297 type(mpi_grp_t), intent(inout) :: base_grp
298 type(namespace_t), intent(in) :: namespace
299
300 logical :: disable, default, run_benchmark
301 integer :: idevice
302#ifdef HAVE_CUDA
303 integer :: dim
304#ifdef HAVE_MPI
305 character(len=256) :: sys_name
306#endif
307#endif
308
309 push_sub(accel_init)
310
312
313 !%Variable DisableAccel
314 !%Type logical
315 !%Default yes
316 !%Section Execution::Accel
317 !%Description
318 !% If Octopus was compiled with CUDA support, it will
319 !% try to initialize and use an accelerator device. By setting this
320 !% variable to <tt>yes</tt> you force Octopus not to use an accelerator even it is available.
321 !%End
322 call messages_obsolete_variable(namespace, 'DisableOpenCL', 'DisableAccel')
323#ifdef HAVE_ACCEL
324 default = .false.
325#else
326 default = .true.
327#endif
328 call parse_variable(namespace, 'DisableAccel', default, disable)
329 accel%enabled = .not. disable
330
331#ifndef HAVE_ACCEL
332 if (accel%enabled) then
333 message(1) = 'Octopus was compiled without Cuda support.'
334 call messages_fatal(1)
335 end if
336#endif
337
338 if (.not. accel_is_enabled()) then
339 pop_sub(accel_init)
340 return
341 end if
342
343 call messages_obsolete_variable(namespace, 'AccelPlatform')
344 call messages_obsolete_variable(namespace, 'OpenCLPlatform', 'AccelPlatform')
345
346 !%Variable AccelDevice
347 !%Type integer
348 !%Default 0
349 !%Section Execution::Accel
350 !%Description
351 !% This variable selects the GPU that Octopus will use. You can specify a
352 !% numerical id to select a specific device.
353 !%
354 !% In case of MPI enabled runs devices are distributed in a round robin fashion,
355 !% starting at this value.
356 !%End
357 call parse_variable(namespace, 'AccelDevice', 0, idevice)
358
359 call messages_obsolete_variable(namespace, 'OpenCLDevice', 'AccelDevice')
360
361 if (idevice < 0) then
362 call messages_write('Invalid AccelDevice')
363 call messages_fatal()
364 end if
366 call messages_print_with_emphasis(msg="GPU acceleration", namespace=namespace)
368#ifdef HAVE_CUDA
369 if (idevice<0) idevice = 0
370 call cuda_init(accel%context%cuda_context, accel%device%cuda_device, accel%cuda_stream, &
371 idevice, base_grp%rank)
372#ifdef HAVE_MPI
373 call loct_sysname(sys_name)
374 write(message(1), '(A,I5,A,I5,2A)') "Rank ", base_grp%rank, " uses device number ", idevice, &
375 " on ", trim(sys_name)
376 call messages_info(1, all_nodes = .true.)
377#endif
378
379 call cublas_init(accel%cuda_stream)
380#endif
382
383 ! Get some device information that we will need later
384#ifdef HAVE_CUDA
385 call cuda_device_total_memory(accel%device%cuda_device, accel%global_memory_size)
386 call cuda_device_shared_memory(accel%device%cuda_device, accel%shared_memory_size)
387 call cuda_device_max_threads_per_block(accel%device%cuda_device, accel%max_block_size)
388 call cuda_device_get_warpsize(accel%device%cuda_device, accel%warp_size)
389 call cuda_device_max_block_dim_x(accel%device%cuda_device, dim)
390 accel%max_block_dim(1) = int(dim, int64)
391 call cuda_device_max_block_dim_y(accel%device%cuda_device, dim)
392 accel%max_block_dim(2) = int(dim, int64)
393 call cuda_device_max_block_dim_z(accel%device%cuda_device, dim)
394 accel%max_block_dim(3) = int(dim, int64)
395 call cuda_device_max_grid_dim_x(accel%device%cuda_device, dim)
396 accel%max_grid_dim(1) = int(dim, int64)
397 call cuda_device_max_grid_dim_y(accel%device%cuda_device, dim)
398 accel%max_grid_dim(2) = int(dim, int64)
399 call cuda_device_max_grid_dim_z(accel%device%cuda_device, dim)
400 accel%max_grid_dim(3) = int(dim, int64)
401#endif
402
403 if (base_grp%is_root()) call device_info()
404
405 ! initialize the cache used to speed up allocations
406 call alloc_cache_init(memcache, nint(0.25_real64*accel%global_memory_size, int64))
407
408 ! now initialize the kernels
410
411#if defined(HAVE_HIP)
412 accel%debug_flag = "-g"
413#elif defined(HAVE_CUDA)
414 accel%debug_flag = "-lineinfo"
415#endif
416
417 call accel_kernel_start_call(kernel_vpsi, 'vpsi.cu', "vpsi<double>")
418 call accel_kernel_start_call(kernel_vpsi_complex, 'vpsi.cu', "vpsi_complex<double>")
419 call accel_kernel_start_call(kernel_vpsi_spinors, 'vpsi.cu', "vpsi_spinors<double>")
420 call accel_kernel_start_call(kernel_vpsi_spinors_complex, 'vpsi.cu', "vpsi_spinors_complex<double>")
421 call accel_kernel_start_call(kernel_daxpy, 'axpy.cu', "axpy<double>")
422 call accel_kernel_start_call(kernel_zaxpy, 'axpy.cu', "axpy<complex<double>>")
423 call accel_kernel_start_call(dpack, 'pack.cu', "pack<double>")
424 call accel_kernel_start_call(zpack, 'pack.cu', "pack<complex<double>>")
425 call accel_kernel_start_call(dunpack, 'pack.cu', "unpack<double>")
426 call accel_kernel_start_call(zunpack, 'pack.cu', "unpack<complex<double>>")
427 call accel_kernel_start_call(kernel_copy, 'copy.cu', "copy<double>")
428 call accel_kernel_start_call(kernel_copy_complex_to_real, 'copy.cu', "copy_complex_to_real<double>")
429 call accel_kernel_start_call(kernel_copy_real_to_complex, 'copy.cu', "copy_real_to_complex<double>")
430 call accel_kernel_start_call(kernel_ghost_reorder, 'ghost.cu', "ghost_reorder<double>")
431 call accel_kernel_start_call(kernel_density_real, 'density.cu', "density<double, double>")
432 call accel_kernel_start_call(kernel_density_complex, 'density.cu', "density<double, complex<double>>")
433 call accel_kernel_start_call(kernel_density_spinors, 'density.cu', "density_spinors<double>")
434 call accel_kernel_start_call(kernel_phase, 'phase.cu', "phase<double>")
435 call accel_kernel_start_call(zkernel_dot_matrix_spinors, 'mesh_batch.cu', "zdot_matrix_spinors<double>")
436
437
438 call accel_kernel_start_call(dzmul_batch, 'mul.cu', 'zmul_batch<double, double>')
439 call accel_kernel_start_call(zzmul_batch, 'mul.cu', 'zmul_batch<double, complex<double>>')
440
441
442 !%Variable AccelBenchmark
443 !%Type logical
444 !%Default no
445 !%Section Execution::Accel
446 !%Description
447 !% If this variable is set to yes, Octopus will run some
448 !% routines to benchmark the performance of the accelerator device.
449 !%End
450 call parse_variable(namespace, 'AccelBenchmark', .false., run_benchmark)
451
452 call messages_obsolete_variable(namespace, 'OpenCLBenchmark', 'AccelBenchmark')
453
454 if (run_benchmark) then
456 end if
457
458 !%Variable GPUAwareMPI
459 !%Type logical
460 !%Section Execution::Accel
461 !%Description
462 !% If Octopus was compiled with GPU support and MPI support and if the MPI
463 !% implementation is GPU-aware (i.e., it supports communication using device pointers),
464 !% this switch can be set to true to use the GPU-aware MPI features. The advantage
465 !% of this approach is that it can do, e.g., peer-to-peer copies between devices without
466 !% going through the host memory.
467 !% The default is false, except when the configure switch --enable-cudampi is set, in which
468 !% case this variable is set to true.
469 !%End
470#ifdef HAVE_CUDA_MPI
471 default = .true.
472#else
473 default = .false.
474#endif
475 call parse_variable(namespace, 'GPUAwareMPI', default, accel%cuda_mpi)
476 if (accel%cuda_mpi) then
477#ifndef HAVE_CUDA_MPI
478 call messages_write("Warning: trying to use GPU-aware MPI, but we have not detected support in the linked MPI library.")
479 call messages_warning()
480#endif
481 call messages_write("Using GPU-aware MPI.")
482 call messages_info()
483 end if
484
485
486 !%Variable AllowCPUonly
487 !%Type logical
488 !%Section Execution::Accel
489 !%Description
490 !% In order to prevent waste of resources, the code will normally stop when the GPU is disabled due to
491 !% incomplete implementations or incompatibilities. AllowCPUonly = yes overrides this and allows the
492 !% code execution also in these cases.
493 !%End
494#if defined (HAVE_ACCEL)
495 default = .false.
496#else
497 default = .true.
498#endif
499 call parse_variable(namespace, 'AllowCPUonly', default, accel%allow_CPU_only)
500
501
502 !%Variable InitializeGPUBuffers
503 !%Type integer
504 !%Default no
505 !%Section Execution::Accel
506 !%Description
507 !% Initialize new GPU buffers to zero on creation (use only for debugging, as it has a performance impact!).
508 !%Option no 0
509 !% Do not initialize GPU buffers.
510 !%Option yes 1
511 !% Initialize GPU buffers to zero.
512 !%Option nan 2
513 !% Initialize GPU buffers to nan.
514 !%End
515 call parse_variable(namespace, 'InitializeGPUBuffers', option__initializegpubuffers__no, accel%initialize_buffers)
516 if (.not. varinfo_valid_option('InitializeGPUBuffers', accel%initialize_buffers)) then
517 call messages_input_error(namespace, 'InitializeGPUBuffers')
518 end if
519
520
521 call messages_print_with_emphasis(namespace=namespace)
522
523 pop_sub(accel_init)
524
525 contains
526
527 subroutine device_info()
528#ifdef HAVE_CUDA
529 integer :: version
530 character(kind=c_char) :: cval_str(257)
531#endif
532 integer :: major, minor
533 character(len=256) :: val_str
534
535 push_sub(accel_init.device_info)
536
537 call messages_new_line()
538 call messages_write('Selected device:')
539 call messages_new_line()
540
541#ifdef HAVE_CUDA
542#ifdef __HIP_PLATFORM_AMD__
543 call messages_write(' Framework : ROCm')
544#else
545 call messages_write(' Framework : CUDA')
546#endif
547#endif
548 call messages_info()
549
550#ifdef HAVE_CUDA
551 call messages_write(' Device type : GPU', new_line = .true.)
552#ifdef __HIP_PLATFORM_AMD__
553 call messages_write(' Device vendor : AMD Corporation', new_line = .true.)
554#else
555 call messages_write(' Device vendor : NVIDIA Corporation', new_line = .true.)
556#endif
557#endif
558
559#ifdef HAVE_CUDA
560 cval_str = c_null_char
561 call cuda_device_name(accel%device%cuda_device, cval_str)
562 call string_c_to_f(cval_str, val_str)
563#endif
564 call messages_write(' Device name : '//trim(val_str))
565 call messages_new_line()
566
567#ifdef HAVE_CUDA
568 call cuda_device_capability(accel%device%cuda_device, major, minor)
569#endif
570 call messages_write(' Cuda capabilities :')
571 call messages_write(major, fmt = '(i2)')
572 call messages_write('.')
573 call messages_write(minor, fmt = '(i1)')
574 call messages_new_line()
575
576 ! VERSION
577#ifdef HAVE_CUDA
578 call cuda_driver_version(version)
579 call messages_write(' Driver version : ')
580 call messages_write(version)
581#endif
582 call messages_new_line()
583
584
585 call messages_write(' Device memory :')
586 call messages_write(accel%global_memory_size, units=unit_megabytes)
587 call messages_new_line()
588
589 call messages_write(' Shared memory :')
590 call messages_write(accel%shared_memory_size, units=unit_kilobytes)
591 call messages_new_line()
592
593 call messages_write(' Max. block size :')
594 call messages_write(accel%max_block_size)
595 call messages_new_line()
596
597 call messages_info()
598
599 pop_sub(accel_init.device_info)
600 end subroutine device_info
601
602 end subroutine accel_init
603
604 ! ------------------------------------------
605 subroutine accel_end(namespace)
606 type(namespace_t), intent(in) :: namespace
607
608 integer(int64) :: hits, misses
609 real(real64) :: volume_hits, volume_misses
610 logical :: found
611 type(accel_mem_t) :: tmp
612
613 push_sub(accel_end)
614
615 if (accel_is_enabled()) then
616
617 ! Release global buffers
618
619 do
620 call alloc_cache_get(memcache, alloc_cache_any_size, found, tmp%mem)
621 if (.not. found) exit
622
623#ifdef HAVE_CUDA
624 call cuda_mem_free(tmp%mem)
625#endif
626 end do
627
628 call alloc_cache_end(memcache, hits, misses, volume_hits, volume_misses)
629
630 call messages_print_with_emphasis(msg="Acceleration-device allocation cache", namespace=namespace)
631
632 call messages_new_line()
633 call messages_write(' Number of allocations =')
634 call messages_write(hits + misses, new_line = .true.)
635 call messages_write(' Volume of allocations =')
636 call messages_write(volume_hits + volume_misses, fmt = 'f18.1', units = unit_gigabytes, align_left = .true., &
637 new_line = .true.)
638 call messages_write(' Hit ratio =')
639 if (hits + misses > 0) then
640 call messages_write(hits/real(hits + misses, real64)*100, fmt='(f6.1)', align_left = .true.)
641 else
642 call messages_write(m_zero, fmt='(f6.1)', align_left = .true.)
643 end if
644 call messages_write('%', new_line = .true.)
645 call messages_write(' Volume hit ratio =')
646 if (volume_hits + volume_misses > 0) then
647 call messages_write(volume_hits/(volume_hits + volume_misses)*100, fmt='(f6.1)', align_left = .true.)
648 else
649 call messages_write(m_zero, fmt='(f6.1)', align_left = .true.)
650 end if
651 call messages_write('%')
652 call messages_new_line()
653 call messages_info()
654
655 call messages_print_with_emphasis(namespace=namespace)
656 end if
657
659
660 if (accel_is_enabled()) then
661#ifdef HAVE_CUDA
662 call cublas_end()
663 if (.not. accel%cuda_mpi) then ! CUDA aware MPI finalize will do the cleanup
664 call cuda_end(accel%context%cuda_context, accel%device%cuda_device)
665 end if
666#endif
667
668 if (buffer_alloc_count /= 0) then
669 call messages_write('Accel:')
670 call messages_write(real(allocated_mem, real64) , fmt = 'f12.1', units = unit_megabytes, align_left = .true.)
671 call messages_write(' in ')
673 call messages_write(' buffers were not deallocated.')
674 call messages_fatal()
675 end if
676
677 end if
678
679 pop_sub(accel_end)
680 end subroutine accel_end
681
682 ! ------------------------------------------
683
685 subroutine accel_grid_size_array_i8(n, blocksizes, gridsizes)
686 integer(int64), intent(in) :: n(:)
687 integer(int64), intent(in) :: blocksizes(:)
688 integer(int64), intent(out) :: gridsizes(:)
689
690 integer :: dim, i
691
692 dim = ubound(n, dim=1)
693 assert(dim == ubound(blocksizes, dim=1))
694 assert(dim == ubound(gridsizes, dim=1))
695
696 do i = 1, dim
697 gridsizes(i) = (n(i) + blocksizes(i) - 1_int64) / blocksizes(i)
698 gridsizes(i) = min(gridsizes(i), accel%max_grid_dim(i))
699 end do
700 end subroutine accel_grid_size_array_i8
701
702 ! ------------------------------------------
703
705 subroutine accel_grid_size_array_i4(n, blocksizes, gridsizes)
706 integer, intent(in) :: n(:)
707 integer, intent(in) :: blocksizes(:)
708 integer, intent(out) :: gridsizes(:)
709
710 integer(int64) :: gridsizes64(size(gridsizes))
711
712 call accel_grid_size_array_i8(int(n(:), int64), int(blocksizes(:), int64), gridsizes64)
713
714 gridsizes = int(gridsizes64, int32)
715 end subroutine accel_grid_size_array_i4
716
717 ! ------------------------------------------
718
720 subroutine accel_grid_size_i8(n, blocksizes, gridsizes)
721 integer(int64), intent(in) :: n
722 integer(int64), intent(in) :: blocksizes
723 integer(int64), intent(out) :: gridsizes
724
725 integer(int64) :: temp(1)
727 call accel_grid_size_array_i8( (/n/), (/blocksizes/), temp)
728
729 gridsizes = temp(1)
730 end subroutine accel_grid_size_i8
731
732 ! ------------------------------------------
733
735 subroutine accel_grid_size_i4(n, blocksizes, gridsizes)
736 integer, intent(in) :: n
737 integer, intent(in) :: blocksizes
738 integer, intent(out) :: gridsizes
739
740 integer(int64) :: temp(1)
741
742 call accel_grid_size_array_i8(int((/n/), int64), int((/blocksizes/), int64), temp)
743
744 gridsizes = int(temp(1), int32)
745 end subroutine accel_grid_size_i4
747! ------------------------------------------
748
752 subroutine accel_grid_size_extend_dim_i8(n, pack_size, gridsizes, blocksizes, kernel)
753 integer(int64), intent(in) :: n
754 integer(int64), intent(in) :: pack_size
755 integer(int64), dimension(3), intent(out) :: gridsizes
756 integer(int64), dimension(3), intent(out) :: blocksizes
757 type(accel_kernel_t), optional, intent(inout) :: kernel
758
759 integer(int64) :: bsize, dim2, dim3
760 integer(int64), dimension(3) :: nn
762 if(present(kernel)) then
763 bsize = accel_kernel_block_size(kernel)/pack_size
764 else
765 bsize = accel_max_block_size()/pack_size
766 end if
767
768 dim3 = n/(accel_max_size_per_dim(2)*bsize) + 1
769 dim2 = min(accel_max_size_per_dim(2)*bsize, pad(n, bsize))
770
771 nn = (/pack_size, dim2, dim3/)
772 blocksizes = (/pack_size, bsize, 1_int64/)
773
774 call accel_grid_size(nn, blocksizes, gridsizes)
775 end subroutine accel_grid_size_extend_dim_i8
777 ! ------------------------------------------
778
782 subroutine accel_grid_size_extend_dim_i4(n, pack_size, gridsizes, blocksizes, kernel)
783 integer, intent(in) :: n
784 integer, intent(in) :: pack_size
785 integer, dimension(3), intent(out) :: gridsizes
786 integer, dimension(3), intent(out) :: blocksizes
787 type(accel_kernel_t), optional, intent(inout) :: kernel
788
789 integer(int64) :: gridsizes64(3), blocksizes64(3)
790
791 call accel_grid_size_extend_dim_i8(int(n, int64), int(pack_size, int64), &
792 gridsizes64, blocksizes64, kernel=kernel)
794 gridsizes = int(gridsizes64, int32)
795 blocksizes = int(blocksizes64, int32)
796 end subroutine accel_grid_size_extend_dim_i4
797
798 ! ------------------------------------------
799
800 integer(int64) function accel_padded_size_i8(nn) result(psize)
801 integer(int64), intent(in) :: nn
802
803 integer(int64) :: modnn, bsize
804
805 psize = nn
806
807 if (accel_is_enabled()) then
808
809 bsize = accel_max_block_size()
810
811 psize = nn
812 modnn = mod(nn, bsize)
813 if (modnn /= 0) psize = psize + bsize - modnn
814
815 end if
816
817 end function accel_padded_size_i8
818
819 ! ------------------------------------------
820
821 integer(int32) function accel_padded_size_i4(nn) result(psize)
822 integer(int32), intent(in) :: nn
824 psize = int(accel_padded_size_i8(int(nn, int64)), int32)
825
826 end function accel_padded_size_i4
827
828 ! ------------------------------------------
829
830 subroutine accel_create_buffer_4(this, flags, type, size, set_zero, async)
831 type(accel_mem_t), intent(inout) :: this
832 integer, intent(in) :: flags
833 type(type_t), intent(in) :: type
834 integer, intent(in) :: size
835 logical, optional, intent(in) :: set_zero
836 logical, optional, intent(in) :: async
837
838 call accel_create_buffer_8(this, flags, type, int(size, int64), set_zero, async)
839 end subroutine accel_create_buffer_4
840
841 ! ------------------------------------------
842
843 subroutine accel_create_buffer_8(this, flags, type, size, set_zero, async)
844 type(accel_mem_t), intent(inout) :: this
845 integer, intent(in) :: flags
846 type(type_t), intent(in) :: type
847 integer(int64), intent(in) :: size
848 logical, optional, intent(in) :: set_zero
849 logical, optional, intent(in) :: async
850
851 integer(int64) :: fsize
852 logical :: found
853 integer(int64) :: initialize_buffers
854
855 push_sub(accel_create_buffer_8)
856
857 this%type = type
858 this%size = size
859 this%flags = flags
860 fsize = int(size, int64)*types_get_size(type)
861 this%allocated = .true.
863 if (fsize > 0) then
864
865 call alloc_cache_get(memcache, fsize, found, this%mem)
866
867 if (.not. found) then
868#ifdef HAVE_CUDA
869 if(optional_default(async, .false.)) then
870 call cuda_mem_alloc_async(this%mem, fsize)
871 else
872 call cuda_mem_alloc(this%mem, fsize)
873 end if
874#endif
875 end if
876
879
880 end if
881
882 if (present(set_zero)) then
883 initialize_buffers = merge(option__initializegpubuffers__yes, option__initializegpubuffers__no, set_zero)
884 else
885 initialize_buffers = accel%initialize_buffers
886 end if
887 select case (initialize_buffers)
888 case (option__initializegpubuffers__yes)
889 call accel_set_buffer_to(this, type, int(z'00', int8), size, async=async)
890 case (option__initializegpubuffers__nan)
891 call accel_set_buffer_to(this, type, int(z'FF', int8), size, async=async)
892 end select
893
894 pop_sub(accel_create_buffer_8)
895 end subroutine accel_create_buffer_8
896
897 ! ------------------------------------------
898
899 subroutine accel_free_buffer(this, async)
900 type(accel_mem_t), intent(inout) :: this
901 logical, optional, intent(in) :: async
902
903 logical :: put
904 integer(int64) :: fsize
905
906 push_sub(accel_free_buffer)
907
908 if (this%size > 0) then
909
910 fsize = int(this%size, int64)*types_get_size(this%type)
911
912 call alloc_cache_put(memcache, fsize, this%mem, put)
913
914 if (.not. put) then
915#ifdef HAVE_CUDA
916 if (optional_default(async, .false.)) then
917 call cuda_mem_free_async(this%mem)
918 else
919 call cuda_mem_free(this%mem)
920 end if
921#endif
922 end if
923
926
927 end if
928
929 this%size = 0
930 this%flags = 0
931
932 this%allocated = .false.
933
934 pop_sub(accel_free_buffer)
935 end subroutine accel_free_buffer
936
937 ! ------------------------------------------
938
942 subroutine accel_move_buffer(buffer_from, buffer_to)
943 type(accel_mem_t), intent(inout) :: buffer_from
944 type(accel_mem_t), intent(inout) :: buffer_to
945
946 push_sub(accel_move_buffer)
947
948 ! Can not move an allocated buffer, the destination buffer should be empty
949 assert(.not. accel_buffer_is_allocated(buffer_to))
950
951 buffer_to%mem = buffer_from%mem
952 buffer_to%size = buffer_from%size
953 buffer_to%type = buffer_from%type
954 buffer_to%flags = buffer_from%flags
955 buffer_to%allocated = buffer_from%allocated
956
957 call accel_detach_buffer(buffer_from)
958
959 pop_sub(accel_move_buffer)
960 end subroutine accel_move_buffer
961
962 ! ------------------------------------------
963
968 subroutine accel_detach_buffer(this)
969 type(accel_mem_t), intent(inout) :: this
970
971 push_sub(accel_detach_buffer)
972
973 this%mem = c_null_ptr
974 this%size = 0
975 this%type = type_none
976 this%flags = 0
977 this%allocated = .false.
978
979 pop_sub(accel_detach_buffer)
980 end subroutine accel_detach_buffer
981
982 ! ------------------------------------------------------
984 ! Check if the temporary buffers are the right size, if not reallocate them
985 subroutine accel_ensure_buffer_size(buffer, flags, type, required_size, set_zero, async)
986 type(accel_mem_t), intent(inout) :: buffer
987 integer, intent(in) :: flags
988 type(type_t), intent(in) :: type
989 integer, intent(in) :: required_size
990 logical, intent(in) :: set_zero
991 logical, optional, intent(in) :: async
992
994
995
996 if (accel_buffer_is_allocated(buffer) .and. buffer%size < required_size) then
997 call accel_free_buffer(buffer, async=optional_default(async, .false.))
998 end if
999
1000 if (.not. accel_buffer_is_allocated(buffer)) then
1001 call accel_create_buffer(buffer, flags, type, required_size, set_zero=set_zero, async=optional_default(async, .false.))
1002 end if
1003
1005 end subroutine accel_ensure_buffer_size
1006
1007 ! ------------------------------------------
1008
1009 logical pure function accel_buffer_is_allocated(this) result(allocated)
1010 type(accel_mem_t), intent(in) :: this
1011
1012 allocated = this%allocated
1013 end function accel_buffer_is_allocated
1014
1015 ! -----------------------------------------
1016
1017 subroutine accel_finish()
1018 ! no push_sub, called too frequently
1019
1020 if (accel_is_enabled()) then
1021#ifdef HAVE_CUDA
1023#endif
1024 end if
1025 end subroutine accel_finish
1027 ! ------------------------------------------
1028
1029 subroutine accel_set_kernel_arg_buffer(kernel, narg, buffer)
1030 type(accel_kernel_t), intent(inout) :: kernel
1031 integer, intent(in) :: narg
1032 type(accel_mem_t), intent(in) :: buffer
1033
1034 assert(accel_buffer_is_allocated(buffer))
1035
1036 ! no push_sub, called too frequently
1037#ifdef HAVE_CUDA
1038 call cuda_kernel_set_arg_buffer(kernel%arguments, buffer%mem, narg)
1039#endif
1040
1041 end subroutine accel_set_kernel_arg_buffer
1042
1043 ! ------------------------------------------
1044
1051 subroutine accel_kernel_run_8(kernel, gridsizes, blocksizes, shared_memory_size)
1052 type(accel_kernel_t), intent(inout) :: kernel
1053 integer(int64), intent(in) :: gridsizes(:)
1054 integer(int64), intent(in) :: blocksizes(:)
1055 integer(int64), optional, intent(in) :: shared_memory_size
1056
1057 integer :: dim
1058 integer(int64) :: gsizes(1:3)
1059 integer(int64) :: bsizes(1:3)
1060
1061 ! no push_sub, called too frequently
1062
1063 ! CUDA needs all dimensions
1064 gsizes = 1
1065 bsizes = 1
1066
1067 dim = ubound(gridsizes, dim=1)
1068
1069 assert(dim == ubound(blocksizes, dim=1))
1071 ! if one size is zero, there is nothing to do
1072 if (any(gridsizes == 0)) return
1073
1074 assert(all(blocksizes > 0))
1075
1076 gsizes(1:dim) = gridsizes(1:dim)
1077 bsizes(1:dim) = blocksizes(1:dim)
1078
1079#ifdef HAVE_CUDA
1080 ! Maximum dimension of a block
1081 if (any(bsizes(1:3) > accel%max_block_dim(1:3))) then
1082 message(1) = "Maximum dimension of a block too large in kernel "//trim(kernel%kernel_name)
1083 message(2) = "The following conditions should be fulfilled:"
1084 write(message(3), "(A, I8, A, I8)") "Dim 1: ", bsizes(1), " <= ", accel%max_block_dim(1)
1085 write(message(4), "(A, I8, A, I8)") "Dim 2: ", bsizes(2), " <= ", accel%max_block_dim(2)
1086 write(message(5), "(A, I8, A, I8)") "Dim 3: ", bsizes(3), " <= ", accel%max_block_dim(3)
1087 message(6) = "This is an internal error, please contact the developers."
1088 call messages_fatal(6)
1089 end if
1090
1091
1092 ! Maximum number of threads per block
1093 if (product(bsizes) > accel_max_block_size()) then
1094 message(1) = "Maximum number of threads per block too large in kernel "//trim(kernel%kernel_name)
1095 message(2) = "The following condition should be fulfilled:"
1096 write(message(3), "(I8, A, I8)") product(bsizes), " <= ", accel_max_block_size()
1097 message(4) = "This is an internal error, please contact the developers."
1098 call messages_fatal(4)
1099 end if
1100
1101 ! Maximum dimensions of the grid of thread block
1102 if (any(gsizes(1:3) > accel%max_grid_dim(1:3))) then
1103 message(1) = "Maximum dimension of grid too large in kernel "//trim(kernel%kernel_name)
1104 message(2) = "The following conditions should be fulfilled:"
1105 write(message(3), "(A, I8, A, I10)") "Dim 1: ", gsizes(1), " <= ", accel%max_grid_dim(1)
1106 write(message(4), "(A, I8, A, I10)") "Dim 2: ", gsizes(2), " <= ", accel%max_grid_dim(2)
1107 write(message(5), "(A, I8, A, I10)") "Dim 3: ", gsizes(3), " <= ", accel%max_grid_dim(3)
1108 message(6) = "This is an internal error, please contact the developers."
1109 call messages_fatal(6)
1110 end if
1111
1112 if(present(shared_memory_size)) then
1113
1114 if (shared_memory_size > accel%shared_memory_size) then
1115 message(1) = "Shared memory too large in kernel "//trim(kernel%kernel_name)
1116 message(2) = "The following condition should be fulfilled:"
1117 message(3) = "Requested shared memory <= Available shared memory"
1118 write(message(4), '(a,f12.6,a)') "Requested shared memory: ", real(shared_memory_size, real64) /1024.0, " Kb"
1119 write(message(5), '(a,f12.6,a)') "Available shared memory: ", real(accel%shared_memory_size, real64) /1024.0, " Kb"
1120 message(6) = "This is an internal error, please contact the developers."
1121 call messages_fatal(6)
1122 else if (shared_memory_size <= 0) then
1123 message(1) = "Invalid shared memory size in kernel "//trim(kernel%kernel_name)
1124 write(message(2), '(a,f12.6,a)') "Shared memory size requested: ", real(shared_memory_size, real64) /1024.0, " Kb"
1125 message(3) = "This is an internal error, please contact the developers."
1126 call messages_fatal(3)
1127 end if
1128 end if
1129
1130 call cuda_launch_kernel(kernel%cuda_kernel, gsizes(1), bsizes(1), &
1131 optional_default(shared_memory_size, 0_int64), kernel%arguments)
1132#endif
1133
1134 end subroutine accel_kernel_run_8
1135
1136 ! -----------------------------------------------
1137
1143
1144 subroutine accel_kernel_run_4(kernel, gridsizes, blocksizes, shared_memory_size)
1145 type(accel_kernel_t), intent(inout) :: kernel
1146 integer, intent(in) :: gridsizes(:)
1147 integer, intent(in) :: blocksizes(:)
1148 integer(int64), optional, intent(in) :: shared_memory_size
1149
1150 call accel_kernel_run_8(kernel, int(gridsizes, int64), int(blocksizes, int64), shared_memory_size)
1151
1152 end subroutine accel_kernel_run_4
1153
1154 ! -----------------------------------------------
1155
1156 integer pure function accel_max_block_size() result(max_block_size)
1157 max_block_size = accel%max_block_size
1158 end function accel_max_block_size
1159
1160 ! -----------------------------------------------
1161
1162 integer function accel_kernel_block_size(kernel) result(block_size)
1163 type(accel_kernel_t), intent(inout) :: kernel
1164
1165#ifdef HAVE_CUDA
1166 integer :: max_block_size
1167#endif
1168
1169 block_size = 0
1170
1171#ifdef HAVE_CUDA
1172 call cuda_kernel_max_threads_per_block(kernel%cuda_kernel, max_block_size)
1173 if (debug%info .and. max_block_size /= accel%max_block_size) then
1174 write(message(1), "(A, I5, A)") "A kernel can use only less threads per block (", max_block_size, ")", &
1175 "than available on the device (", accel%max_block_size, ")"
1176 call messages_info(1)
1177 end if
1178
1179 ! recommended number of threads per block is 256 according to the CUDA best practice guide
1180 ! see https://docs.nvidia.com/cuda/cuda-c-best-practices-guide/index.html#thread-and-block-heuristics
1181 block_size = 256
1182
1183 ! make sure we do not use more threads per block than available for this kernel
1184 block_size = min(block_size, max_block_size)
1185#endif
1186
1187 end function accel_kernel_block_size
1188
1189 ! ----------------------------------------------------
1190
1192 subroutine accel_copy_buffer(dest, src, type, nval, offset_dest, offset_src, async)
1193 type(accel_mem_t), intent(inout) :: dest
1194 type(accel_mem_t), intent(in) :: src
1195 type(type_t), intent(in) :: type
1196 integer(int64), intent(in) :: nval
1197 integer(int64), optional, intent(in) :: offset_dest
1198 integer(int64), optional, intent(in) :: offset_src
1199 logical, optional, intent(in) :: async
1200
1201 integer(int64) :: type_size, offset_dest_, offset_src_
1202
1204 call profiling_in("ACCEL_COPY_BUFFER")
1205
1206 if (nval == 0) then
1207 call profiling_out("ACCEL_COPY_BUFFER")
1208 pop_sub(accel_copy_buffer)
1209 return
1210 end if
1211 assert(nval > 0)
1212
1213 type_size = types_get_size(type)
1214
1215 offset_dest_ = 0_int64
1216 if (present(offset_dest)) offset_dest_ = offset_dest*type_size
1217 offset_src_ = 0_int64
1218 if (present(offset_src)) offset_src_ = offset_src*type_size
1219
1220 assert(offset_dest_ + nval*type_size <= int(dest%size, int64)*types_get_size(dest%type))
1221 assert(offset_src_ + nval*type_size <= int(src%size, int64)*types_get_size(src%type))
1222
1223 call cuda_memcpy_dtod(dest%mem, src%mem, nval*type_size, offset_dest_, offset_src_)
1224
1225 if (.not. optional_default(async, .false.)) call accel_finish()
1226
1227 call profiling_out("ACCEL_COPY_BUFFER")
1228 pop_sub(accel_copy_buffer)
1229 end subroutine accel_copy_buffer
1230
1231 ! ----------------------------------------------------
1232
1233 subroutine accel_set_buffer_to(buffer, type, val, nval, offset, async)
1234 type(accel_mem_t), intent(inout) :: buffer
1235 type(type_t), intent(in) :: type
1236 integer(int8), intent(in) :: val
1237 integer(int64), intent(in) :: nval
1238 integer(int64), optional, intent(in) :: offset
1239 logical, optional, intent(in) :: async
1240
1241 integer(int64) :: nval_, offset_, type_size
1242
1243 push_sub(accel_set_buffer_to)
1245 if (nval == 0) then
1246 pop_sub(accel_set_buffer_to)
1247 return
1248 end if
1249 assert(nval > 0)
1250
1251 if (present(offset)) then
1252 assert(offset >= 0)
1253 if(offset > buffer%size) then
1254 pop_sub(accel_set_buffer_to)
1255 return
1256 end if
1257 end if
1258
1259 type_size = types_get_size(type)
1261 nval_ = nval*type_size
1262
1263 offset_ = 0_int64
1264 if (present(offset)) offset_ = offset*type_size
1265
1266 call cuda_mem_set_async(buffer%mem, val, nval_, offset_)
1267 if(.not. optional_default(async, .false.)) call accel_finish()
1268
1269 pop_sub(accel_set_buffer_to)
1270 end subroutine accel_set_buffer_to
1271
1272 ! ----------------------------------------------------
1273
1274 subroutine accel_set_buffer_to_zero_i8(buffer, type, nval, offset, async)
1275 type(accel_mem_t), intent(inout) :: buffer
1276 type(type_t), intent(in) :: type
1277 integer(int64), intent(in) :: nval
1278 integer(int64), optional, intent(in) :: offset
1279 logical, optional, intent(in) :: async
1282
1283 call accel_set_buffer_to(buffer, type, int(z'00', int8), nval, offset, async)
1284
1286 end subroutine accel_set_buffer_to_zero_i8
1287
1288 ! ----------------------------------------------------
1289
1290 subroutine accel_set_buffer_to_zero_i4(buffer, type, nval, offset, async)
1291 type(accel_mem_t), intent(inout) :: buffer
1292 type(type_t), intent(in) :: type
1293 integer(int32), intent(in) :: nval
1294 integer(int32), optional, intent(in) :: offset
1295 logical, optional, intent(in) :: async
1296
1298
1299 if (present(offset)) then
1300 call accel_set_buffer_to_zero_i8(buffer, type, int(nval, int64), int(offset, int64), async=async)
1301 else
1302 call accel_set_buffer_to_zero_i8(buffer, type, int(nval, int64), async=async)
1303 end if
1304
1306 end subroutine accel_set_buffer_to_zero_i4
1307
1308 ! ----------------------------------------------------
1309
1310 subroutine accel_check_bandwidth()
1311 integer :: itime
1312 integer, parameter :: times = 10
1313 integer :: size
1314 real(real64) :: time, stime
1315 real(real64) :: read_bw, write_bw
1316 type(accel_mem_t) :: buff
1317 real(real64), allocatable :: data(:)
1318
1319 call messages_new_line()
1320 call messages_write('Info: Benchmarking the bandwidth between main memory and device memory')
1321 call messages_new_line()
1322 call messages_info()
1323
1324 call messages_write(' Buffer size Read bw Write bw')
1325 call messages_new_line()
1326 call messages_write(' [MiB] [MiB/s] [MiB/s]')
1327 call messages_info()
1328
1329 size = 15000
1330 do
1331 safe_allocate(data(1:size))
1332 call accel_create_buffer(buff, accel_mem_read_write, type_float, size)
1333
1334 stime = loct_clock()
1335 do itime = 1, times
1336 call accel_write_buffer(buff, size, data)
1337 call accel_finish()
1338 end do
1339 time = (loct_clock() - stime)/real(times, real64)
1340
1341 write_bw = real(size, real64) *8.0_real64/time
1342
1343 stime = loct_clock()
1344 do itime = 1, times
1345 call accel_read_buffer(buff, size, data)
1346 end do
1347 call accel_finish()
1348
1349 time = (loct_clock() - stime)/real(times, real64)
1350 read_bw = real(size, real64) *8.0_real64/time
1351
1352 call messages_write(size*8.0_real64/1024.0_real64**2)
1353 call messages_write(write_bw/1024.0_real64**2, fmt = '(f10.1)')
1354 call messages_write(read_bw/1024.0_real64**2, fmt = '(f10.1)')
1355 call messages_info()
1356
1357 call accel_free_buffer(buff)
1358
1359 safe_deallocate_a(data)
1361 size = int(size*2.0)
1362
1363 if (size > 50000000) exit
1364 end do
1365 end subroutine accel_check_bandwidth
1366
1367 !------------------------------------------------------------
1368
1369 subroutine accel_kernel_global_init()
1370
1371 push_sub(accel_kernel_global_init)
1372
1373 nullify(head)
1374
1375 call cuda_program_map_init(accel%program_map)
1376
1377 call accel_kernel_list()
1378
1380 end subroutine accel_kernel_global_init
1381
1382 !------------------------------------------------------------
1383
1390 subroutine accel_kernel_list()
1391
1392 push_sub(accel_kernel_list)
1393
1394 call accel_program_add('axpy.cu', 'axpy<double>')
1395 call accel_program_add('axpy.cu', 'axpy<complex<double>>')
1396 call accel_program_add('axpy.cu', 'axpby<double>')
1397 call accel_program_add('axpy.cu', 'axpby<complex<double>>')
1398 call accel_program_add('axpy.cu', 'scal2v<double>')
1399 call accel_program_add('axpy.cu', 'scal2v<complex<double>, Conjugation::No>')
1400 call accel_program_add('axpy.cu', 'scal2v<complex<double>, Conjugation::Yes>')
1401 call accel_program_add('axpy.cu', 'axpy_vec<double>')
1402 call accel_program_add('axpy.cu', 'axpy_vec<complex<double>>')
1403 call accel_program_add('axpy.cu', 'scal_vec<double>')
1404 call accel_program_add('axpy.cu', 'scal_vec<complex<double>>')
1405 call accel_program_add('axpy.cu', 'xpay_vec<double>')
1406 call accel_program_add('axpy.cu', 'xpay_vec<complex<double>>')
1407 call accel_program_add('axpy.cu', &
1408 'batch_axpy_function<double, DimSpin::D1>')
1409 call accel_program_add('axpy.cu', &
1410 'batch_axpy_function<double, DimSpin::D2>')
1411 call accel_program_add('axpy.cu', &
1412 'batch_axpy_function<complex<double>, DimSpin::D1>')
1413 call accel_program_add('axpy.cu', &
1414 'batch_axpy_function<complex<double>, DimSpin::D2>')
1415 call accel_program_add('axpy.cu', &
1416 'batch_ax_function_py<double, DimSpin::D1>')
1417 call accel_program_add('axpy.cu', &
1418 'batch_ax_function_py<double, DimSpin::D2>')
1419 call accel_program_add('axpy.cu', &
1420 'batch_ax_function_py<complex<double>, DimSpin::D1>')
1421 call accel_program_add('axpy.cu', &
1422 'batch_ax_function_py<complex<double>, DimSpin::D2>')
1423
1424 call accel_program_add('batch_mul.cu', 'mul_batch<double>')
1425 call accel_program_add('batch_mul.cu', 'mul_mf<double, double>')
1426 call accel_program_add('batch_mul.cu', 'mul_batch<complex<double>, Conjugation::No>')
1427 call accel_program_add('batch_mul.cu', 'mul_batch<complex<double>, Conjugation::Yes>')
1428 call accel_program_add('batch_mul.cu', 'mul_mf<complex<double>, double, Conjugation::No>')
1429 call accel_program_add('batch_mul.cu', 'mul_mf<complex<double>, double, Conjugation::Yes>')
1430 call accel_program_add('batch_mul.cu', 'mul_mf<complex<double>, complex<double>, Conjugation::No>')
1431 call accel_program_add('batch_mul.cu', 'mul_mf<complex<double>, complex<double>, Conjugation::Yes>')
1432
1433 call accel_program_add('boundaries.cu', 'boundaries_periodic<double>')
1434 call accel_program_add('boundaries.cu', 'boundaries_periodic_corr<double>')
1435 call accel_program_add('boundaries.cu', 'boundaries_periodic_recv<double>')
1436 call accel_program_add('boundaries.cu', 'boundaries_periodic_recv_corr<double>')
1437 call accel_program_add('boundaries.cu', 'boundaries_periodic_send<double>')
1438
1439 call accel_program_add('copy.cu', 'add_with_map<double>')
1440 call accel_program_add('copy.cu', 'copy<double>')
1441 call accel_program_add('copy.cu', 'copy_complex_to_real<double>')
1442 call accel_program_add('copy.cu', 'copy_real_to_complex<double>')
1443 call accel_program_add('copy.cu', 'copy_with_map<double>')
1444
1445 call accel_program_add('curl.cu', 'curl<double>')
1446 call accel_program_add('curl.cu', 'curl<complex<double>>')
1447
1448 call accel_program_add('density.cu', 'density<double, double>')
1449 call accel_program_add('density.cu', 'density<double, complex<double>>')
1450 call accel_program_add('density.cu', 'current_accumulate<double>')
1451 call accel_program_add('density.cu', 'density_spinors<double>')
1452
1453 call accel_program_add('dftu_projector.cu', &
1454 'dftu_pos_mat_elem<double, double, Indexing::Indirect>')
1455 call accel_program_add('dftu_projector.cu', &
1456 'dftu_pos_mat_elem<double, complex<double>, Indexing::Indirect>')
1457 call accel_program_add('dftu_projector.cu', &
1458 'dftu_pos_mat_elem<double, complex<double>, Indexing::Direct>')
1459 call accel_program_add('dftu_projector.cu', 'dftu_pos_mat_elem_phase<double>')
1460 call accel_program_add('dftu_projector.cu', &
1461 'dftu_pos_mat_elem<double, double, Indexing::Direct>')
1462 call accel_program_add('dftu_projector.cu', &
1463 'dftu_projector_bra<double>')
1464 call accel_program_add('dftu_projector.cu', &
1465 'dftu_projector_bra<complex<double>>')
1466 call accel_program_add('dftu_projector.cu', &
1467 'dftu_projector_bra_submesh<complex<double>>')
1468 call accel_program_add('dftu_projector.cu', &
1469 'dftu_projector_bra_submesh<double>')
1470 call accel_program_add('dftu_projector.cu', &
1471 'dftu_projector_ket<double>')
1472 call accel_program_add('dftu_projector.cu', &
1473 'dftu_projector_ket<complex<double>>')
1474 call accel_program_add('dftu_projector.cu', &
1475 'dftu_projector_ket_submesh<complex<double>>')
1476 call accel_program_add('dftu_projector.cu', &
1477 'dftu_projector_ket_submesh<double>')
1478
1479 call accel_program_add('exchange_local.cu', &
1480 'exchange_accumulate_batch<double, double, DimSpin::D1>')
1481 call accel_program_add('exchange_local.cu', &
1482 'exchange_accumulate_return_batch<double, double, DimSpin::D1>')
1483 call accel_program_add('exchange_local.cu', &
1484 'exchange_codensity_batch<double, DimSpin::D1>')
1485 call accel_program_add('exchange_local.cu', &
1486 'exchange_accumulate_batch<double, double, DimSpin::D2>')
1487 call accel_program_add('exchange_local.cu', &
1488 'exchange_accumulate_return_batch<double, double, DimSpin::D2>')
1489 call accel_program_add('exchange_local.cu', &
1490 'exchange_codensity_batch<double, DimSpin::D2>')
1491 call accel_program_add('exchange_local.cu', &
1492 'exchange_accumulate_batch<double, complex<double>, DimSpin::D1>')
1493 call accel_program_add('exchange_local.cu', &
1494 'exchange_accumulate_return_batch<double, complex<double>, DimSpin::D1>')
1495 call accel_program_add('exchange_local.cu', &
1496 'exchange_codensity_batch<complex<double>, DimSpin::D1>')
1497 call accel_program_add('exchange_local.cu', &
1498 'exchange_accumulate_batch<double, complex<double>, DimSpin::D2>')
1499 call accel_program_add('exchange_local.cu', &
1500 'exchange_accumulate_return_batch<double, complex<double>, DimSpin::D2>')
1501 call accel_program_add('exchange_local.cu', &
1502 'exchange_codensity_batch<complex<double>, DimSpin::D2>')
1503
1504 call accel_program_add('forces.cu', 'density_gradient<double, double>')
1505 call accel_program_add('forces.cu', 'density_gradient<double, complex<double>>')
1506
1507 call accel_program_add('get_points.cu', 'get_selected_points<double>')
1508
1509 call accel_program_add('ghost.cu', 'ghost_reorder<double>')
1510
1511 call accel_program_add('mesh_batch.cu', 'zdot_matrix_spinors<double>')
1512
1513 call accel_program_add('mesh_batch_single.cu', 'batch_dotpv_partial<double>')
1514 call accel_program_add('mesh_batch_single.cu', &
1515 'batch_dotpv_reduce<double, double, DimSpin::D1>')
1516 call accel_program_add('mesh_batch_single.cu', &
1517 'batch_dotpv_reduce<double, double, DimSpin::D2>')
1518 call accel_program_add('mesh_batch_single.cu', &
1519 'batch_mf_dotp<double, DimSpin::D1>')
1520 call accel_program_add('mesh_batch_single.cu', &
1521 'batch_mf_dotp<double, DimSpin::D2>')
1522 call accel_program_add('mesh_batch_single.cu', 'batch_dotpv_partial<complex<double>>')
1523 call accel_program_add('mesh_batch_single.cu', &
1524 'batch_dotpv_reduce<double, complex<double>, DimSpin::D1>')
1525 call accel_program_add('mesh_batch_single.cu', &
1526 'batch_dotpv_reduce<double, complex<double>, DimSpin::D2>')
1527 call accel_program_add('mesh_batch_single.cu', &
1528 'batch_mf_dotp<complex<double>, DimSpin::D1>')
1529 call accel_program_add('mesh_batch_single.cu', &
1530 'batch_mf_dotp<complex<double>, DimSpin::D2>')
1531
1532 call accel_program_add('mesh_interpolate.cu', &
1533 'mesh_interpolate<double, double, Dim::D1>')
1534 call accel_program_add('mesh_interpolate.cu', &
1535 'mesh_interpolate<double, double, Dim::D2>')
1536 call accel_program_add('mesh_interpolate.cu', &
1537 'mesh_interpolate<double, double, Dim::D3>')
1538 call accel_program_add('mesh_interpolate.cu', &
1539 'mesh_interpolate<double, complex<double>, Dim::D1>')
1540 call accel_program_add('mesh_interpolate.cu', &
1541 'mesh_interpolate<double, complex<double>, Dim::D2>')
1542 call accel_program_add('mesh_interpolate.cu', &
1543 'mesh_interpolate<double, complex<double>, Dim::D3>')
1544
1545 call accel_program_add('mesh_to_cube.cu', 'cube_to_mesh_batch<double>')
1546 call accel_program_add('mesh_to_cube.cu', 'mesh_to_cube_batch<double>')
1547 call accel_program_add('mesh_to_cube.cu', 'cube_to_mesh_batch<complex<double>>')
1548 call accel_program_add('mesh_to_cube.cu', 'mesh_to_cube_batch<complex<double>>')
1549 call accel_program_add('mesh_to_cube.cu', 'submesh_to_cube<double>')
1550 call accel_program_add('mesh_to_cube.cu', 'cube_to_submesh<double>')
1551 call accel_program_add('mesh_to_cube.cu', 'submesh_to_cube<complex<double>>')
1552 call accel_program_add('mesh_to_cube.cu', 'cube_to_submesh<complex<double>>')
1553
1554 call accel_program_add('mul.cu', 'zmul_batch<double, double>')
1555 call accel_program_add('mul.cu', 'zmul_batch<double, complex<double>>')
1556
1557 call accel_program_add('operate.cu', 'operate<double>')
1558 call accel_program_add('operate.cu', 'operate_map<double, Indexing::Direct>')
1559 call accel_program_add('operate.cu', 'operate_map<double, Indexing::Indirect>')
1560 call accel_program_add('operate.cu', 'operate_map<double, Indexing::Direct, Symmetry::Antisymmetric>')
1561 call accel_program_add('operate.cu', 'operate_map<double, Indexing::Direct, Symmetry::Symmetric>')
1562 call accel_program_add('operate.cu', 'operate_map<double, Indexing::Indirect, Symmetry::Antisymmetric>')
1563 call accel_program_add('operate.cu', 'operate_map<double, Indexing::Indirect, Symmetry::Symmetric>')
1564
1565 call accel_program_add('pack.cu', 'pack<double>')
1566 call accel_program_add('pack.cu', 'unpack<double>')
1567 call accel_program_add('pack.cu', 'pack<complex<double>>')
1568 call accel_program_add('pack.cu', 'unpack<complex<double>>')
1569
1570 call accel_program_add('pes.cu', 'zpes_flux_sph_integrate<double>')
1571 call accel_program_add('pes.cu', 'zpes_flux_sph_integxx<double>')
1572 call accel_program_add('pes.cu', 'zpes_flux_sph_integxx_2<double>')
1573
1574 call accel_program_add('phase.cu', 'phase<double>')
1575 call accel_program_add('phase.cu', 'phase_hamiltonian<double>')
1576 call accel_program_add('phase.cu', 'update_phases<double, Dim::D1>')
1577 call accel_program_add('phase.cu', 'update_phases<double, Dim::D2>')
1578 call accel_program_add('phase.cu', 'update_phases<double, Dim::D3>')
1579
1580 call accel_program_add('phase_spiral.cu', 'phase_spiral_apply<double>')
1581
1582 call accel_program_add('pml.cu', 'pml_apply<double>')
1583 call accel_program_add('pml.cu', 'pml_apply_new<double>')
1584 call accel_program_add('pml.cu', 'pml_copy<double>')
1585 call accel_program_add('pml.cu', 'pml_update_conv<double>')
1586 call accel_program_add('pml.cu', 'pml_update_new<double>')
1587
1588 call accel_program_add('points.cu', 'get_points<double>')
1589 call accel_program_add('points.cu', 'set_points<double>')
1590
1591 call accel_program_add('projector.cu', 'projector_bra_force<double, double>')
1592 call accel_program_add('projector.cu', 'projector_bra_force_phase<double, double>')
1593 call accel_program_add('projector.cu', 'projector_bra_gather<double>')
1594 call accel_program_add('projector.cu', 'projector_bra_scatter_real<double, double>')
1595 call accel_program_add('projector.cu', 'projector_ket<double>')
1596 call accel_program_add('projector.cu', 'projector_ket_phase<double, double>')
1597 call accel_program_add('projector.cu', 'projector_ket_phase_spiral<double, double>')
1598 call accel_program_add('projector.cu', 'dprojector_mix<double>')
1599 call accel_program_add('projector.cu', 'projector_r_vnl_bra<double, double>')
1600 call accel_program_add('projector.cu', 'projector_r_vnl_bra_phase<double, double>')
1601 call accel_program_add('projector.cu', 'projector_r_vnl_ket<double, double>')
1602 call accel_program_add('projector.cu', 'projector_r_vnl_ket_phase<double, double>')
1603 call accel_program_add('projector.cu', 'projector_bra_phase_gather<double>')
1604 call accel_program_add('projector.cu', 'projector_bra_phase_spiral_gather<double>')
1605 call accel_program_add('projector.cu', 'projector_bra_force<double, complex<double>>')
1606 call accel_program_add('projector.cu', 'projector_bra_force_phase<double, complex<double>>')
1607 call accel_program_add('projector.cu', 'projector_bra_gather<complex<double>>')
1608 call accel_program_add('projector.cu', 'projector_bra_scatter_complex<double, complex<double>>')
1609 call accel_program_add('projector.cu', 'projector_bra_scatter_real<double, complex<double>>')
1610 call accel_program_add('projector.cu', 'projector_ket<complex<double>>')
1611 call accel_program_add('projector.cu', 'projector_ket_phase<double, complex<double>>')
1612 call accel_program_add('projector.cu', 'projector_ket_phase_spiral<double, complex<double>>')
1613 call accel_program_add('projector.cu', 'zprojector_mix<double>')
1614 call accel_program_add('projector.cu', 'projector_r_vnl_bra<double, complex<double>>')
1615 call accel_program_add('projector.cu', 'projector_r_vnl_bra_phase<double, complex<double>>')
1616 call accel_program_add('projector.cu', 'projector_r_vnl_ket<double, complex<double>>')
1617 call accel_program_add('projector.cu', 'projector_r_vnl_ket_phase<double, complex<double>>')
1618
1619 call accel_program_add('projector_commutator.cu', 'projector_commutator_bra<double, double>')
1620 call accel_program_add('projector_commutator.cu', 'projector_commutator_bra_phase<double, double>')
1621 call accel_program_add('projector_commutator.cu', 'projector_commutator_ket<double, double>')
1622 call accel_program_add('projector_commutator.cu', 'projector_commutator_ket_phase<double, double>')
1623 call accel_program_add('projector_commutator.cu', 'dprojector_mix_commutator<double>')
1624 call accel_program_add('projector_commutator.cu', 'projector_commutator_bra<double, complex<double>>')
1625 call accel_program_add('projector_commutator.cu', 'projector_commutator_bra_phase<double, complex<double>>')
1626 call accel_program_add('projector_commutator.cu', 'projector_commutator_ket<double, complex<double>>')
1627 call accel_program_add('projector_commutator.cu', 'projector_commutator_ket_phase<double, complex<double>>')
1628 call accel_program_add('projector_commutator.cu', 'zprojector_mix_commutator<double>')
1629
1630 call accel_program_add('split.cu', 'merge_complex<double>')
1631 call accel_program_add('split.cu', 'split_complex<double>')
1632
1633 call accel_program_add('symmetrize_batch.cu', &
1634 'symmetrizer_apply_single_batch<double, Conjugation::No>')
1635 call accel_program_add('symmetrize_batch.cu', &
1636 'symmetrizer_apply_single_batch<double, Conjugation::Yes>')
1637 call accel_program_add('symmetrize_batch.cu', &
1638 'symmetrizer_apply_single_batch<complex<double>, Conjugation::No>')
1639 call accel_program_add('symmetrize_batch.cu', &
1640 'symmetrizer_apply_single_batch<complex<double>, Conjugation::Yes>')
1641
1642 call accel_program_add('uvw_to_xyz.cu', &
1643 'uvw_to_xyz<double, Dim::D1, double*, int, double*, int>')
1644 call accel_program_add('uvw_to_xyz.cu', &
1645 'uvw_to_xyz<double, Dim::D2, double*, int, double*, int, double*, int, double*, int>')
1646 call accel_program_add('uvw_to_xyz.cu', &
1647 'uvw_to_xyz<double, Dim::D3, double*, int, double*, int, double*, int, double*, int, double*, int, double*, int>')
1648
1649 call accel_program_add('vpsi.cu', 'vpsi<double>')
1650 call accel_program_add('vpsi.cu', 'vpsi_complex<double>')
1651 call accel_program_add('vpsi.cu', 'vpsi_spinors<double>')
1652 call accel_program_add('vpsi.cu', 'vpsi_spinors_complex<double>')
1653
1654 call accel_program_add('xc_dens_block.cu', 'xc_dens_apply_corrections<double>')
1655 call accel_program_add('xc_dens_block.cu', 'xc_dens_extract_block<double>')
1656
1657 pop_sub(accel_kernel_list)
1658 end subroutine accel_kernel_list
1659
1660 !------------------------------------------------------------
1661
1667 subroutine accel_program_add(file_name, name)
1668 character(len=*), intent(in) :: file_name
1669 character(len=*), intent(in) :: name
1670
1671 push_sub(accel_program_add)
1672
1673 call cuda_program_register(accel%program_map, string_f_to_c(trim(file_name)), &
1674 string_f_to_c(trim(name)))
1675
1676 pop_sub(accel_program_add)
1677 end subroutine accel_program_add
1678
1679 !------------------------------------------------------------
1680
1681 subroutine accel_kernel_global_end()
1682 type(accel_kernel_t), pointer :: next_head
1683
1684 push_sub(accel_kernel_global_end)
1685
1686 do
1687 if (.not. associated(head)) exit
1688 next_head => head%next
1690 head => next_head
1691 end do
1692
1693 if (accel_is_enabled()) then
1694 call cuda_program_map_end(accel%program_map)
1695 end if
1696
1698 end subroutine accel_kernel_global_end
1699
1700 !------------------------------------------------------------
1707 subroutine accel_kernel_build(this, file_name, kernel_name, flags)
1708 type(accel_kernel_t), intent(inout) :: this
1709 character(len=*), intent(in) :: file_name
1710 character(len=*), intent(in) :: kernel_name
1711 character(len=*), optional, intent(in) :: flags
1712
1713#ifdef HAVE_CUDA
1714 character(len=1000) :: all_flags
1715#endif
1716
1717 push_sub(accel_kernel_build)
1718
1719 call profiling_in("ACCEL_COMPILE", exclude = .true.)
1720
1721#ifdef HAVE_CUDA
1722 all_flags = '-I'//trim(conf%share)//'/kernels/'//" "//trim(accel%debug_flag)
1723
1724 if (present(flags)) then
1725 all_flags = trim(all_flags)//' '//trim(flags)
1726 end if
1727
1728 call cuda_program_build(accel%program_map, accel%device%cuda_device, &
1729 string_f_to_c(trim(file_name)), string_f_to_c(trim(all_flags)))
1730
1731 call cuda_program_get_kernel(this%cuda_kernel, accel%program_map, &
1732 string_f_to_c(trim(file_name)), string_f_to_c(trim(all_flags)), &
1733 string_f_to_c(trim(kernel_name)))
1734 call cuda_alloc_arg_array(this%arguments)
1735#endif
1736
1737 this%initialized = .true.
1738 this%kernel_name = trim(kernel_name)
1739
1740 call profiling_out("ACCEL_COMPILE")
1741
1742 pop_sub(accel_kernel_build)
1743 end subroutine accel_kernel_build
1744
1745 !------------------------------------------------------------
1747 subroutine accel_kernel_end(this)
1748 type(accel_kernel_t), intent(inout) :: this
1749
1750 push_sub(accel_kernel_end)
1751
1752#ifdef HAVE_CUDA
1753 call cuda_free_arg_array(this%arguments)
1754 call cuda_release_kernel(this%cuda_kernel)
1755 ! modules are not released here, since they are not associated to a kernel
1756#endif
1757
1758 this%initialized = .false.
1759
1760 pop_sub(accel_kernel_end)
1761 end subroutine accel_kernel_end
1762
1763 !------------------------------------------------------------
1764
1765 subroutine accel_kernel_start_call(this, file_name, kernel_name, flags)
1766 type(accel_kernel_t), target, intent(inout) :: this
1767 character(len=*), intent(in) :: file_name
1768 character(len=*), intent(in) :: kernel_name
1769 character(len=*), optional, intent(in) :: flags
1770
1771 push_sub(accel_kernel_start_call)
1772
1773 if (.not. this%initialized) then
1774 call accel_kernel_build(this, file_name, kernel_name, flags)
1775 this%next => head
1776 head => this
1777 end if
1778
1780 end subroutine accel_kernel_start_call
1781
1782 !--------------------------------------------------------------
1783
1784 integer(int64) pure function accel_global_memory_size() result(size)
1785
1786 size = accel%global_memory_size
1787
1788 end function accel_global_memory_size
1789
1790 !--------------------------------------------------------------
1791
1792 integer(int64) pure function accel_shared_memory_size() result(size)
1793
1794 size = accel%shared_memory_size
1795
1796 end function accel_shared_memory_size
1797 !--------------------------------------------------------------
1798
1799 integer pure function accel_max_size_per_dim(dim) result(size)
1800 integer, intent(in) :: dim
1801
1802 size = 0
1803#ifdef HAVE_CUDA
1804 size = 32768
1805 if (dim == 1) size = 2**30
1806#endif
1807 end function accel_max_size_per_dim
1808
1809 ! ------------------------------------------------------
1810
1811 subroutine accel_set_stream(stream_number)
1812 integer, intent(in) :: stream_number
1813
1814 push_sub(accel_set_stream)
1815
1816 if (accel_is_enabled()) then
1817#ifdef HAVE_CUDA
1818 call cuda_set_stream(accel%cuda_stream, stream_number)
1819 ! The stream number selects which of the per-stream BLAS handles the
1820 ! wrappers use; see cublas_init() in src/basic/cublas.cc.
1821 call cublas_set_stream(accel%cuda_stream, stream_number)
1822#endif
1823 end if
1824
1825 pop_sub(accel_set_stream)
1826 end subroutine accel_set_stream
1828 ! ------------------------------------------------------
1829
1830 subroutine accel_get_stream(stream_number)
1831 integer, intent(inout) :: stream_number
1832
1833 push_sub(accel_get_stream)
1834
1835 if (accel_is_enabled()) then
1836#ifdef HAVE_CUDA
1837 call cuda_get_stream(stream_number)
1838#endif
1839 end if
1840
1841 pop_sub(accel_get_stream)
1842 end subroutine accel_get_stream
1843
1844 ! ------------------------------------------------------
1845
1848
1849 if (accel_is_enabled()) then
1850#ifdef HAVE_CUDA
1851 call cuda_synchronize_all_streams()
1852#endif
1853 end if
1854
1856 end subroutine accel_synchronize_all_streams
1857
1858 function daccel_get_pointer_with_offset(buffer, offset) result(buffer_offset)
1859 type(c_ptr), intent(in) :: buffer
1860 integer(int64), intent(in) :: offset
1861 type(c_ptr) :: buffer_offset
1862
1864#ifdef HAVE_CUDA
1865 call cuda_get_pointer_with_offset(buffer, offset, buffer_offset)
1866#else
1867 ! this is needed to make the compiler happy for non-GPU compilations
1868 buffer_offset = buffer
1869#endif
1872
1873 function zaccel_get_pointer_with_offset(buffer, offset) result(buffer_offset)
1874 type(c_ptr), intent(in) :: buffer
1875 integer(int64), intent(in) :: offset
1876 type(c_ptr) :: buffer_offset
1877
1879#ifdef HAVE_CUDA
1880 call cuda_get_pointer_with_offset(buffer, 2_int64*offset, buffer_offset)
1881#else
1882 ! this is needed to make the compiler happy for non-GPU compilations
1883 buffer_offset = buffer
1884#endif
1887
1888 subroutine accel_clean_pointer(buffer)
1889 type(c_ptr), intent(in) :: buffer
1890
1891 push_sub(accel_clean_pointer)
1892#ifdef HAVE_CUDA
1893 call cuda_clean_pointer(buffer)
1894#endif
1895 pop_sub(accel_clean_pointer)
1896 end subroutine accel_clean_pointer
1897
1901 subroutine accel_get_unfolded_size(size, grid_size, thread_block_size)
1902 integer(int64), intent(in) :: size
1903 integer(int64), intent(out) :: grid_size
1904 integer(int64), intent(out) :: thread_block_size
1905
1906 push_sub(accel_get_unfolded_size)
1907#ifdef __HIP_PLATFORM_AMD__
1908 ! not benefitial for AMD chips
1909 grid_size = 1_int64
1910 thread_block_size = size
1911#else
1912 grid_size = size
1913 thread_block_size = accel%warp_size
1914#endif
1916 end subroutine accel_get_unfolded_size
1917
1918#include "undef.F90"
1919#include "real.F90"
1920#include "accel_inc.F90"
1921
1922#include "undef.F90"
1923#include "complex.F90"
1924#include "accel_inc.F90"
1925
1926#include "undef.F90"
1927#include "integer.F90"
1928#include "accel_inc.F90"
1929
1930#include "undef.F90"
1931#include "integer8.F90"
1932#include "accel_inc.F90"
1933
1934end module accel_oct_m
1935
1936!! Local Variables:
1937!! mode: f90
1938!! coding: utf-8
1939!! End:
subroutine device_info()
Definition: accel.F90:590
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:777
subroutine laccel_get_device_pointer_3l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:6035
subroutine zaccel_get_device_pointer_2l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:3914
subroutine, public accel_clean_pointer(buffer)
Definition: accel.F90:1843
subroutine accel_kernel_global_end()
Definition: accel.F90:1652
subroutine zaccel_write_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:3092
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:1856
subroutine laccel_read_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:5831
subroutine laccel_read_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:5590
subroutine iaccel_write_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:4109
pure logical function, public accel_allow_cpu_only()
Definition: accel.F90:382
subroutine daccel_get_device_pointer_1(host_pointer, device_pointer, dimensions)
Definition: accel.F90:2773
subroutine zaccel_read_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:3734
subroutine daccel_read_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:2495
subroutine zaccel_get_device_pointer_1(host_pointer, device_pointer, dimensions)
Definition: accel.F90:3821
subroutine laccel_read_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:5614
subroutine daccel_write_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:2253
subroutine laccel_write_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:5189
subroutine daccel_write_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:2225
subroutine laccel_get_device_pointer_1(host_pointer, device_pointer, dimensions)
Definition: accel.F90:5918
subroutine zaccel_read_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:3571
subroutine zaccel_read_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:3403
integer function, public accel_kernel_block_size(kernel)
Definition: accel.F90:1149
subroutine zaccel_write_buffer_single(this, data, async)
Definition: accel.F90:2989
subroutine daccel_read_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:2414
integer buffer_alloc_count
Definition: accel.F90:364
subroutine iaccel_get_device_pointer_3l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:4986
subroutine zaccel_read_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:3462
subroutine laccel_get_device_pointer_2(host_pointer, device_pointer, dimensions)
Definition: accel.F90:5942
subroutine iaccel_write_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:4321
subroutine zaccel_write_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:3367
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:727
subroutine laccel_write_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:5430
subroutine zaccel_read_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:3493
subroutine iaccel_write_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:4090
subroutine laccel_write_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:5267
subroutine, public accel_free_buffer(this, async)
Definition: accel.F90:941
subroutine daccel_write_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:2068
subroutine iaccel_write_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:4248
subroutine, public accel_kernel_start_call(this, file_name, kernel_name, flags)
Definition: accel.F90:1720
subroutine iaccel_write_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:4140
subroutine zaccel_write_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:3142
subroutine iaccel_read_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:4722
subroutine zaccel_write_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:3238
subroutine, public accel_get_stream(stream_number)
Definition: accel.F90:1785
subroutine accel_create_buffer_4(this, flags, type, size, set_zero, async)
Definition: accel.F90:872
subroutine zaccel_read_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:3620
subroutine iaccel_write_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:4218
integer(int64) pure function, public accel_global_memory_size()
Definition: accel.F90:1739
subroutine daccel_read_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:2469
subroutine laccel_write_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:5139
subroutine daccel_read_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:2395
subroutine daccel_write_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:2013
subroutine zaccel_set_kernel_arg_data(kernel, narg, data)
Definition: accel.F90:3805
subroutine daccel_get_device_pointer_3l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:2890
subroutine iaccel_read_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:4541
subroutine daccel_get_device_pointer_2l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:2866
integer(int64) function accel_padded_size_i8(nn)
Definition: accel.F90:842
subroutine accel_check_bandwidth()
Definition: accel.F90:1281
subroutine iaccel_write_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:4349
subroutine daccel_read_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:2720
subroutine laccel_read_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:5500
subroutine daccel_write_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:1954
subroutine zaccel_read_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:3601
subroutine iaccel_get_device_pointer_1l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:4937
subroutine, public accel_finish()
Definition: accel.F90:1059
subroutine laccel_write_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:5398
subroutine accel_kernel_global_init()
Definition: accel.F90:1340
subroutine zaccel_read_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:3674
integer(int64) allocated_mem
Definition: accel.F90:365
subroutine daccel_read_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:2523
subroutine accel_kernel_run_4(kernel, gridsizes, blocksizes, shared_memory_size)
Run a kernel with 4-byte integer sizes.
Definition: accel.F90:1131
subroutine zaccel_write_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:3042
subroutine iaccel_get_device_pointer_1(host_pointer, device_pointer, dimensions)
Definition: accel.F90:4869
subroutine laccel_read_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:5865
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:1163
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:824
subroutine, public accel_ensure_buffer_size(buffer, flags, type, required_size, set_zero, async)
Definition: accel.F90:1027
subroutine accel_set_buffer_to(buffer, type, val, nval, offset, async)
Definition: accel.F90:1204
subroutine, public accel_move_buffer(buffer_from, buffer_to)
Move the buffer memory from the first buffer to the second.
Definition: accel.F90:984
subroutine, public accel_detach_buffer(this)
Clear a buffer handle without freeing device memory.
Definition: accel.F90:1010
subroutine laccel_set_kernel_arg_data(kernel, narg, data)
Definition: accel.F90:5902
subroutine iaccel_write_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:4190
subroutine daccel_write_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:1994
subroutine daccel_read_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:2553
subroutine zaccel_read_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:3443
subroutine iaccel_write_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:4381
subroutine daccel_read_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:2445
subroutine laccel_write_buffer_single(this, data, async)
Definition: accel.F90:5086
subroutine laccel_read_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:5668
subroutine daccel_get_device_pointer_2(host_pointer, device_pointer, dimensions)
Definition: accel.F90:2797
subroutine accel_kernel_run_8(kernel, gridsizes, blocksizes, shared_memory_size)
Run a kernel with 8-byte integer sizes.
Definition: accel.F90:1093
subroutine iaccel_read_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:4687
subroutine zaccel_write_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:3200
subroutine zaccel_write_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:3219
subroutine accel_set_buffer_to_zero_i8(buffer, type, nval, offset, async)
Definition: accel.F90:1245
subroutine zaccel_get_device_pointer_1l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:3889
logical pure function, public accel_buffer_is_allocated(this)
Definition: accel.F90:1051
integer, parameter, public accel_mem_read_write
Definition: accel.F90:185
subroutine accel_kernel_end(this)
Definition: accel.F90:1702
subroutine laccel_write_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:5370
subroutine zaccel_write_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:3333
subroutine zaccel_get_device_pointer_2(host_pointer, device_pointer, dimensions)
Definition: accel.F90:3845
subroutine daccel_write_buffer_3(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:2044
subroutine laccel_read_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:5736
type(c_ptr) function, public daccel_get_pointer_with_offset(buffer, offset)
Definition: accel.F90:1813
subroutine iaccel_write_buffer_single(this, data, async)
Definition: accel.F90:4037
subroutine iaccel_get_device_pointer_2(host_pointer, device_pointer, dimensions)
Definition: accel.F90:4893
integer pure function, public accel_max_size_per_dim(dim)
Definition: accel.F90:1754
subroutine zaccel_read_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:3517
subroutine iaccel_read_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:4451
subroutine daccel_read_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:2355
subroutine iaccel_read_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:4668
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:747
subroutine iaccel_read_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:4782
subroutine laccel_write_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:5213
subroutine laccel_write_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:5297
subroutine zaccel_write_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:3061
subroutine laccel_read_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:5698
subroutine laccel_get_device_pointer_2l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:6011
subroutine iaccel_get_device_pointer_3(host_pointer, device_pointer, dimensions)
Definition: accel.F90:4915
subroutine zaccel_write_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:3116
subroutine zaccel_write_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:3273
subroutine daccel_set_kernel_arg_data(kernel, narg, data)
Definition: accel.F90:2757
subroutine iaccel_read_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:4491
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:794
subroutine, public accel_kernel_build(this, file_name, kernel_name, flags)
Compile the program that contains a given kernel.
Definition: accel.F90:1678
subroutine, public accel_init(base_grp, namespace)
Definition: accel.F90:392
subroutine, public accel_end(namespace)
Definition: accel.F90:647
subroutine laccel_write_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:5099
subroutine daccel_write_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:2122
subroutine zaccel_read_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:3543
subroutine, public accel_synchronize_all_streams()
Definition: accel.F90:1801
subroutine, public accel_set_stream(stream_number)
Definition: accel.F90:1766
subroutine laccel_read_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:5559
subroutine iaccel_read_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:4750
subroutine iaccel_read_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:4565
subroutine laccel_get_device_pointer_1l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:5986
subroutine iaccel_read_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:4649
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:762
subroutine iaccel_write_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:4415
integer(int32) function accel_padded_size_i4(nn)
Definition: accel.F90:863
subroutine accel_set_buffer_to_zero_i4(buffer, type, nval, offset, async)
Definition: accel.F90:1261
subroutine daccel_write_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:2319
subroutine laccel_write_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:5316
subroutine iaccel_get_device_pointer_2l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:4962
subroutine iaccel_write_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:4286
pure logical function, public accel_is_enabled()
Definition: accel.F90:372
subroutine zaccel_read_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:3768
type(alloc_cache_t) memcache
Definition: accel.F90:367
subroutine daccel_write_buffer_0_int32(this, n1, data, offset, async)
Definition: accel.F90:2152
subroutine iaccel_write_buffer_4(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:4164
subroutine daccel_write_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:2190
subroutine iaccel_write_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:4267
integer, parameter, public accel_mem_write_only
Definition: accel.F90:185
subroutine zaccel_write_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:3301
subroutine daccel_read_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:2626
subroutine laccel_write_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:5464
subroutine laccel_read_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:5717
subroutine daccel_read_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:2572
subroutine laccel_read_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:5799
subroutine daccel_write_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:2094
subroutine daccel_get_device_pointer_1l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:2841
subroutine iaccel_read_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:4510
subroutine laccel_write_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:5239
subroutine laccel_write_buffer_2(this, n1, n2, data, offset, async)
Definition: accel.F90:5158
subroutine daccel_write_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:2285
subroutine laccel_write_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:5335
subroutine zaccel_get_device_pointer_3(host_pointer, device_pointer, dimensions)
Definition: accel.F90:3867
type(c_ptr) function, public zaccel_get_pointer_with_offset(buffer, offset)
Definition: accel.F90:1828
subroutine iaccel_read_buffer_6_int32(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:4816
subroutine laccel_read_buffer_3_int32(this, n1, n2, n3, data, offset, async)
Definition: accel.F90:5771
subroutine daccel_write_buffer_single(this, data, async)
Definition: accel.F90:1941
subroutine daccel_write_buffer_1_int32(this, n1, data, offset, async)
Definition: accel.F90:2171
subroutine zaccel_write_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:3002
type(accel_t), public accel
Definition: accel.F90:248
subroutine laccel_get_device_pointer_3(host_pointer, device_pointer, dimensions)
Definition: accel.F90:5964
subroutine iaccel_read_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:4619
integer(int64) pure function, public accel_shared_memory_size()
Definition: accel.F90:1747
integer pure function, public accel_max_block_size()
Definition: accel.F90:1143
subroutine iaccel_set_kernel_arg_data(kernel, narg, data)
Definition: accel.F90:4853
subroutine daccel_read_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:2591
subroutine iaccel_read_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:4591
subroutine iaccel_write_buffer_0(this, n1, data, offset, async)
Definition: accel.F90:4050
subroutine zaccel_get_device_pointer_3l(host_pointer, device_pointer, dimensions)
Definition: accel.F90:3938
subroutine accel_create_buffer_8(this, flags, type, size, set_zero, async)
Definition: accel.F90:885
subroutine laccel_read_buffer_1(this, n1, data, offset, async)
Definition: accel.F90:5540
subroutine daccel_read_buffer_5_int32(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:2686
subroutine daccel_read_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:2654
subroutine accel_program_add(file_name, name)
Register a kernel for later retrieval.
Definition: accel.F90:1638
subroutine accel_set_kernel_arg_buffer(kernel, narg, buffer)
Definition: accel.F90:1071
subroutine accel_kernel_list()
The kernels each source provides.
Definition: accel.F90:1361
subroutine laccel_read_buffer_5(this, n1, n2, n3, n4, n5, data, offset, async)
Definition: accel.F90:5640
subroutine zaccel_read_buffer_2_int32(this, n1, n2, data, offset, async)
Definition: accel.F90:3639
subroutine zaccel_write_buffer_6(this, n1, n2, n3, n4, n5, n6, data, offset, async)
Definition: accel.F90:3170
subroutine daccel_get_device_pointer_3(host_pointer, device_pointer, dimensions)
Definition: accel.F90:2819
type(accel_kernel_t), pointer head
Definition: accel.F90:366
subroutine zaccel_read_buffer_4_int32(this, n1, n2, n3, n4, data, offset, async)
Definition: accel.F90:3702
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
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
integer pure function, public types_get_size(this)
Definition: types.F90:154
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)