Octopus
batch.F90
Go to the documentation of this file.
1!! Copyright (C) 2008 X. Andrade, 2020 S. Ohlmann
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
39!
40module batch_oct_m
41 use accel_oct_m
43 use blas_oct_m
44 use debug_oct_m
45 use global_oct_m
47 use iso_c_binding
48 use math_oct_m
50 use mpi_oct_m
52 use types_oct_m
53
54 implicit none
55
56 private
57 public :: &
58 batch_t, &
59 batch_init, &
66
69 type batch_t
70 private
71 integer, public :: nst
72 integer, public :: dim
73 integer :: np
74 integer :: ndims
75 integer, allocatable :: ist_idim_index(:, :)
76
80 integer, allocatable, public :: ist(:)
86
87 logical :: is_allocated
88 logical :: own_memory
89 ! We also need a linear array with the states in order to calculate derivatives, etc.
90 integer, public :: nst_linear
91
92 integer :: status_of
96 integer :: status_host
105 type(type_t) :: type_of
106 integer :: device_buffer_count
107 integer :: host_buffer_count
108 logical :: special_memory
109 logical :: needs_finish_unpack
110
111
112 ! unpacked variables; linear variables are pointers with different shapes
113 real(real64), pointer, contiguous, public :: dff(:, :, :)
114 ! !! indices are (1:np, 1:dim, 1:nst)
115 complex(real64), pointer, contiguous, public :: zff(:, :, :)
116 ! !! indices are (1:np, 1:dim, 1:nst)
117 real(real64), pointer, contiguous, public :: dff_linear(:, :)
118 ! !! indices are (1:np, 1:nst_linear)
119 complex(real64), pointer, contiguous, public :: zff_linear(:, :)
120 ! !! indices are (1:np, 1:nst_linear)
121
122 ! packed variables; only rank-2 arrays due to padding to powers of 2
123 real(real64), pointer, contiguous, public :: dff_pack(:, :)
124 ! !! indices are (1:nst_linear, 1:np)
125 complex(real64), pointer, contiguous, public :: zff_pack(:, :)
126 ! !! indices are (1:nst_linear, 1:np)
127
128 ! single-precision storage (used by the single-precision exchange path)
129 real(real32), pointer, contiguous, public :: sff(:, :, :)
130 complex(real32), pointer, contiguous, public :: cff(:, :, :)
131 real(real32), pointer, contiguous, public :: sff_linear(:, :)
132 complex(real32), pointer, contiguous, public :: cff_linear(:, :)
133 real(real32), pointer, contiguous, public :: sff_pack(:, :)
134 complex(real32), pointer, contiguous, public :: cff_pack(:, :)
136 integer(int64), public :: pack_size(1:2)
138 integer(int64), public :: pack_size_real(1:2)
141
142 type(accel_mem_t), public :: ff_device
143
144 contains
145 procedure :: check_compatibility_with => batch_check_compatibility_with
146 procedure :: clone_to => batch_clone_to
147 procedure :: clone_to_array => batch_clone_to_array
148 procedure :: copy_to => batch_copy_to
149 procedure :: copy_data_to => batch_copy_data_to
150 procedure :: do_pack_generic => batch_do_pack_generic
151 procedure :: do_pack_target => batch_do_pack_target
152 generic :: do_pack => do_pack_generic, do_pack_target
153 procedure :: do_unpack => batch_do_unpack
154 procedure :: finish_unpack => batch_finish_unpack
155 procedure :: end => batch_end
156 procedure :: inv_index => batch_inv_index
157 procedure :: is_packed => batch_is_packed
158 procedure :: ist_idim_to_linear => batch_ist_idim_to_linear
159 procedure :: linear_to_idim => batch_linear_to_idim
160 procedure :: linear_to_ist => batch_linear_to_ist
161 procedure :: pack_total_size => batch_pack_total_size
162 procedure :: remote_access_start => batch_remote_access_start
163 procedure :: remote_access_stop => batch_remote_access_stop
164 procedure :: status => batch_status
165 procedure :: type => batch_type
166 procedure :: type_as_int => batch_type_as_integer
167 procedure, private :: dallocate_unpacked_host => dbatch_allocate_unpacked_host
169 procedure, private :: zallocate_unpacked_host => zbatch_allocate_unpacked_host
171 procedure, private :: sallocate_unpacked_host => sbatch_allocate_unpacked_host
172
173 procedure, private :: callocate_unpacked_host => cbatch_allocate_unpacked_host
174
175 procedure, private :: allocate_unpacked_host => batch_allocate_unpacked_host
176
177 procedure, private :: dallocate_packed_host => dbatch_allocate_packed_host
178
179 procedure, private :: zallocate_packed_host => zbatch_allocate_packed_host
180
181 procedure, private :: sallocate_packed_host => sbatch_allocate_packed_host
183 procedure, private :: callocate_packed_host => cbatch_allocate_packed_host
184
185 procedure, private :: allocate_packed_host => batch_allocate_packed_host
186
187 procedure, private :: allocate_packed_device => batch_allocate_packed_device
188
189 procedure, private :: deallocate_unpacked_host => batch_deallocate_unpacked_host
190
191 procedure, private :: deallocate_packed_host => batch_deallocate_packed_host
192
193 procedure, private :: deallocate_packed_device => batch_deallocate_packed_device
194
195 end type batch_t
196
197 !--------------------------------------------------------------
201 interface batch_init
205 module procedure cbatch_init_with_memory_3
206 module procedure dbatch_init_with_memory_2
207 module procedure zbatch_init_with_memory_2
209 module procedure cbatch_init_with_memory_2
211 module procedure zbatch_init_with_memory_1
213 module procedure cbatch_init_with_memory_1
214 end interface batch_init
215
216 integer, public, parameter :: &
217 batch_not_packed = 0, & !< functions are stored in CPU memory, unpacked order
221 integer, parameter :: gpu_pack_max_buffer_size = 4
223
224contains
226 !--------------------------------------------------------------
234 subroutine batch_end(this, copy)
235 class(batch_t), intent(inout) :: this
236 logical, optional, intent(in) :: copy
238
239 push_sub(batch_end)
241 if (this%own_memory .and. this%is_packed()) then
242 !deallocate directly to avoid unnecessary copies
243 if (this%status() == batch_device_packed) then
244 call this%deallocate_packed_device()
245 end if
246 if (this%status() == batch_packed .or. this%status_host == batch_packed) then
247 call this%deallocate_packed_host()
248 end if
249 this%status_of = batch_not_packed
250 this%status_host = batch_not_packed
251 this%host_buffer_count = 0
252 this%device_buffer_count = 0
253 end if
254 if (this%status() == batch_device_packed) call this%do_unpack(copy, force = .true.)
255 if (this%status() == batch_packed) call this%do_unpack(copy, force = .true.)
257 if (this%is_allocated) then
258 call this%deallocate_unpacked_host()
259 end if
261 safe_deallocate_a(this%ist_idim_index)
262 safe_deallocate_a(this%ist)
263
264 pop_sub(batch_end)
265 end subroutine batch_end
267 !--------------------------------------------------------------
271 !
273 class(batch_t), intent(inout) :: this
277 this%is_allocated = .false.
279 if (this%special_memory) then
280 if (associated(this%dff)) then
281 call deallocate_hardware_aware(c_loc(this%dff(1,1,1)), int(this%np, int64)*this%dim*this%nst*8)
282 end if
283 if (associated(this%zff)) then
284 call deallocate_hardware_aware(c_loc(this%zff(1,1,1)), int(this%np, int64)*this%dim*this%nst*16)
285 end if
286 if (associated(this%sff)) then
287 call deallocate_hardware_aware(c_loc(this%sff(1,1,1)), int(this%np, int64)*this%dim*this%nst*4)
288 end if
289 if (associated(this%cff)) then
290 call deallocate_hardware_aware(c_loc(this%cff(1,1,1)), int(this%np, int64)*this%dim*this%nst*8)
291 end if
292 else
293 safe_deallocate_p(this%dff)
294 safe_deallocate_p(this%zff)
295 safe_deallocate_p(this%sff)
296 safe_deallocate_p(this%cff)
297 end if
298 nullify(this%dff)
299 nullify(this%dff_linear)
300 nullify(this%zff)
301 nullify(this%zff_linear)
302 nullify(this%sff)
303 nullify(this%sff_linear)
304 nullify(this%cff)
305 nullify(this%cff_linear)
306
308 end subroutine batch_deallocate_unpacked_host
309
310 !--------------------------------------------------------------
314 !
315 subroutine batch_deallocate_packed_host(this)
316 class(batch_t), intent(inout) :: this
317
319
320 if (this%special_memory) then
321 if (associated(this%dff_pack)) then
322 call deallocate_hardware_aware(c_loc(this%dff_pack(1,1)), int(this%pack_size(1), int64)*this%pack_size(2)*8)
323 end if
324 if (associated(this%zff_pack)) then
325 call deallocate_hardware_aware(c_loc(this%zff_pack(1,1)), int(this%pack_size(1), int64)*this%pack_size(2)*16)
326 end if
327 if (associated(this%sff_pack)) then
328 call deallocate_hardware_aware(c_loc(this%sff_pack(1,1)), int(this%pack_size(1), int64)*this%pack_size(2)*4)
329 end if
330 if (associated(this%cff_pack)) then
331 call deallocate_hardware_aware(c_loc(this%cff_pack(1,1)), int(this%pack_size(1), int64)*this%pack_size(2)*8)
332 end if
333 else
334 safe_deallocate_p(this%dff_pack)
335 safe_deallocate_p(this%zff_pack)
336 safe_deallocate_p(this%sff_pack)
337 safe_deallocate_p(this%cff_pack)
338 end if
339 nullify(this%dff_pack)
340 nullify(this%zff_pack)
341 nullify(this%sff_pack)
342 nullify(this%cff_pack)
343
345 end subroutine batch_deallocate_packed_host
346
347 !--------------------------------------------------------------
349 !
350 subroutine batch_deallocate_packed_device(this)
351 class(batch_t), intent(inout) :: this
352
354
355 call accel_free_buffer(this%ff_device)
356
358 end subroutine batch_deallocate_packed_device
359
360 !--------------------------------------------------------------
364 !
365 subroutine batch_allocate_unpacked_host(this)
366 class(batch_t), intent(inout) :: this
369
370 if (this%type() == type_float) then
371 call this%dallocate_unpacked_host()
372 else if (this%type() == type_cmplx) then
373 call this%zallocate_unpacked_host()
374 else if (this%type() == type_float_single) then
375 call this%sallocate_unpacked_host()
376 else if (this%type() == type_cmplx_single) then
377 call this%callocate_unpacked_host()
378 end if
379
381 end subroutine batch_allocate_unpacked_host
382
383 !--------------------------------------------------------------
387 !
388 subroutine batch_allocate_packed_host(this)
389 class(batch_t), intent(inout) :: this
390
392
393 if (this%type() == type_float) then
394 call this%dallocate_packed_host()
395 else if (this%type() == type_cmplx) then
396 call this%zallocate_packed_host()
397 else if (this%type() == type_float_single) then
398 call this%sallocate_packed_host()
399 else if (this%type() == type_cmplx_single) then
400 call this%callocate_packed_host()
401 end if
402
404 end subroutine batch_allocate_packed_host
405
406 !--------------------------------------------------------------
411 subroutine batch_allocate_packed_device(this)
412 class(batch_t), intent(inout) :: this
413
415
416 call accel_create_buffer(this%ff_device, accel_mem_read_write, this%type(), &
417 product(this%pack_size))
418
420 end subroutine batch_allocate_packed_device
421
422 !--------------------------------------------------------------
428 !
429 subroutine batch_init_empty (this, dim, nst, np)
430 type(batch_t), intent(out) :: this
431 integer, intent(in) :: dim
432 integer, intent(in) :: nst
433 integer, intent(in) :: np
434
435 push_sub(batch_init_empty)
436
437 this%is_allocated = .false.
438 this%own_memory = .false.
439 this%special_memory = .false.
440 this%needs_finish_unpack = .false.
441 this%nst = nst
442 this%dim = dim
443 this%type_of = type_none
444
445 this%nst_linear = nst*dim
446
447 this%np = np
448 this%device_buffer_count = 0
449 this%host_buffer_count = 0
450 this%status_of = batch_not_packed
451 this%status_host = batch_not_packed
452
453 this%ndims = 2
454 safe_allocate(this%ist_idim_index(1:this%nst_linear, 1:this%ndims))
455 safe_allocate(this%ist(1:this%nst))
456
457 nullify(this%dff, this%zff, this%dff_linear, this%zff_linear)
458 nullify(this%dff_pack, this%zff_pack)
459 nullify(this%sff, this%cff, this%sff_linear, this%cff_linear)
460 nullify(this%sff_pack, this%cff_pack)
461
462 pop_sub(batch_init_empty)
463 end subroutine batch_init_empty
464
465 !--------------------------------------------------------------
470 !
471 subroutine batch_clone_to(this, dest, pack, copy_data, new_np, special, dest_type)
472 class(batch_t), intent(in) :: this
473 class(batch_t), allocatable, intent(out) :: dest
474 logical, optional, intent(in) :: pack
476 logical, optional, intent(in) :: copy_data
478 integer, optional, intent(in) :: new_np
479 logical, optional, intent(in) :: special
481 type(type_t), optional, intent(in) :: dest_type
482
484
485 if (.not. allocated(dest)) then
486 safe_allocate_type(batch_t, dest)
487 else
488 message(1) = "Internal error: destination batch in batch_clone_to has been previously allocated."
489 call messages_fatal(1)
490 end if
491
492 call this%copy_to(dest, pack, copy_data, new_np, special, dest_type)
493
494 pop_sub(batch_clone_to)
495 end subroutine batch_clone_to
496
497 !--------------------------------------------------------------
498
499 subroutine batch_clone_to_array(this, dest, n_batches, pack, copy_data, new_np, special, dest_type)
500 class(batch_t), intent(in) :: this
501 class(batch_t), allocatable, intent(out) :: dest(:)
502 integer, intent(in) :: n_batches
503 logical, optional, intent(in) :: pack
505 logical, optional, intent(in) :: copy_data
507 integer, optional, intent(in) :: new_np
508 logical, optional, intent(in) :: special
510 type(type_t), optional, intent(in) :: dest_type
511
512 integer :: ib
513
514 push_sub(batch_clone_to_array)
515
516 if (.not. allocated(dest)) then
517 safe_allocate_type_array(batch_t, dest, (1:n_batches))
518 else
519 message(1) = "Internal error: destination batch in batch_clone_to_array has been previously allocated."
520 call messages_fatal(1)
521 end if
522
523 do ib = 1, n_batches
524 call this%copy_to(dest(ib), pack, copy_data, new_np, special, dest_type)
525 end do
526
527 pop_sub(batch_clone_to_array)
528 end subroutine batch_clone_to_array
529
530 !--------------------------------------------------------------
535 subroutine batch_copy_to(this, dest, pack, copy_data, new_np, special, dest_type)
536 class(batch_t), intent(in) :: this
537 class(batch_t), intent(out) :: dest
538 logical, optional, intent(in) :: pack
540 logical, optional, intent(in) :: copy_data
542 integer, optional, intent(in) :: new_np
543 logical, optional, intent(in) :: special
545 type(type_t), optional, intent(in) :: dest_type
546
547 logical :: host_packed, special_
548 integer :: np_
549 type(type_t) :: type_
550
551 push_sub(batch_copy_to)
552
553 np_ = optional_default(new_np, this%np)
554
555 host_packed = this%host_buffer_count > 0
556 ! use special memory here only for batches not on the GPU to avoid allocating
557 ! pinned memory for temporary batches because that leads to a severe performance
558 ! decrease for GPU runs (up to 20x)
559 if (present(special)) then
560 special_ = this%special_memory
561 else
562 special_ = this%special_memory .and. .not. this%device_buffer_count > 0
563 end if
564
565 if (present(dest_type)) then
566 type_ = dest_type
567 else
568 type_ = this%type()
569 end if
570
571 if (type_ == type_float) then
572 call dbatch_init(dest, this%dim, 1, this%nst, np_, packed=host_packed, special=special_)
573 else if (type_ == type_cmplx) then
574 call zbatch_init(dest, this%dim, 1, this%nst, np_, packed=host_packed, special=special_)
575 else if (type_ == type_float_single) then
576 call sbatch_init(dest, this%dim, 1, this%nst, np_, packed=host_packed, special=special_)
577 else if (type_ == type_cmplx_single) then
578 call cbatch_init(dest, this%dim, 1, this%nst, np_, packed=host_packed, special=special_)
579 else
580 message(1) = "Internal error: unknown batch type in batch_copy_to."
581 call messages_fatal(1)
582 end if
583
584 if (this%status() /= dest%status() .and. optional_default(pack, this%is_packed())) call dest%do_pack(copy = .false.)
585
586 dest%ist_idim_index(1:this%nst_linear, 1:this%ndims) = this%ist_idim_index(1:this%nst_linear, 1:this%ndims)
587 dest%ist(1:this%nst) = this%ist(1:this%nst)
588
589 if (optional_default(copy_data, .false.)) then
590 assert(np_ == this%np)
591 ! copy_data_to cannot convert precision; use batch_copy_precision instead
592 assert(type_is_single(this%type()) .eqv. type_is_single(dest%type()))
593 call this%copy_data_to(min(this%np, np_), dest)
594 end if
595
596 pop_sub(batch_copy_to)
597 end subroutine batch_copy_to
598
599 ! ----------------------------------------------------
604 type(type_t) pure function batch_type(this) result(btype)
605 class(batch_t), intent(in) :: this
606
607 btype = this%type_of
608
609 end function batch_type
610
611 ! ----------------------------------------------------
613 integer pure function batch_type_as_integer(this) result(itype)
614 class(batch_t), intent(in) :: this
615
616 type(type_t) :: btype
617
618 itype = 0
619 btype = this%type()
620 if (btype == type_float) itype = 1
621 if (btype == type_cmplx) itype = 2
622 if (btype == type_float_single) itype = 3
623 if (btype == type_cmplx_single) itype = 4
624
625 end function batch_type_as_integer
626
627 ! ----------------------------------------------------
632 integer pure function batch_status(this) result(bstatus)
633 class(batch_t), intent(in) :: this
634
635 bstatus = this%status_of
636 end function batch_status
637
638 ! ----------------------------------------------------
639
640 logical pure function batch_is_packed(this) result(in_buffer)
641 class(batch_t), intent(in) :: this
642
643 in_buffer = (this%device_buffer_count > 0) .or. (this%host_buffer_count > 0)
644 end function batch_is_packed
645
646 ! ----------------------------------------------------
647
648 integer(int64) function batch_pack_total_size(this) result(size)
649 class(batch_t), intent(inout) :: this
650
651 size = this%np
652 if (accel_is_enabled()) size = accel_padded_size(size)
653 size = size*pad_pow2(this%nst_linear)*types_get_size(this%type())
654
655 end function batch_pack_total_size
656
657 ! ----------------------------------------------------
658
664 subroutine batch_do_pack_generic(this, copy, async)
665 class(batch_t), intent(inout) :: this
666 logical, optional, intent(in) :: copy
667 logical, optional, intent(in) :: async
669
670 integer :: source, target
671
672 ! no push_sub, called too frequently
673
674 ! get source and target states for this batch
675 source = this%status()
676 select case (source)
678 if (accel_is_enabled()) then
679 target = batch_device_packed
680 else
681 target = batch_packed
682 end if
684 target = batch_device_packed
685 end select
686
687 call this%do_pack(target, copy, async)
688
689 end subroutine batch_do_pack_generic
690
695 subroutine batch_do_pack_target(this, target, copy, async, cpu_only)
696 class(batch_t), intent(inout) :: this
697 integer, intent(in) :: target
698 logical, optional, intent(in) :: copy
699 logical, optional, intent(in) :: async
701 logical, optional, intent(in) :: cpu_only
702
703 logical :: copy_
704 logical :: async_
705 integer :: source
706
707 ! no push_sub, called too frequently
709 call profiling_in("BATCH_DO_PACK")
710
711 copy_ = optional_default(copy, .true.)
712
713 async_ = optional_default(async, .false.)
714
715 ! get source state for this batch
716 source = this%status()
717
718 ! only do something if target is different from source
719 if (source /= target) then
720 select case (target)
722 call this%allocate_packed_device()
723 this%status_of = batch_device_packed ! Note that this%status_host remains untouched.
724
725 if (copy_) then
726 select case (source)
728 ! copy from unpacked host array to device
730 case (batch_packed)
731 ! copy from packed host array to device
732 call batch_write_packed_to_device(this, async_)
733 end select
734 end if
736 call this%allocate_packed_host()
737 this%status_of = batch_packed
738 this%status_host = batch_packed
739
740 if (copy_) then
741 if (this%type() == type_float) then
742 call dbatch_pack_copy(this)
743 else if (this%type() == type_cmplx) then
744 call zbatch_pack_copy(this)
745 else if (this%type() == type_float_single) then
746 call sbatch_pack_copy(this)
747 else if (this%type() == type_cmplx_single) then
748 call cbatch_pack_copy(this)
749 end if
750 end if
751 if (this%own_memory) call this%deallocate_unpacked_host()
752 case (batch_not_packed)
753 call messages_not_implemented("Error: batch_do_pack called with BATCH_NOT_PACKED as target.")
754 end select
755 end if
756
757 select case (target)
759 this%device_buffer_count = this%device_buffer_count + 1
760 case (batch_packed)
761 this%host_buffer_count = this%host_buffer_count + 1
762 end select
763
764 call profiling_out("BATCH_DO_PACK")
765 end subroutine batch_do_pack_target
766
767
768 ! ----------------------------------------------------
773 subroutine batch_do_unpack(this, copy, force, async)
774 class(batch_t), intent(inout) :: this
775 logical, optional, intent(in) :: copy
776 logical, optional, intent(in) :: force
777 logical, optional, intent(in) :: async
779
780 logical :: copy_, force_, async_
781 integer :: source, target
782
783 push_sub(batch_do_unpack)
784
785 call profiling_in("BATCH_DO_UNPACK")
786
787 copy_ = optional_default(copy, .true.)
788
789 force_ = optional_default(force, .false.)
791 async_ = optional_default(async, .false.)
792
793 ! get source and target states for this batch
794 source = this%status()
795 select case (source)
796 case (batch_not_packed)
797 target = source
798 case (batch_packed)
799 target = batch_not_packed
801 target = this%status_host
802 end select
803
804 ! only do something if target is different from source
805 if (source /= target) then
806 select case (source)
807 case (batch_packed)
808 if (this%host_buffer_count == 1 .or. force_) then
809 if (this%own_memory) call this%allocate_unpacked_host()
810 ! unpack from packed_host to unpacked_host
811 if (copy_ .or. this%own_memory) then
812 if (this%type() == type_float) then
813 call dbatch_unpack_copy(this)
814 else if (this%type() == type_cmplx) then
815 call zbatch_unpack_copy(this)
816 else if (this%type() == type_float_single) then
817 call sbatch_unpack_copy(this)
818 else if (this%type() == type_cmplx_single) then
819 call cbatch_unpack_copy(this)
820 end if
821 end if
822 call this%deallocate_packed_host()
823 this%status_host = target
824 this%status_of = target
825 this%host_buffer_count = 1
826 end if
827 this%host_buffer_count = this%host_buffer_count - 1
829 if (this%device_buffer_count == 1 .or. force_) then
830 if (copy_) then
831 select case (target)
832 ! unpack from packed_device to unpacked_host
833 case (batch_not_packed)
835 ! unpack from packed_device to packed_host
836 case (batch_packed)
837 call batch_read_device_to_packed(this, async_)
838 end select
839 end if
840 if (async_) then
841 this%needs_finish_unpack = .true.
842 else
843 call this%deallocate_packed_device()
844 end if
845 this%status_of = target
846 this%device_buffer_count = 1
847 end if
848 this%device_buffer_count = this%device_buffer_count - 1
849 end select
850 end if
851
852 call profiling_out("BATCH_DO_UNPACK")
853
854 pop_sub(batch_do_unpack)
855 end subroutine batch_do_unpack
856
857 ! ----------------------------------------------------
859 subroutine batch_finish_unpack(this)
860 class(batch_t), intent(inout) :: this
861
862 push_sub(batch_finish_unpack)
863 if (this%needs_finish_unpack) then
864 call accel_finish()
865 call this%deallocate_packed_device()
866 this%needs_finish_unpack = .false.
867 end if
869 end subroutine batch_finish_unpack
870
871 ! ----------------------------------------------------
872
873 subroutine batch_write_unpacked_to_device(this)
874 class(batch_t), intent(inout) :: this
875
876 integer :: ist, ist2
877 integer(int64) :: unroll, bsize, gsize
878 type(accel_mem_t) :: tmp
879 type(accel_kernel_t), pointer :: kernel
880
882
883 call profiling_in("BATCH_WRT_UNPACK_ACCEL")
884 if (this%nst_linear == 1) then
885 ! we can copy directly
886 if (this%type() == type_float) then
887 call accel_write_buffer(this%ff_device, ubound(this%dff_linear, dim=1), this%dff_linear(:, 1))
888 else if (this%type() == type_cmplx) then
889 call accel_write_buffer(this%ff_device, ubound(this%zff_linear, dim=1), this%zff_linear(:, 1))
890 else if (this%type() == type_float_single) then
891 call accel_write_buffer(this%ff_device, ubound(this%sff_linear, dim=1), this%sff_linear(:, 1))
892 else
893 call accel_write_buffer(this%ff_device, ubound(this%cff_linear, dim=1), this%cff_linear(:, 1))
894 end if
895
896 else
897 ! we copy to a temporary array and then we re-arrange data
898
899 if (this%type() == type_float) then
900 kernel => dpack
901 else if (this%type() == type_cmplx) then
902 kernel => zpack
903 else if (this%type() == type_float_single) then
904 kernel => spack
905 else
906 kernel => cpack
907 end if
908
909 unroll = min(int(gpu_pack_max_buffer_size, int64), this%pack_size(1))
910
911 call accel_create_buffer(tmp, accel_mem_read_only, this%type(), unroll*this%pack_size(2))
912
913 do ist = 1, this%nst_linear, int(unroll, int32)
914
915 ! copy a number 'unroll' of states to the buffer
916 do ist2 = ist, min(ist + int(unroll, int32) - 1, this%nst_linear)
917
918 if (this%type() == type_float) then
919 call accel_write_buffer(tmp, ubound(this%dff_linear, dim=1, kind=int64), this%dff_linear(:, ist2), &
920 offset = (ist2 - ist)*this%pack_size(2))
921 else if (this%type() == type_cmplx) then
922 call accel_write_buffer(tmp, ubound(this%zff_linear, dim=1, kind=int64), this%zff_linear(:, ist2), &
923 offset = (ist2 - ist)*this%pack_size(2))
924 else if (this%type() == type_float_single) then
925 call accel_write_buffer(tmp, ubound(this%sff_linear, dim=1, kind=int64), this%sff_linear(:, ist2), &
926 offset = (ist2 - ist)*this%pack_size(2))
927 else
928 call accel_write_buffer(tmp, ubound(this%cff_linear, dim=1, kind=int64), this%cff_linear(:, ist2), &
929 offset = (ist2 - ist)*this%pack_size(2))
930 end if
931 end do
932
933 ! now call a kernel to rearrange the data
934 call accel_set_kernel_arg(kernel, 0, int(this%pack_size(1), int32))
935 call accel_set_kernel_arg(kernel, 1, this%np)
936 call accel_set_kernel_arg(kernel, 2, this%nst_linear)
937 call accel_set_kernel_arg(kernel, 3, ist - 1)
938 call accel_set_kernel_arg(kernel, 4, tmp)
939 call accel_set_kernel_arg(kernel, 5, this%ff_device)
940
941 call profiling_in("GPU_PACK")
942
943 ! Compute the grid size
944 bsize = accel_max_block_size()/unroll
945 call accel_grid_size(this%pack_size(2), bsize, gsize)
946
947 call accel_kernel_run(kernel, (/gsize, 1_int64/), (/bsize, unroll/))
948
949 if (this%type() == type_float) then
950 call profiling_count_transfers(unroll*this%pack_size(2), m_one)
951 else
952 call profiling_count_transfers(unroll*this%pack_size(2), m_zi)
953 end if
955 call accel_finish()
956 call profiling_out("GPU_PACK")
957
958 end do
959
960 call accel_free_buffer(tmp)
961
962 end if
963
964 call profiling_out("BATCH_WRT_UNPACK_ACCEL")
966 end subroutine batch_write_unpacked_to_device
967
968 ! ------------------------------------------------------------------
969
970 subroutine batch_read_device_to_unpacked(this)
971 class(batch_t), intent(inout) :: this
972
973 integer :: ist, ist2
974 integer(int64) :: unroll, bsize, gsize
975 type(accel_mem_t) :: tmp
976 type(accel_kernel_t), pointer :: kernel
977
979 call profiling_in("BATCH_READ_UNPACKED_ACCEL")
980
981 if (this%nst_linear == 1) then
982 ! we can copy directly
983 if (this%type() == type_float) then
984 call accel_read_buffer(this%ff_device, ubound(this%dff_linear, dim=1), this%dff_linear(:, 1))
985 else if (this%type() == type_cmplx) then
986 call accel_read_buffer(this%ff_device, ubound(this%zff_linear, dim=1), this%zff_linear(:, 1))
987 else if (this%type() == type_float_single) then
988 call accel_read_buffer(this%ff_device, ubound(this%sff_linear, dim=1), this%sff_linear(:, 1))
989 else
990 call accel_read_buffer(this%ff_device, ubound(this%cff_linear, dim=1), this%cff_linear(:, 1))
991 end if
992 else
993
994 unroll = min(int(gpu_pack_max_buffer_size, int64), this%pack_size(1))
995
996 ! we use a kernel to move to a temporary array and then we read
997 call accel_create_buffer(tmp, accel_mem_write_only, this%type(), unroll*this%pack_size(2))
998
999 if (this%type() == type_float) then
1000 kernel => dunpack
1001 else if (this%type() == type_cmplx) then
1002 kernel => zunpack
1003 else if (this%type() == type_float_single) then
1004 kernel => sunpack
1005 else
1006 kernel => cunpack
1007 end if
1008
1009 do ist = 1, this%nst_linear, int(unroll, int32)
1010 call accel_set_kernel_arg(kernel, 0, int(this%pack_size(1), int32))
1011 call accel_set_kernel_arg(kernel, 1, this%np)
1012 call accel_set_kernel_arg(kernel, 2, this%nst_linear)
1013 call accel_set_kernel_arg(kernel, 3, ist - 1)
1014 call accel_set_kernel_arg(kernel, 4, this%ff_device)
1015 call accel_set_kernel_arg(kernel, 5, tmp)
1016
1017 call profiling_in("GPU_UNPACK")
1018
1019 ! Compute the grid size
1020 bsize = accel_max_block_size()/unroll
1021 call accel_grid_size(this%pack_size(2), bsize, gsize)
1022
1023 call accel_kernel_run(kernel, (/1_int64, gsize/), (/unroll, bsize/))
1024
1025 if (this%type() == type_float) then
1026 call profiling_count_transfers(unroll*this%pack_size(2), m_one)
1027 else
1028 call profiling_count_transfers(unroll*this%pack_size(2), m_zi)
1029 end if
1030
1031 call accel_finish()
1032 call profiling_out("GPU_UNPACK")
1033
1034 ! copy a number 'unroll' of states from the buffer
1035 do ist2 = ist, min(ist + int(unroll, int32) - 1, this%nst_linear)
1036
1037 if (this%type() == type_float) then
1038 call accel_read_buffer(tmp, ubound(this%dff_linear, dim=1, kind=int64), this%dff_linear(:, ist2), &
1039 offset = (ist2 - ist)*this%pack_size(2))
1040 else if (this%type() == type_cmplx) then
1041 call accel_read_buffer(tmp, ubound(this%zff_linear, dim=1, kind=int64), this%zff_linear(:, ist2), &
1042 offset = (ist2 - ist)*this%pack_size(2))
1043 else if (this%type() == type_float_single) then
1044 call accel_read_buffer(tmp, ubound(this%sff_linear, dim=1, kind=int64), this%sff_linear(:, ist2), &
1045 offset = (ist2 - ist)*this%pack_size(2))
1046 else
1047 call accel_read_buffer(tmp, ubound(this%cff_linear, dim=1, kind=int64), this%cff_linear(:, ist2), &
1048 offset = (ist2 - ist)*this%pack_size(2))
1049 end if
1050 end do
1051
1052 end do
1053
1054 call accel_free_buffer(tmp)
1055 end if
1056
1057 call profiling_out("BATCH_READ_UNPACKED_ACCEL")
1059 end subroutine batch_read_device_to_unpacked
1060
1061 ! ------------------------------------------------------------------
1062 subroutine batch_write_packed_to_device(this, async)
1063 class(batch_t), intent(inout) :: this
1064 logical, optional, intent(in) :: async
1066
1068
1069 call profiling_in("BATCH_WRITE_PACKED_ACCEL")
1070 if (this%type() == type_float) then
1071 call accel_write_buffer(this%ff_device, this%pack_size(1), this%pack_size(2), this%dff_pack, async=async)
1072 else if (this%type() == type_cmplx) then
1073 call accel_write_buffer(this%ff_device, this%pack_size(1), this%pack_size(2), this%zff_pack, async=async)
1074 else if (this%type() == type_float_single) then
1075 call accel_write_buffer(this%ff_device, this%pack_size(1), this%pack_size(2), this%sff_pack, async=async)
1076 else
1077 call accel_write_buffer(this%ff_device, this%pack_size(1), this%pack_size(2), this%cff_pack, async=async)
1078 end if
1079 call profiling_out("BATCH_WRITE_PACKED_ACCEL")
1080
1082 end subroutine batch_write_packed_to_device
1083
1084 ! ------------------------------------------------------------------
1085 subroutine batch_read_device_to_packed(this, async)
1086 class(batch_t), intent(inout) :: this
1087 logical, optional, intent(in) :: async
1088
1089
1091
1092 call profiling_in("BATCH_READ_PACKED_ACCEL")
1093 if (this%type() == type_float) then
1094 call accel_read_buffer(this%ff_device, this%pack_size(1), this%pack_size(2), this%dff_pack, async=async)
1095 else if (this%type() == type_cmplx) then
1096 call accel_read_buffer(this%ff_device, this%pack_size(1), this%pack_size(2), this%zff_pack, async=async)
1097 else if (this%type() == type_float_single) then
1098 call accel_read_buffer(this%ff_device, this%pack_size(1), this%pack_size(2), this%sff_pack, async=async)
1099 else
1100 call accel_read_buffer(this%ff_device, this%pack_size(1), this%pack_size(2), this%cff_pack, async=async)
1101 end if
1102 call profiling_out("BATCH_READ_PACKED_ACCEL")
1103
1105 end subroutine batch_read_device_to_packed
1106
1107 ! ------------------------------------------------------
1112 integer function batch_inv_index(this, cind) result(index)
1113 class(batch_t), intent(in) :: this
1114 integer, intent(in) :: cind(:)
1115
1116 do index = 1, this%nst_linear
1117 if (all(cind(1:this%ndims) == this%ist_idim_index(index, 1:this%ndims))) exit
1118 end do
1119
1120 assert(index <= this%nst_linear)
1121
1122 end function batch_inv_index
1123
1124 ! ------------------------------------------------------
1128 !
1129 integer pure function batch_ist_idim_to_linear(this, cind) result(index)
1130 class(batch_t), intent(in) :: this
1131 integer, intent(in) :: cind(:)
1132
1133 if (ubound(cind, dim = 1) == 1) then
1134 index = cind(1)
1135 else
1136 index = (cind(1) - 1)*this%dim + cind(2)
1137 end if
1138
1139 end function batch_ist_idim_to_linear
1140
1141 ! ------------------------------------------------------
1146 !
1147 integer pure function batch_linear_to_ist(this, linear_index) result(ist)
1148 class(batch_t), intent(in) :: this
1149 integer, intent(in) :: linear_index
1150
1151 ist = this%ist_idim_index(linear_index, 1)
1152
1153 end function batch_linear_to_ist
1154
1155 ! ------------------------------------------------------
1158 integer pure function batch_linear_to_idim(this, linear_index) result(idim)
1159 class(batch_t), intent(in) :: this
1160 integer, intent(in) :: linear_index
1161
1162 idim = this%ist_idim_index(linear_index, 2)
1163
1164 end function batch_linear_to_idim
1165
1166 ! ------------------------------------------------------
1175 !
1176 subroutine batch_remote_access_start(this, mpi_grp, rma_win)
1177 class(batch_t), intent(inout) :: this
1178 type(mpi_grp_t), intent(in) :: mpi_grp
1179 type(mpi_win), intent(out) :: rma_win
1182
1183 if (mpi_grp%size > 1) then
1184
1185 assert(.not. accel_is_enabled())
1186
1187 call this%do_pack()
1188
1189 assert(int(product(this%pack_size)*types_get_size(this%type())) > 0) ! In case of overflow, this becomes negative
1190 if (this%type() == type_cmplx) then
1191#ifdef HAVE_MPI
1192 call mpi_win_create(this%zff_pack(1, 1), int(product(this%pack_size)*types_get_size(this%type()), mpi_address_kind), &
1193 types_get_size(this%type()), mpi_info_null, mpi_grp%comm, rma_win)
1194#endif
1195 else if (this%type() == type_float) then
1196#ifdef HAVE_MPI
1197 call mpi_win_create(this%dff_pack(1, 1), int(product(this%pack_size)*types_get_size(this%type()), mpi_address_kind), &
1198 types_get_size(this%type()), mpi_info_null, mpi_grp%comm, rma_win)
1199#endif
1200 else if (this%type() == type_cmplx_single) then
1201#ifdef HAVE_MPI
1202 call mpi_win_create(this%cff_pack(1, 1), int(product(this%pack_size)*types_get_size(this%type()), mpi_address_kind), &
1203 types_get_size(this%type()), mpi_info_null, mpi_grp%comm, rma_win)
1204#endif
1205 else if (this%type() == type_float_single) then
1206#ifdef HAVE_MPI
1207 call mpi_win_create(this%sff_pack(1, 1), int(product(this%pack_size)*types_get_size(this%type()), mpi_address_kind), &
1208 types_get_size(this%type()), mpi_info_null, mpi_grp%comm, rma_win)
1209#endif
1210 else
1211 message(1) = "Internal error: unknown batch type in batch_remote_access_start."
1212 call messages_fatal(1)
1213 end if
1214
1215 else
1216 rma_win = mpi_win_null
1217 end if
1218
1220 end subroutine batch_remote_access_start
1221
1222 ! ------------------------------------------------------
1228 !
1229 subroutine batch_remote_access_stop(this, rma_win)
1230 class(batch_t), intent(inout) :: this
1231 type(mpi_win), intent(inout) :: rma_win
1232
1233 push_sub(batch_remote_access_stop)
1234
1235 if (rma_win /= mpi_win_null) then
1236#ifdef HAVE_MPI
1237 call mpi_win_free(rma_win)
1238#endif
1239 call this%do_unpack()
1240 end if
1241
1243 end subroutine batch_remote_access_stop
1244
1245 ! --------------------------------------------------------------
1247 !
1248 subroutine batch_copy_data_to(this, np, dest, async)
1249 class(batch_t), intent(in) :: this
1250 integer, intent(in) :: np
1251 class(batch_t), intent(inout) :: dest
1252 logical, optional, intent(in) :: async
1254 integer(int64), dimension(3) :: gsizes, bsizes
1255 integer :: ist, ip
1256 type(accel_kernel_t), pointer :: kernel
1257
1258 push_sub(batch_copy_data_to)
1259 call profiling_in("BATCH_COPY_DATA_TO")
1260
1261 ! this routine can be used to copy data between batches of different type
1262 call this%check_compatibility_with(dest, type_check=.false.)
1263
1264 if (this%type() == dest%type()) then
1265 select case (this%status())
1266 case (batch_device_packed)
1267 ! pack_size_real counts elements of the real type matching the batch precision,
1268 ! so the kernel has to match it
1269 if (type_is_single(this%type())) then
1270 kernel => kernel_scopy
1271 else
1272 kernel => kernel_copy
1273 end if
1274 call accel_set_kernel_arg(kernel, 0, np)
1275 call accel_set_kernel_arg(kernel, 1, this%ff_device)
1276 call accel_set_kernel_arg(kernel, 2, log2(int(this%pack_size_real(1), int32)))
1277 call accel_set_kernel_arg(kernel, 3, dest%ff_device)
1278 call accel_set_kernel_arg(kernel, 4, log2(int(dest%pack_size_real(1), int32)))
1279
1280 ! Compute the grid (extend to another dimensions if the size of the problem is too big)
1281 call accel_grid_size_extend_dim(int(np, int64), dest%pack_size_real(1), gsizes, bsizes, kernel)
1282
1283 call accel_kernel_run(kernel, gsizes, bsizes)
1284
1285 if(.not. optional_default(async, .false.)) call accel_finish()
1286
1287 case (batch_packed)
1288 if (dest%type() == type_float_single) then
1289 !$omp parallel do private(ist) schedule(static)
1290 do ip = 1, np
1291 do ist = 1, int(this%pack_size(1), int32)
1292 dest%sff_pack(ist, ip) = this%sff_pack(ist, ip)
1293 end do
1294 end do
1295 else if (dest%type() == type_cmplx_single) then
1296 !$omp parallel do private(ist) schedule(static)
1297 do ip = 1, np
1298 do ist = 1, int(this%pack_size(1), int32)
1299 dest%cff_pack(ist, ip) = this%cff_pack(ist, ip)
1300 end do
1301 end do
1302 else if (np*this%pack_size(1) > huge(0_int32)) then
1303 ! BLAS cannot handle 8-byte integers, so we need a special version here
1304 do ip = 1, np
1305 if (dest%type() == type_float) then
1306 call blas_copy(int(this%pack_size(1), int32), this%dff_pack(1, ip), 1, dest%dff_pack(1, ip), 1)
1307 else
1308 call blas_copy(int(this%pack_size(1), int32), this%zff_pack(1, ip), 1, dest%zff_pack(1, ip), 1)
1309 end if
1310 end do
1311 else
1312 if (dest%type() == type_float) then
1313 call blas_copy(int(this%pack_size(1)*np, int32), this%dff_pack(1, 1), 1, dest%dff_pack(1, 1), 1)
1314 else
1315 call blas_copy(int(this%pack_size(1)*np, int32), this%zff_pack(1, 1), 1, dest%zff_pack(1, 1), 1)
1316 end if
1317 end if
1318
1319 case (batch_not_packed)
1320 do ist = 1, dest%nst_linear
1321 if (dest%type() == type_cmplx) then
1322 call blas_copy(np, this%zff_linear(1, ist), 1, dest%zff_linear(1, ist), 1)
1323 else if (dest%type() == type_float_single) then
1324 !$omp parallel do schedule(static)
1325 do ip = 1, np
1326 dest%sff_linear(ip, ist) = this%sff_linear(ip, ist)
1327 end do
1328 else if (dest%type() == type_cmplx_single) then
1329 !$omp parallel do schedule(static)
1330 do ip = 1, np
1331 dest%cff_linear(ip, ist) = this%cff_linear(ip, ist)
1332 end do
1333 else
1334 call blas_copy(np, this%dff_linear(1, ist), 1, dest%dff_linear(1, ist), 1)
1335 end if
1336 end do
1337
1338 end select
1339 else if (this%type() == type_cmplx) then
1340 ! copy complex -> real
1341 select case (this%status())
1342 case (batch_device_packed)
1343 call accel_set_kernel_arg(kernel_copy_complex_to_real, 0, np)
1344 call accel_set_kernel_arg(kernel_copy_complex_to_real, 1, this%ff_device)
1345 call accel_set_kernel_arg(kernel_copy_complex_to_real, 2, log2(int(this%pack_size_real(1), int32)))
1346 call accel_set_kernel_arg(kernel_copy_complex_to_real, 3, dest%ff_device)
1347 call accel_set_kernel_arg(kernel_copy_complex_to_real, 4, log2(int(dest%pack_size_real(1), int32)))
1348
1349 ! Compute the grid (extend to another dimensions if the size of the problem is too big)
1350 call accel_grid_size_extend_dim(int(np, int64), dest%pack_size_real(1), gsizes, bsizes, kernel_copy_complex_to_real)
1351
1352 call accel_kernel_run(kernel_copy_complex_to_real, gsizes, bsizes)
1353
1354 if(.not. optional_default(async, .false.)) call accel_finish()
1355
1356 case (batch_packed)
1357 !$omp parallel do private(ist, ip)
1358 do ip = 1, np
1359 !$omp simd
1360 do ist = 1, dest%nst_linear
1361 dest%dff_pack(ist, ip) = real(this%zff_pack(ist, ip), real64)
1362 end do
1363 end do
1364 !$omp end parallel do
1365 case (batch_not_packed)
1366 !$omp parallel private(ist, ip)
1367 do ist = 1, dest%nst_linear
1368 !$omp do
1369 do ip = 1, np
1370 dest%dff_linear(ip, ist) = real(this%zff_linear(ip, ist), real64)
1371 end do
1372 !$omp end do nowait
1373 end do
1374 !$omp end parallel
1375 end select
1376 else if (this%type() == type_float) then
1377 ! copy real -> complex
1378 select case (this%status())
1379 case (batch_device_packed)
1380 call accel_set_kernel_arg(kernel_copy_real_to_complex, 0, np)
1381 call accel_set_kernel_arg(kernel_copy_real_to_complex, 1, this%ff_device)
1382 call accel_set_kernel_arg(kernel_copy_real_to_complex, 2, log2(int(this%pack_size_real(1), int32)))
1383 call accel_set_kernel_arg(kernel_copy_real_to_complex, 3, dest%ff_device)
1384 call accel_set_kernel_arg(kernel_copy_real_to_complex, 4, log2(int(dest%pack_size_real(1), int32)))
1385
1386 ! Compute the grid (extend to another dimensions if the size of the problem is too big)
1387 call accel_grid_size_extend_dim(int(np, int64), this%pack_size_real(1), gsizes, bsizes, kernel_copy_real_to_complex)
1388
1389 call accel_kernel_run(kernel_copy_real_to_complex, gsizes, bsizes)
1390
1391 if(.not. optional_default(async, .false.)) call accel_finish()
1392
1393 case (batch_packed)
1394 !$omp parallel do private(ist, ip)
1395 do ip = 1, np
1396 !$omp simd
1397 do ist = 1, dest%nst_linear
1398 dest%zff_pack(ist, ip) = cmplx(this%dff_pack(ist, ip), m_zero, real64)
1399 end do
1400 end do
1401 !$omp end parallel do
1402 case (batch_not_packed)
1403 !$omp parallel private(ist, ip)
1404 do ist = 1, dest%nst_linear
1405 !$omp do
1406 do ip = 1, np
1407 dest%zff_linear(ip, ist) = cmplx(this%dff_linear(ip, ist), m_zero, real64)
1408 end do
1409 !$omp end do nowait
1410 end do
1411 !$omp end parallel
1412 end select
1413 else
1414 message(1) = "Error! This should not happen."
1415 call messages_fatal(1)
1416 end if
1417
1418 call profiling_out("BATCH_COPY_DATA_TO")
1419 pop_sub(batch_copy_data_to)
1420 end subroutine batch_copy_data_to
1421
1422 ! --------------------------------------------------------------
1424 !
1425 subroutine batch_check_compatibility_with(this, target, only_check_dim, type_check)
1426 class(batch_t), intent(in) :: this
1427 class(batch_t), intent(in) :: target
1428 logical, optional, intent(in) :: only_check_dim
1429 logical, optional, intent(in) :: type_check
1430
1432
1433 if (optional_default(type_check, .true.)) then
1434 assert(this%type() == target%type())
1435 end if
1436 if (.not. optional_default(only_check_dim, .false.)) then
1437 assert(this%nst_linear == target%nst_linear)
1438 end if
1439 assert(this%status() == target%status())
1440 assert(this%dim == target%dim)
1441
1443
1444 end subroutine batch_check_compatibility_with
1445
1446!--------------------------------------------------------------
1449 subroutine batch_build_indices(this, st_start, st_end)
1450 class(batch_t), intent(inout) :: this
1451 integer, intent(in) :: st_start
1452 integer, intent(in) :: st_end
1453
1454 integer :: idim, ii, ist
1455
1456 push_sub(batch_build_indices)
1457
1458 do ist = st_start, st_end
1459 ! now we also populate the linear array
1460 do idim = 1, this%dim
1461 ii = this%dim*(ist - st_start) + idim
1462 this%ist_idim_index(ii, 1) = ist
1463 this%ist_idim_index(ii, 2) = idim
1464 end do
1465 this%ist(ist - st_start + 1) = ist
1466 end do
1467
1468 ! compute packed sizes
1469 this%pack_size(1) = pad_pow2(this%nst_linear)
1470 this%pack_size(2) = this%np
1471 if (accel_is_enabled()) this%pack_size(2) = accel_padded_size(this%pack_size(2))
1472
1473 this%pack_size_real = this%pack_size
1474 if (type_is_complex(this%type())) this%pack_size_real(1) = 2*this%pack_size_real(1)
1475
1476 pop_sub(batch_build_indices)
1477 end subroutine batch_build_indices
1478
1479
1480#include "real.F90"
1481#include "batch_inc.F90"
1482#include "undef.F90"
1483
1484#include "complex.F90"
1485#include "batch_inc.F90"
1486#include "undef.F90"
1487
1488#include "real32.F90"
1489#include "batch_inc.F90"
1490#include "undef.F90"
1491
1492#include "complex32.F90"
1493#include "batch_inc.F90"
1494#include "undef.F90"
1495
1496end module batch_oct_m
1497
1498!! Local Variables:
1499!! mode: f90
1500!! coding: utf-8
1501!! End:
initialize a batch with existing memory
Definition: batch.F90:296
double log2(double __x) __attribute__((__nothrow__
subroutine, public accel_free_buffer(this, async)
Definition: accel.F90:990
integer, parameter, public accel_mem_read_write
Definition: accel.F90:185
This module contains interfaces for routines in allocate_hardware_aware.c.
subroutine, public deallocate_hardware_aware(array, size)
This module implements batches of mesh functions.
Definition: batch.F90:135
type(type_t) pure function batch_type(this)
return the type of a batch
Definition: batch.F90:700
subroutine zbatch_pack_copy(this)
copy data from the unpacked to the packed arrays
Definition: batch.F90:2112
subroutine cbatch_init_with_memory_3(this, dim, st_start, st_end, psi)
initialize a batch with an rank-3 array of TYPE_CMPLX_SINGLE valued mesh functions psi.
Definition: batch.F90:2565
subroutine, public batch_write_packed_to_device(this, async)
Definition: batch.F90:1158
integer, parameter, public batch_not_packed
functions are stored in CPU memory, unpacked order
Definition: batch.F90:311
integer, parameter, public batch_device_packed
functions are stored in device memory in packed order
Definition: batch.F90:311
subroutine zbatch_init_with_memory_3(this, dim, st_start, st_end, psi)
initialize a batch with an rank-3 array of TYPE_CMPLX valued mesh functions psi.
Definition: batch.F90:1937
subroutine batch_check_compatibility_with(this, target, only_check_dim, type_check)
check whether two batches have compatible dimensions (and type)
Definition: batch.F90:1521
logical pure function batch_is_packed(this)
Definition: batch.F90:736
subroutine dbatch_unpack_copy(this)
copy data from the packed to the unpacked arrays
Definition: batch.F90:1835
subroutine cbatch_pack_copy(this)
copy data from the unpacked to the packed arrays
Definition: batch.F90:2740
subroutine dbatch_init_with_memory_1(this, psi)
initialize a batch with an rank-1 array of TYPE_FLOAT valued mesh functions psi.
Definition: batch.F90:1692
subroutine cbatch_init_with_memory_2(this, dim, st_start, st_end, psi)
initialize a batch with an rank-2 array of TYPE_CMPLX_SINGLE valued mesh functions psi.
Definition: batch.F90:2601
subroutine batch_write_unpacked_to_device(this)
Definition: batch.F90:969
subroutine batch_do_unpack(this, copy, force, async)
unpack a batch
Definition: batch.F90:869
subroutine batch_finish_unpack(this)
finish the unpacking if do_unpack() was called with async=.true.
Definition: batch.F90:955
subroutine zbatch_allocate_unpacked_host(this)
allocate host (CPU) memory for unpacked data of type TYPE_CMPLX
Definition: batch.F90:2023
subroutine batch_deallocate_packed_device(this)
release packed device memory
Definition: batch.F90:446
integer pure function batch_type_as_integer(this)
For debuging purpose only.
Definition: batch.F90:709
subroutine sbatch_unpack_copy(this)
copy data from the packed to the unpacked arrays
Definition: batch.F90:2459
subroutine batch_do_pack_generic(this, copy, async)
pack the data in a batch
Definition: batch.F90:760
integer function batch_inv_index(this, cind)
inverse index lookup
Definition: batch.F90:1208
subroutine dbatch_init_with_memory_2(this, dim, st_start, st_end, psi)
initialize a batch with an rank-2 array of TYPE_FLOAT valued mesh functions psi.
Definition: batch.F90:1663
subroutine batch_allocate_packed_host(this)
allocate host (CPU) memory for packed data
Definition: batch.F90:484
subroutine, public zbatch_init(this, dim, st_start, st_end, np, special, packed)
initialize a TYPE_CMPLX valued batch to given size without providing external memory
Definition: batch.F90:2073
subroutine zbatch_allocate_packed_host(this)
allocate host (CPU) memory for packed data of type TYPE_CMPLX
Definition: batch.F90:2049
subroutine batch_clone_to(this, dest, pack, copy_data, new_np, special, dest_type)
clone a batch to a new batch
Definition: batch.F90:567
subroutine cbatch_allocate_unpacked_host(this)
allocate host (CPU) memory for unpacked data of type TYPE_CMPLX_SINGLE
Definition: batch.F90:2651
subroutine batch_remote_access_stop(this, rma_win)
stop the remote access to the batch
Definition: batch.F90:1325
subroutine sbatch_allocate_unpacked_host(this)
allocate host (CPU) memory for unpacked data of type TYPE_FLOAT_SINGLE
Definition: batch.F90:2337
subroutine batch_read_device_to_unpacked(this)
Definition: batch.F90:1066
subroutine zbatch_init_with_memory_1(this, psi)
initialize a batch with an rank-1 array of TYPE_CMPLX valued mesh functions psi.
Definition: batch.F90:2002
subroutine, public sbatch_init(this, dim, st_start, st_end, np, special, packed)
initialize a TYPE_FLOAT_SINGLE valued batch to given size without providing external memory
Definition: batch.F90:2387
subroutine sbatch_pack_copy(this)
copy data from the unpacked to the packed arrays
Definition: batch.F90:2426
subroutine dbatch_allocate_packed_host(this)
allocate host (CPU) memory for packed data of type TYPE_FLOAT
Definition: batch.F90:1739
subroutine batch_clone_to_array(this, dest, n_batches, pack, copy_data, new_np, special, dest_type)
Definition: batch.F90:595
subroutine batch_allocate_packed_device(this)
allocate device (GPU) memory for packed data
Definition: batch.F90:507
subroutine batch_build_indices(this, st_start, st_end)
build the index ist(:) and ist_idim_index(:,:) and set pack_size
Definition: batch.F90:1545
integer pure function batch_ist_idim_to_linear(this, cind)
direct index lookup
Definition: batch.F90:1225
integer, parameter gpu_pack_max_buffer_size
this value controls the size (in number of wave-functions) of the buffer used to copy states to the G...
Definition: batch.F90:316
subroutine batch_do_pack_target(this, target, copy, async, cpu_only)
pack the data in a batch
Definition: batch.F90:791
subroutine sbatch_init_with_memory_1(this, psi)
initialize a batch with an rank-1 array of TYPE_FLOAT_SINGLE valued mesh functions psi.
Definition: batch.F90:2316
integer pure function batch_linear_to_ist(this, linear_index)
get state index ist from linear (combined dim and nst) index
Definition: batch.F90:1243
subroutine batch_copy_to(this, dest, pack, copy_data, new_np, special, dest_type)
make a copy of a batch
Definition: batch.F90:631
subroutine, public batch_read_device_to_packed(this, async)
Definition: batch.F90:1181
subroutine cbatch_unpack_copy(this)
copy data from the packed to the unpacked arrays
Definition: batch.F90:2773
subroutine dbatch_init_with_memory_3(this, dim, st_start, st_end, psi)
initialize a batch with an rank-3 array of TYPE_FLOAT valued mesh functions psi.
Definition: batch.F90:1627
subroutine cbatch_init_with_memory_1(this, psi)
initialize a batch with an rank-1 array of TYPE_CMPLX_SINGLE valued mesh functions psi.
Definition: batch.F90:2630
subroutine batch_allocate_unpacked_host(this)
allocate host (CPU) memory for unpacked data
Definition: batch.F90:461
subroutine, public cbatch_init(this, dim, st_start, st_end, np, special, packed)
initialize a TYPE_CMPLX_SINGLE valued batch to given size without providing external memory
Definition: batch.F90:2701
subroutine batch_init_empty(this, dim, nst, np)
initialize an empty batch
Definition: batch.F90:525
subroutine, public dbatch_init(this, dim, st_start, st_end, np, special, packed)
initialize a TYPE_FLOAT valued batch to given size without providing external memory
Definition: batch.F90:1763
subroutine zbatch_init_with_memory_2(this, dim, st_start, st_end, psi)
initialize a batch with an rank-2 array of TYPE_CMPLX valued mesh functions psi.
Definition: batch.F90:1973
integer pure function batch_linear_to_idim(this, linear_index)
extract idim from linear index
Definition: batch.F90:1254
subroutine batch_remote_access_start(this, mpi_grp, rma_win)
start remote access to a batch on another node
Definition: batch.F90:1272
subroutine sbatch_allocate_packed_host(this)
allocate host (CPU) memory for packed data of type TYPE_FLOAT_SINGLE
Definition: batch.F90:2363
subroutine batch_copy_data_to(this, np, dest, async)
copy data to another batch.
Definition: batch.F90:1344
subroutine dbatch_allocate_unpacked_host(this)
allocate host (CPU) memory for unpacked data of type TYPE_FLOAT
Definition: batch.F90:1713
subroutine dbatch_pack_copy(this)
copy data from the unpacked to the packed arrays
Definition: batch.F90:1802
subroutine cbatch_allocate_packed_host(this)
allocate host (CPU) memory for packed data of type TYPE_CMPLX_SINGLE
Definition: batch.F90:2677
subroutine sbatch_init_with_memory_2(this, dim, st_start, st_end, psi)
initialize a batch with an rank-2 array of TYPE_FLOAT_SINGLE valued mesh functions psi.
Definition: batch.F90:2287
subroutine sbatch_init_with_memory_3(this, dim, st_start, st_end, psi)
initialize a batch with an rank-3 array of TYPE_FLOAT_SINGLE valued mesh functions psi.
Definition: batch.F90:2251
integer pure function batch_status(this)
return the status of a batch
Definition: batch.F90:728
subroutine batch_deallocate_unpacked_host(this)
release unpacked host memory
Definition: batch.F90:368
integer, parameter, public batch_packed
functions are stored in CPU memory, in transposed (packed) order
Definition: batch.F90:311
subroutine batch_deallocate_packed_host(this)
release packed host memory
Definition: batch.F90:411
integer(int64) function batch_pack_total_size(this)
Definition: batch.F90:744
subroutine batch_end(this, copy)
finalize a batch and release allocated memory, if necessary
Definition: batch.F90:330
subroutine zbatch_unpack_copy(this)
copy data from the packed to the unpacked arrays
Definition: batch.F90:2145
This module contains interfaces for BLAS routines You should not use these routines directly....
Definition: blas.F90:120
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
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
type(type_t), parameter, public type_cmplx_single
Definition: types.F90:142
type(type_t), parameter, public type_float_single
Definition: types.F90:141
type(type_t), parameter, public type_cmplx
Definition: types.F90:137
type(type_t), parameter, public type_float
Definition: types.F90:136
logical pure function, public type_is_single(this)
Definition: types.F90:194
type(type_t), parameter, public type_none
Definition: types.F90:135
Class defining batches of mesh functions.
Definition: batch.F90:164
int true(void)