15 USE dbcsr_api,
ONLY: dbcsr_type, dbcsr_get_info, dbcsr_distribution_type, dbcsr_distribution_get
20 dbm_distribution_obj, dbm_type
29 dbt_tas_type, dbt_tas_distribution_type, dbt_tas_split_info, dbt_tas_mm_storage
45 #include "../base/base_uses.f90"
49 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'dbt_types'
62 dbt_distribution_type, &
93 dbt_contraction_storage, &
97 TYPE(nd_to_2d_mapping) :: nd_index_grid
98 TYPE(mp_cart_type) :: mp_comm_2d
99 TYPE(dbt_tas_split_info),
ALLOCATABLE :: tas_split_info
100 INTEGER :: nproc = -1
103 TYPE dbt_contraction_storage
104 REAL(dp) :: nsplit_avg = 0.0_dp
105 INTEGER :: ibatch = -1
106 TYPE(array_list) :: batch_ranges
107 LOGICAL :: static = .false.
111 TYPE(dbt_tas_type),
POINTER :: matrix_rep => null()
112 TYPE(nd_to_2d_mapping) :: nd_index_blk
113 TYPE(nd_to_2d_mapping) :: nd_index
114 TYPE(array_list) :: blk_sizes
115 TYPE(array_list) :: blk_offsets
116 TYPE(array_list) :: nd_dist
117 TYPE(dbt_pgrid_type) :: pgrid
118 TYPE(array_list) :: blks_local
119 INTEGER,
DIMENSION(:),
ALLOCATABLE :: nblks_local
120 INTEGER,
DIMENSION(:),
ALLOCATABLE :: nfull_local
121 LOGICAL :: valid = .false.
122 LOGICAL :: owns_matrix = .false.
123 CHARACTER(LEN=default_string_length) :: name =
""
125 INTEGER,
POINTER :: refcount => null()
126 TYPE(dbt_contraction_storage),
ALLOCATABLE :: contraction_storage
129 TYPE dbt_distribution_type
130 TYPE(dbt_tas_distribution_type) :: dist
131 TYPE(dbt_pgrid_type) :: pgrid
132 TYPE(array_list) :: nd_dist
134 INTEGER,
POINTER :: refcount => null()
145 TYPE,
EXTENDS(dbt_tas_distribution) :: dbt_tas_dist_t
146 INTEGER,
DIMENSION(:),
ALLOCATABLE :: dims
147 INTEGER,
DIMENSION(:),
ALLOCATABLE :: dims_grid
148 TYPE(array_list) :: nd_dist
150 PROCEDURE :: dist => tas_dist_t
151 PROCEDURE :: rowcols => tas_rowcols_t
159 TYPE,
EXTENDS(dbt_tas_rowcol_data) :: dbt_tas_blk_size_t
160 INTEGER,
DIMENSION(:),
ALLOCATABLE :: dims
161 TYPE(array_list) :: blk_size
163 PROCEDURE :: data => tas_blk_size_t
167 MODULE PROCEDURE dbt_create_new
168 MODULE PROCEDURE dbt_create_template
169 MODULE PROCEDURE dbt_create_matrix
172 INTERFACE dbt_tas_dist_t
173 MODULE PROCEDURE new_dbt_tas_dist_t
176 INTERFACE dbt_tas_blk_size_t
177 MODULE PROCEDURE new_dbt_tas_blk_size_t
191 FUNCTION new_dbt_tas_dist_t(nd_dist, map_blks, map_grid, which_dim)
192 TYPE(array_list),
INTENT(IN) :: nd_dist
193 TYPE(nd_to_2d_mapping),
INTENT(IN) :: map_blks, map_grid
194 INTEGER,
INTENT(IN) :: which_dim
196 TYPE(dbt_tas_dist_t) :: new_dbt_tas_dist_t
197 INTEGER,
DIMENSION(2) :: grid_dims
198 INTEGER(KIND=int_8),
DIMENSION(2) :: matrix_dims
199 INTEGER,
DIMENSION(:),
ALLOCATABLE :: index_map
201 IF (which_dim == 1)
THEN
205 dims_2d_i8=matrix_dims, &
207 dims1_2d=new_dbt_tas_dist_t%dims)
211 dims1_2d=new_dbt_tas_dist_t%dims_grid)
212 ELSEIF (which_dim == 2)
THEN
216 dims_2d_i8=matrix_dims, &
218 dims2_2d=new_dbt_tas_dist_t%dims)
222 dims2_2d=new_dbt_tas_dist_t%dims_grid)
224 cpabort(
"Unknown value for which_dim")
227 new_dbt_tas_dist_t%nd_dist =
array_sublist(nd_dist, index_map)
228 new_dbt_tas_dist_t%nprowcol = grid_dims(which_dim)
229 new_dbt_tas_dist_t%nmrowcol = matrix_dims(which_dim)
235 FUNCTION tas_dist_t(t, rowcol)
236 CLASS(dbt_tas_dist_t),
INTENT(IN) :: t
237 INTEGER(KIND=int_8),
INTENT(IN) :: rowcol
238 INTEGER,
DIMENSION(4) :: ind_blk
239 INTEGER,
DIMENSION(4) :: dist_blk
240 INTEGER :: tas_dist_t
250 FUNCTION tas_rowcols_t(t, dist)
251 CLASS(dbt_tas_dist_t),
INTENT(IN) :: t
252 INTEGER,
INTENT(IN) :: dist
253 INTEGER(KIND=int_8),
DIMENSION(:),
ALLOCATABLE :: tas_rowcols_t
254 INTEGER,
DIMENSION(4) :: dist_blk
255 INTEGER,
DIMENSION(:),
ALLOCATABLE :: dist_1, dist_2, dist_3, dist_4, blks_1, blks_2, blks_3, blks_4, blks_tmp, nd_ind
256 INTEGER :: i_1, i_2, i_3, i_4, i, iblk, iblk_count, nblks
257 INTEGER(KIND=int_8) :: nrowcols
258 TYPE(array_list) :: blks
262 IF (
SIZE(t%dims) == 1)
THEN
265 IF (
SIZE(t%dims) == 2)
THEN
268 IF (
SIZE(t%dims) == 3)
THEN
269 CALL get_arrays(t%nd_dist, dist_1, dist_2, dist_3)
271 IF (
SIZE(t%dims) == 4)
THEN
272 CALL get_arrays(t%nd_dist, dist_1, dist_2, dist_3, dist_4)
275 IF (
SIZE(t%dims) .GE. 1)
THEN
277 ALLOCATE (blks_tmp(nblks))
280 IF (dist_1(iblk) == dist_blk(1))
THEN
281 iblk_count = iblk_count + 1
282 blks_tmp(iblk_count) = iblk
285 ALLOCATE (blks_1(iblk_count))
286 blks_1(:) = blks_tmp(:iblk_count)
287 DEALLOCATE (blks_tmp)
289 IF (
SIZE(t%dims) .GE. 2)
THEN
291 ALLOCATE (blks_tmp(nblks))
294 IF (dist_2(iblk) == dist_blk(2))
THEN
295 iblk_count = iblk_count + 1
296 blks_tmp(iblk_count) = iblk
299 ALLOCATE (blks_2(iblk_count))
300 blks_2(:) = blks_tmp(:iblk_count)
301 DEALLOCATE (blks_tmp)
303 IF (
SIZE(t%dims) .GE. 3)
THEN
305 ALLOCATE (blks_tmp(nblks))
308 IF (dist_3(iblk) == dist_blk(3))
THEN
309 iblk_count = iblk_count + 1
310 blks_tmp(iblk_count) = iblk
313 ALLOCATE (blks_3(iblk_count))
314 blks_3(:) = blks_tmp(:iblk_count)
315 DEALLOCATE (blks_tmp)
317 IF (
SIZE(t%dims) .GE. 4)
THEN
319 ALLOCATE (blks_tmp(nblks))
322 IF (dist_4(iblk) == dist_blk(4))
THEN
323 iblk_count = iblk_count + 1
324 blks_tmp(iblk_count) = iblk
327 ALLOCATE (blks_4(iblk_count))
328 blks_4(:) = blks_tmp(:iblk_count)
329 DEALLOCATE (blks_tmp)
332 IF (
SIZE(t%dims) == 1)
THEN
335 IF (
SIZE(t%dims) == 2)
THEN
338 IF (
SIZE(t%dims) == 3)
THEN
341 IF (
SIZE(t%dims) == 4)
THEN
346 ALLOCATE (tas_rowcols_t(nrowcols))
348 IF (
SIZE(t%dims) == 1)
THEN
351 DO i_1 = 1,
SIZE(blks_1)
358 IF (
SIZE(t%dims) == 2)
THEN
361 DO i_1 = 1,
SIZE(blks_1)
362 DO i_2 = 1,
SIZE(blks_2)
370 IF (
SIZE(t%dims) == 3)
THEN
373 DO i_1 = 1,
SIZE(blks_1)
374 DO i_2 = 1,
SIZE(blks_2)
375 DO i_3 = 1,
SIZE(blks_3)
384 IF (
SIZE(t%dims) == 4)
THEN
387 DO i_1 = 1,
SIZE(blks_1)
388 DO i_2 = 1,
SIZE(blks_2)
389 DO i_3 = 1,
SIZE(blks_3)
390 DO i_4 = 1,
SIZE(blks_4)
411 FUNCTION new_dbt_tas_blk_size_t(blk_size, map_blks, which_dim)
412 TYPE(array_list),
INTENT(IN) :: blk_size
413 TYPE(nd_to_2d_mapping),
INTENT(IN) :: map_blks
414 INTEGER,
INTENT(IN) :: which_dim
415 INTEGER(KIND=int_8),
DIMENSION(2) :: matrix_dims
416 INTEGER,
DIMENSION(:),
ALLOCATABLE :: index_map
417 TYPE(dbt_tas_blk_size_t) :: new_dbt_tas_blk_size_t
419 IF (which_dim == 1)
THEN
423 dims_2d_i8=matrix_dims, &
425 dims1_2d=new_dbt_tas_blk_size_t%dims)
426 ELSEIF (which_dim == 2)
THEN
430 dims_2d_i8=matrix_dims, &
432 dims2_2d=new_dbt_tas_blk_size_t%dims)
434 cpabort(
"Unknown value for which_dim")
437 new_dbt_tas_blk_size_t%blk_size =
array_sublist(blk_size, index_map)
438 new_dbt_tas_blk_size_t%nmrowcol = matrix_dims(which_dim)
440 new_dbt_tas_blk_size_t%nfullrowcol = product(int(
sum_of_arrays(new_dbt_tas_blk_size_t%blk_size), &
447 FUNCTION tas_blk_size_t(t, rowcol)
448 CLASS(dbt_tas_blk_size_t),
INTENT(IN) :: t
449 INTEGER(KIND=int_8),
INTENT(IN) :: rowcol
450 INTEGER :: tas_blk_size_t
451 INTEGER,
DIMENSION(SIZE(t%dims)) :: ind_blk
452 INTEGER,
DIMENSION(SIZE(t%dims)) :: blk_size
456 tas_blk_size_t = product(blk_size)
469 PURE FUNCTION accept_pdims_loadbalancing(pdims_avail, pdim, tdim, lb_ratio)
470 INTEGER,
INTENT(IN) :: pdims_avail
471 INTEGER,
INTENT(IN) :: pdim
472 INTEGER,
INTENT(IN) :: tdim
473 REAL(dp),
INTENT(IN) :: lb_ratio
474 LOGICAL :: accept_pdims_loadbalancing
476 accept_pdims_loadbalancing = .false.
477 IF (mod(pdims_avail, pdim) == 0)
THEN
478 IF (real(tdim, dp)*lb_ratio < real(pdim, dp))
THEN
479 IF (mod(tdim, pdim) == 0) accept_pdims_loadbalancing = .true.
481 accept_pdims_loadbalancing = .true.
498 INTEGER,
INTENT(IN) :: nodes
499 INTEGER,
DIMENSION(:),
INTENT(INOUT) :: dims
500 INTEGER,
DIMENSION(:),
INTENT(IN) :: tensor_dims
501 REAL(
dp),
INTENT(IN),
OPTIONAL :: lb_ratio
503 INTEGER,
DIMENSION(:),
ALLOCATABLE :: tensor_dims_sorted, sort_indices, dims_store
504 REAL(
dp),
DIMENSION(:),
ALLOCATABLE :: sort_key
505 INTEGER :: pdims_rem, idim, pdim
506 REAL(
dp) :: lb_ratio_prv
508 IF (
PRESENT(lb_ratio))
THEN
509 lb_ratio_prv = lb_ratio
511 lb_ratio_prv = 0.1_dp
514 ALLOCATE (dims_store, source=dims)
517 IF (any(dims == 0))
THEN
522 ALLOCATE (sort_key(
SIZE(tensor_dims)))
523 sort_key(:) = real(tensor_dims,
dp)/dims
525 ALLOCATE (tensor_dims_sorted, source=tensor_dims)
526 ALLOCATE (sort_indices(
SIZE(sort_key)))
527 CALL sort(sort_key,
SIZE(sort_key), sort_indices)
528 tensor_dims_sorted(:) = tensor_dims_sorted(sort_indices)
529 dims(:) = dims(sort_indices)
534 DO idim = 1,
SIZE(tensor_dims_sorted)
535 IF (.NOT. accept_pdims_loadbalancing(pdims_rem, dims(idim), tensor_dims_sorted(idim), lb_ratio_prv))
THEN
536 pdim = tensor_dims_sorted(idim)
537 DO WHILE (.NOT. accept_pdims_loadbalancing(pdims_rem, pdim, tensor_dims_sorted(idim), lb_ratio_prv))
541 pdims_rem = pdims_rem/dims(idim)
543 IF (idim .NE.
SIZE(tensor_dims_sorted))
THEN
546 ELSEIF (lb_ratio_prv < 0.5_dp)
THEN
559 pdims_rem = pdims_rem/dims(idim)
563 dims(sort_indices) = dims
594 CLASS(mp_comm_type),
INTENT(IN) :: mp_comm
595 INTEGER,
DIMENSION(:),
INTENT(INOUT) :: dims
596 TYPE(dbt_pgrid_type),
INTENT(OUT) :: pgrid
597 INTEGER,
DIMENSION(:),
INTENT(IN) :: map1_2d, map2_2d
598 INTEGER,
DIMENSION(:),
INTENT(IN),
OPTIONAL :: tensor_dims
599 INTEGER,
INTENT(IN),
OPTIONAL :: nsplit, dimsplit
600 INTEGER,
DIMENSION(2) :: pdims_2d
601 INTEGER :: nproc, ndims, handle
602 TYPE(dbt_tas_split_info) :: info
604 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dbt_pgrid_create_expert'
606 CALL timeset(routinen, handle)
610 nproc = mp_comm%num_pe
611 IF (any(dims == 0))
THEN
612 IF (.NOT.
PRESENT(tensor_dims))
THEN
620 CALL pgrid%mp_comm_2d%create(mp_comm, 2, pdims_2d)
622 IF (
PRESENT(nsplit))
THEN
623 cpassert(
PRESENT(dimsplit))
625 ALLOCATE (pgrid%tas_split_info, source=info)
631 CALL timestop(handle)
651 FUNCTION dbt_nd_mp_comm(comm_2d, map1_2d, map2_2d, dims_nd, dims1_nd, dims2_nd, pdims_2d, tdims, &
653 CLASS(mp_comm_type),
INTENT(IN) :: comm_2d
654 INTEGER,
DIMENSION(:),
INTENT(IN) :: map1_2d, map2_2d
655 INTEGER,
DIMENSION(SIZE(map1_2d) + SIZE(map2_2d)), &
656 INTENT(IN),
OPTIONAL :: dims_nd
657 INTEGER,
DIMENSION(SIZE(map1_2d)),
INTENT(IN),
OPTIONAL :: dims1_nd
658 INTEGER,
DIMENSION(SIZE(map2_2d)),
INTENT(IN),
OPTIONAL :: dims2_nd
659 INTEGER,
DIMENSION(2),
INTENT(IN),
OPTIONAL :: pdims_2d
660 INTEGER,
DIMENSION(SIZE(map1_2d) + SIZE(map2_2d)), &
661 INTENT(IN),
OPTIONAL :: tdims
662 INTEGER,
INTENT(IN),
OPTIONAL :: nsplit, dimsplit
663 INTEGER :: ndim1, ndim2
664 INTEGER,
DIMENSION(2) :: dims_2d
666 INTEGER,
DIMENSION(SIZE(map1_2d)) :: dims1_nd_prv
667 INTEGER,
DIMENSION(SIZE(map2_2d)) :: dims2_nd_prv
668 INTEGER,
DIMENSION(SIZE(map1_2d) + SIZE(map2_2d)) :: dims_nd_prv
670 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dbt_nd_mp_comm'
673 CALL timeset(routinen, handle)
675 ndim1 =
SIZE(map1_2d); ndim2 =
SIZE(map2_2d)
677 IF (
PRESENT(pdims_2d))
THEN
678 dims_2d(:) = pdims_2d
682 SELECT TYPE (comm_2d)
683 CLASS IS (mp_cart_type)
684 dims_2d = comm_2d%num_pe_cart
686 CALL cp_abort(__location__,
"If the argument pdims_2d is not given, the "// &
687 "communicator comm_2d must be of class mp_cart_type.")
691 IF (.NOT.
PRESENT(dims_nd))
THEN
692 dims1_nd_prv = 0; dims2_nd_prv = 0
693 IF (
PRESENT(dims1_nd))
THEN
694 dims1_nd_prv(:) = dims1_nd
697 IF (
PRESENT(tdims))
THEN
704 IF (
PRESENT(dims2_nd))
THEN
705 dims2_nd_prv(:) = dims2_nd
707 IF (
PRESENT(tdims))
THEN
713 dims_nd_prv(map1_2d) = dims1_nd_prv
714 dims_nd_prv(map2_2d) = dims2_nd_prv
716 cpassert(product(dims_nd(map1_2d)) == dims_2d(1))
717 cpassert(product(dims_nd(map2_2d)) == dims_2d(2))
718 dims_nd_prv = dims_nd
722 tensor_dims=tdims, map1_2d=map1_2d, map2_2d=map2_2d, nsplit=nsplit, dimsplit=dimsplit)
724 CALL timestop(handle)
733 TYPE(mp_comm_type),
INTENT(INOUT) :: mp_comm
744 SUBROUTINE dbt_pgrid_remap(pgrid_in, map1_2d, map2_2d, pgrid_out)
745 TYPE(dbt_pgrid_type),
INTENT(IN) :: pgrid_in
746 INTEGER,
DIMENSION(:),
INTENT(IN) :: map1_2d, map2_2d
747 TYPE(dbt_pgrid_type),
INTENT(OUT) :: pgrid_out
748 INTEGER,
DIMENSION(:),
ALLOCATABLE :: dims
749 INTEGER,
DIMENSION(ndims_mapping_row(pgrid_in%nd_index_grid)) :: map1_2d_old
750 INTEGER,
DIMENSION(ndims_mapping_column(pgrid_in%nd_index_grid)) :: map2_2d_old
752 ALLOCATE (dims(
SIZE(map1_2d) +
SIZE(map2_2d)))
753 CALL dbt_get_mapping_info(pgrid_in%nd_index_grid, dims_nd=dims, map1_2d=map1_2d_old, map2_2d=map2_2d_old)
756 IF (
ALLOCATED(pgrid_in%tas_split_info))
THEN
757 ALLOCATE (pgrid_out%tas_split_info, source=pgrid_in%tas_split_info)
768 TYPE(dbt_pgrid_type),
INTENT(IN) :: pgrid
769 INTEGER,
DIMENSION(ndims_mapping(pgrid%nd_index_grid)),
INTENT(OUT) :: dims
770 INTEGER,
DIMENSION(ndims_mapping(pgrid%nd_index_grid)),
INTENT(OUT) :: task_coor
771 INTEGER,
DIMENSION(2) :: task_coor_2d
773 task_coor_2d = pgrid%mp_comm_2d%mepos_cart
787 TYPE(dbt_distribution_type),
INTENT(OUT) :: dist
788 TYPE(dbt_pgrid_type),
INTENT(IN) :: pgrid
789 INTEGER,
DIMENSION(:),
INTENT(IN) :: map1_2d
790 INTEGER,
DIMENSION(:),
INTENT(IN) :: map2_2d
791 INTEGER,
DIMENSION(:),
INTENT(IN),
OPTIONAL :: nd_dist_1, nd_dist_2, nd_dist_3, nd_dist_4
792 LOGICAL,
INTENT(IN),
OPTIONAL :: own_comm
794 TYPE(mp_cart_type) :: comm_2d
795 INTEGER,
DIMENSION(2) :: pdims_2d_check, &
797 INTEGER,
DIMENSION(SIZE(map1_2d) + SIZE(map2_2d)) :: dims, nblks_nd, task_coor
798 TYPE(array_list) :: nd_dist
799 TYPE(nd_to_2d_mapping) :: map_blks, map_grid
801 TYPE(dbt_tas_dist_t) :: row_dist_obj, col_dist_obj
802 TYPE(dbt_pgrid_type) :: pgrid_prv
803 LOGICAL :: need_pgrid_remap
804 INTEGER,
DIMENSION(ndims_mapping_row(pgrid%nd_index_grid)) :: map1_2d_check
805 INTEGER,
DIMENSION(ndims_mapping_column(pgrid%nd_index_grid)) :: map2_2d_check
806 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dbt_distribution_new_expert'
808 CALL timeset(routinen, handle)
809 ndims =
SIZE(map1_2d) +
SIZE(map2_2d)
810 cpassert(ndims .GE. 2 .AND. ndims .LE. 4)
812 CALL create_array_list(nd_dist, ndims, nd_dist_1, nd_dist_2, nd_dist_3, nd_dist_4)
816 need_pgrid_remap = .true.
817 IF (
PRESENT(own_comm))
THEN
820 IF (.NOT.
array_eq_i(map1_2d_check, map1_2d) .OR. .NOT.
array_eq_i(map2_2d_check, map2_2d))
THEN
821 cpabort(
"map1_2d / map2_2d are not consistent with pgrid")
824 need_pgrid_remap = .false.
828 IF (need_pgrid_remap)
CALL dbt_pgrid_remap(pgrid, map1_2d, map2_2d, pgrid_prv)
839 row_dist_obj = dbt_tas_dist_t(nd_dist, map_blks, map_grid, 1)
840 col_dist_obj = dbt_tas_dist_t(nd_dist, map_blks, map_grid, 2)
844 comm_2d = pgrid_prv%mp_comm_2d
846 pdims_2d_check = comm_2d%num_pe_cart
847 IF (any(pdims_2d_check .NE. pdims_2d))
THEN
848 cpabort(
"inconsistent process grid dimensions")
851 IF (
ALLOCATED(pgrid_prv%tas_split_info))
THEN
855 ALLOCATE (pgrid_prv%tas_split_info, source=dist%dist%info)
859 dist%nd_dist = nd_dist
860 dist%pgrid = pgrid_prv
862 ALLOCATE (dist%refcount)
864 CALL timestop(handle)
868 INTEGER,
INTENT(IN),
DIMENSION(:) :: arr1
869 INTEGER,
INTENT(IN),
DIMENSION(:) :: arr2
873 IF (
SIZE(arr1) .EQ.
SIZE(arr2))
array_eq_i = all(arr1 == arr2)
886 TYPE(dbt_distribution_type),
INTENT(OUT) :: dist
887 TYPE(dbt_pgrid_type),
INTENT(IN) :: pgrid
888 INTEGER,
DIMENSION(:),
INTENT(IN),
OPTIONAL :: nd_dist_1, nd_dist_2, nd_dist_3, nd_dist_4
889 INTEGER,
DIMENSION(ndims_mapping_row(pgrid%nd_index_grid)) :: map1_2d
890 INTEGER,
DIMENSION(ndims_mapping_column(pgrid%nd_index_grid)) :: map2_2d
905 TYPE(dbt_pgrid_type),
INTENT(INOUT) :: pgrid
906 LOGICAL,
INTENT(IN),
OPTIONAL :: keep_comm
907 LOGICAL :: keep_comm_prv
908 IF (
PRESENT(keep_comm))
THEN
909 keep_comm_prv = keep_comm
911 keep_comm_prv = .false.
913 IF (.NOT. keep_comm_prv)
CALL pgrid%mp_comm_2d%free()
915 IF (
ALLOCATED(pgrid%tas_split_info) .AND. .NOT. keep_comm_prv)
THEN
917 DEALLOCATE (pgrid%tas_split_info)
926 TYPE(dbt_distribution_type),
INTENT(INOUT) :: dist
928 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dbt_distribution_destroy'
931 CALL timeset(routinen, handle)
936 IF (.NOT.
ASSOCIATED(dist%refcount))
THEN
938 ELSEIF (dist%refcount < 1)
THEN
943 cpabort(
"can not destroy non-existing tensor distribution")
946 dist%refcount = dist%refcount - 1
948 IF (dist%refcount == 0)
THEN
950 DEALLOCATE (dist%refcount)
955 CALL timestop(handle)
963 SUBROUTINE dbt_distribution_hold(dist)
964 TYPE(dbt_distribution_type),
INTENT(IN) :: dist
965 INTEGER,
POINTER :: ref
967 IF (dist%refcount < 1)
THEN
968 cpabort(
"can not hold non-existing tensor distribution")
980 TYPE(dbt_type),
INTENT(IN) ::
tensor
992 SUBROUTINE dbt_distribution_remap(dist_in, map1_2d, map2_2d, dist_out)
993 TYPE(dbt_distribution_type),
INTENT(IN) :: dist_in
994 INTEGER,
DIMENSION(:),
INTENT(IN) :: map1_2d, map2_2d
995 TYPE(dbt_distribution_type),
INTENT(OUT) :: dist_out
996 INTEGER,
DIMENSION(:),
ALLOCATABLE :: dist_1, dist_2, dist_3, dist_4
998 ndims =
SIZE(map1_2d) +
SIZE(map2_2d)
1003 IF (ndims == 2)
THEN
1004 CALL get_arrays(dist_in%nd_dist, dist_1, dist_2)
1007 IF (ndims == 3)
THEN
1008 CALL get_arrays(dist_in%nd_dist, dist_1, dist_2, dist_3)
1011 IF (ndims == 4)
THEN
1012 CALL get_arrays(dist_in%nd_dist, dist_1, dist_2, dist_3, dist_4)
1027 SUBROUTINE dbt_create_new(tensor, name, dist, map1_2d, map2_2d, &
1028 blk_size_1, blk_size_2, blk_size_3, blk_size_4)
1029 TYPE(dbt_type),
INTENT(OUT) ::
tensor
1030 CHARACTER(len=*),
INTENT(IN) :: name
1031 TYPE(dbt_distribution_type),
INTENT(INOUT) :: dist
1032 INTEGER,
DIMENSION(:),
INTENT(IN) :: map1_2d
1033 INTEGER,
DIMENSION(:),
INTENT(IN) :: map2_2d
1034 INTEGER,
DIMENSION(:),
INTENT(IN),
OPTIONAL :: blk_size_1, blk_size_2, blk_size_3, blk_size_4
1036 INTEGER(KIND=int_8),
DIMENSION(2) :: dims_2d
1037 INTEGER,
DIMENSION(SIZE(map1_2d) + SIZE(map2_2d)) :: dims, pdims, task_coor
1038 TYPE(dbt_tas_blk_size_t) :: col_blk_size_obj, row_blk_size_obj
1039 TYPE(dbt_distribution_type) :: dist_new
1040 TYPE(array_list) :: blk_size, blks_local
1041 TYPE(nd_to_2d_mapping) :: map
1043 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dbt_create_new'
1044 INTEGER,
DIMENSION(:),
ALLOCATABLE :: blks_local_1, blks_local_2, blks_local_3, blks_local_4
1045 INTEGER,
DIMENSION(:),
ALLOCATABLE :: dist_1, dist_2, dist_3, dist_4
1046 INTEGER :: iblk_count, iblk
1047 INTEGER,
DIMENSION(:),
ALLOCATABLE :: nblks_local, nfull_local
1049 CALL timeset(routinen, handle)
1050 ndims =
SIZE(map1_2d) +
SIZE(map2_2d)
1051 CALL create_array_list(blk_size, ndims, blk_size_1, blk_size_2, blk_size_3, blk_size_4)
1057 row_blk_size_obj = dbt_tas_blk_size_t(blk_size, map, 1)
1058 col_blk_size_obj = dbt_tas_blk_size_t(blk_size, map, 2)
1060 CALL dbt_distribution_remap(dist, map1_2d, map2_2d, dist_new)
1062 ALLOCATE (
tensor%matrix_rep)
1063 CALL dbt_tas_create(matrix=
tensor%matrix_rep, &
1064 name=trim(name)//
" matrix", &
1065 dist=dist_new%dist, &
1066 row_blk_size=row_blk_size_obj, &
1067 col_blk_size=col_blk_size_obj)
1069 tensor%owns_matrix = .true.
1071 tensor%nd_index_blk = map
1080 tensor%blk_sizes = blk_size
1084 IF (ndims == 1)
THEN
1087 IF (ndims == 2)
THEN
1088 CALL get_arrays(dist_new%nd_dist, dist_1, dist_2)
1090 IF (ndims == 3)
THEN
1091 CALL get_arrays(dist_new%nd_dist, dist_1, dist_2, dist_3)
1093 IF (ndims == 4)
THEN
1094 CALL get_arrays(dist_new%nd_dist, dist_1, dist_2, dist_3, dist_4)
1097 ALLOCATE (nblks_local(ndims))
1098 ALLOCATE (nfull_local(ndims))
1100 IF (ndims .GE. 1)
THEN
1101 nblks_local(1) = count(dist_1 == task_coor(1))
1102 ALLOCATE (blks_local_1(nblks_local(1)))
1104 DO iblk = 1,
SIZE(dist_1)
1105 IF (dist_1(iblk) == task_coor(1))
THEN
1106 iblk_count = iblk_count + 1
1107 blks_local_1(iblk_count) = iblk
1108 nfull_local(1) = nfull_local(1) + blk_size_1(iblk)
1112 IF (ndims .GE. 2)
THEN
1113 nblks_local(2) = count(dist_2 == task_coor(2))
1114 ALLOCATE (blks_local_2(nblks_local(2)))
1116 DO iblk = 1,
SIZE(dist_2)
1117 IF (dist_2(iblk) == task_coor(2))
THEN
1118 iblk_count = iblk_count + 1
1119 blks_local_2(iblk_count) = iblk
1120 nfull_local(2) = nfull_local(2) + blk_size_2(iblk)
1124 IF (ndims .GE. 3)
THEN
1125 nblks_local(3) = count(dist_3 == task_coor(3))
1126 ALLOCATE (blks_local_3(nblks_local(3)))
1128 DO iblk = 1,
SIZE(dist_3)
1129 IF (dist_3(iblk) == task_coor(3))
THEN
1130 iblk_count = iblk_count + 1
1131 blks_local_3(iblk_count) = iblk
1132 nfull_local(3) = nfull_local(3) + blk_size_3(iblk)
1136 IF (ndims .GE. 4)
THEN
1137 nblks_local(4) = count(dist_4 == task_coor(4))
1138 ALLOCATE (blks_local_4(nblks_local(4)))
1140 DO iblk = 1,
SIZE(dist_4)
1141 IF (dist_4(iblk) == task_coor(4))
THEN
1142 iblk_count = iblk_count + 1
1143 blks_local_4(iblk_count) = iblk
1144 nfull_local(4) = nfull_local(4) + blk_size_4(iblk)
1149 IF (ndims == 1)
THEN
1152 IF (ndims == 2)
THEN
1155 IF (ndims == 3)
THEN
1158 IF (ndims == 4)
THEN
1159 CALL create_array_list(blks_local, 4, blks_local_1, blks_local_2, blks_local_3, blks_local_4)
1162 ALLOCATE (
tensor%nblks_local(ndims))
1163 ALLOCATE (
tensor%nfull_local(ndims))
1164 tensor%nblks_local(:) = nblks_local
1165 tensor%nfull_local(:) = nfull_local
1167 tensor%blks_local = blks_local
1169 tensor%nd_dist = dist_new%nd_dist
1170 tensor%pgrid = dist_new%pgrid
1172 CALL dbt_distribution_hold(dist_new)
1173 tensor%refcount => dist_new%refcount
1179 CALL timestop(handle)
1188 TYPE(dbt_type),
INTENT(IN) ::
tensor
1189 INTEGER,
POINTER :: ref
1191 IF (
tensor%refcount < 1)
THEN
1192 cpabort(
"can not hold non-existing tensor")
1204 TYPE(dbt_type),
INTENT(IN) ::
tensor
1216 TYPE(dbt_type),
INTENT(IN) ::
tensor
1227 TYPE(dbt_type),
INTENT(IN) ::
tensor
1238 TYPE(dbt_type),
INTENT(IN) ::
tensor
1239 INTEGER,
DIMENSION(ndims_tensor(tensor)), &
1243 dims =
tensor%nd_index%dims_nd
1250 SUBROUTINE dbt_create_template(tensor_in, tensor, name, dist, map1_2d, map2_2d)
1251 TYPE(dbt_type),
INTENT(INOUT) :: tensor_in
1252 TYPE(dbt_type),
INTENT(OUT) ::
tensor
1253 CHARACTER(len=*),
INTENT(IN),
OPTIONAL :: name
1254 TYPE(dbt_distribution_type), &
1255 INTENT(INOUT),
OPTIONAL :: dist
1256 INTEGER,
DIMENSION(:),
INTENT(IN), &
1257 OPTIONAL :: map1_2d, map2_2d
1259 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dbt_create_template'
1260 INTEGER,
DIMENSION(:),
ALLOCATABLE :: bsize_1, bsize_2, bsize_3, bsize_4
1261 INTEGER,
DIMENSION(:),
ALLOCATABLE :: map1_2d_prv, map2_2d_prv
1262 CHARACTER(len=default_string_length) :: name_prv
1263 TYPE(dbt_distribution_type) :: dist_prv
1265 CALL timeset(routinen, handle)
1267 IF (
PRESENT(dist) .OR.
PRESENT(map1_2d) .OR.
PRESENT(map2_2d))
THEN
1269 IF (
PRESENT(dist))
THEN
1274 IF (
PRESENT(map1_2d) .AND.
PRESENT(map2_2d))
THEN
1275 ALLOCATE (map1_2d_prv, source=map1_2d)
1276 ALLOCATE (map2_2d_prv, source=map2_2d)
1282 IF (
PRESENT(name))
THEN
1285 name_prv = tensor_in%name
1289 CALL get_arrays(tensor_in%blk_sizes, bsize_1)
1290 CALL dbt_create(
tensor, name_prv, dist_prv, map1_2d_prv, map2_2d_prv, &
1294 CALL get_arrays(tensor_in%blk_sizes, bsize_1, bsize_2)
1295 CALL dbt_create(
tensor, name_prv, dist_prv, map1_2d_prv, map2_2d_prv, &
1299 CALL get_arrays(tensor_in%blk_sizes, bsize_1, bsize_2, bsize_3)
1300 CALL dbt_create(
tensor, name_prv, dist_prv, map1_2d_prv, map2_2d_prv, &
1301 bsize_1, bsize_2, bsize_3)
1304 CALL get_arrays(tensor_in%blk_sizes, bsize_1, bsize_2, bsize_3, bsize_4)
1305 CALL dbt_create(
tensor, name_prv, dist_prv, map1_2d_prv, map2_2d_prv, &
1306 bsize_1, bsize_2, bsize_3, bsize_4)
1310 ALLOCATE (
tensor%matrix_rep)
1311 IF (.NOT.
PRESENT(name))
THEN
1312 CALL dbt_tas_create(tensor_in%matrix_rep,
tensor%matrix_rep, &
1313 name=trim(tensor_in%name)//
" matrix")
1315 CALL dbt_tas_create(tensor_in%matrix_rep,
tensor%matrix_rep, name=trim(name)//
" matrix")
1317 tensor%owns_matrix = .true.
1320 tensor%nd_index_blk = tensor_in%nd_index_blk
1321 tensor%nd_index = tensor_in%nd_index
1322 tensor%blk_sizes = tensor_in%blk_sizes
1323 tensor%blk_offsets = tensor_in%blk_offsets
1324 tensor%nd_dist = tensor_in%nd_dist
1325 tensor%blks_local = tensor_in%blks_local
1327 tensor%nblks_local(:) = tensor_in%nblks_local
1329 tensor%nfull_local(:) = tensor_in%nfull_local
1330 tensor%pgrid = tensor_in%pgrid
1332 tensor%refcount => tensor_in%refcount
1336 IF (
PRESENT(name))
THEN
1339 tensor%name = tensor_in%name
1342 CALL timestop(handle)
1349 SUBROUTINE dbt_create_matrix(matrix_in, tensor, order, name)
1350 TYPE(dbcsr_type),
INTENT(IN) :: matrix_in
1351 TYPE(dbt_type),
INTENT(OUT) ::
tensor
1352 INTEGER,
DIMENSION(2),
INTENT(IN),
OPTIONAL :: order
1353 CHARACTER(len=*),
INTENT(IN),
OPTIONAL :: name
1355 CHARACTER(len=default_string_length) :: name_in
1356 INTEGER,
DIMENSION(2) :: order_in
1357 TYPE(mp_comm_type) :: comm_2d
1358 TYPE(dbcsr_distribution_type) :: matrix_dist
1359 TYPE(dbt_distribution_type) :: dist
1360 INTEGER,
DIMENSION(:),
POINTER :: row_blk_size, col_blk_size
1361 INTEGER,
DIMENSION(:),
POINTER :: col_dist, row_dist
1362 INTEGER :: handle, comm_2d_handle
1363 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dbt_create_matrix'
1364 TYPE(dbt_pgrid_type) :: comm_nd
1365 INTEGER,
DIMENSION(2) :: pdims_2d
1367 CALL timeset(routinen, handle)
1369 NULLIFY (row_blk_size, col_blk_size, col_dist, row_dist)
1370 IF (
PRESENT(name))
THEN
1373 CALL dbcsr_get_info(matrix_in, name=name_in)
1376 IF (
PRESENT(order))
THEN
1382 CALL dbcsr_get_info(matrix_in, distribution=matrix_dist)
1383 CALL dbcsr_distribution_get(matrix_dist, group=comm_2d_handle, row_dist=row_dist, col_dist=col_dist, &
1384 nprows=pdims_2d(1), npcols=pdims_2d(2))
1385 CALL comm_2d%set_handle(comm_2d_handle)
1386 comm_nd =
dbt_nd_mp_comm(comm_2d, [order_in(1)], [order_in(2)], pdims_2d=pdims_2d)
1391 [order_in(1)], [order_in(2)], &
1392 row_dist, col_dist, own_comm=.true.)
1394 CALL dbcsr_get_info(matrix_in, row_blk_size=row_blk_size, col_blk_size=col_blk_size)
1396 CALL dbt_create_new(
tensor, name_in, dist, &
1397 [order_in(1)], [order_in(2)], &
1402 CALL timestop(handle)
1410 TYPE(dbt_type),
INTENT(INOUT) ::
tensor
1412 CHARACTER(LEN=*),
PARAMETER :: routinen =
'dbt_destroy'
1415 CALL timeset(routinen, handle)
1416 IF (
tensor%owns_matrix)
THEN
1418 DEALLOCATE (
tensor%matrix_rep)
1420 NULLIFY (
tensor%matrix_rep)
1422 tensor%owns_matrix = .false.
1435 IF (.NOT.
ASSOCIATED(
tensor%refcount))
THEN
1437 ELSEIF (
tensor%refcount < 1)
THEN
1442 cpabort(
"can not destroy non-existing tensor")
1447 IF (
tensor%refcount == 0)
THEN
1451 DEALLOCATE (
tensor%refcount)
1458 CALL timestop(handle)
1466 TYPE(dbt_type),
INTENT(IN) ::
tensor
1467 INTEGER,
DIMENSION(ndims_tensor(tensor)), &
1471 dims =
tensor%nd_index_blk%dims_nd
1479 TYPE(dbt_type),
INTENT(IN) ::
tensor
1480 INTEGER,
DIMENSION(ndims_tensor(tensor)), &
1482 INTEGER,
DIMENSION(ndims_tensor(tensor)), &
1483 INTENT(OUT) :: blk_size
1495 TYPE(dbt_type),
INTENT(IN) ::
tensor
1496 INTEGER,
DIMENSION(ndims_tensor(tensor)), &
1498 INTEGER,
DIMENSION(ndims_tensor(tensor)), &
1499 INTENT(OUT) :: blk_offset
1510 TYPE(dbt_type),
INTENT(IN) ::
tensor
1511 INTEGER,
DIMENSION(ndims_tensor(tensor)), &
1512 INTENT(IN) :: ind_nd
1513 INTEGER,
INTENT(OUT) :: processor
1515 INTEGER(KIND=int_8),
DIMENSION(2) :: ind_2d
1525 CLASS(mp_comm_type),
INTENT(IN) :: mp_comm
1526 INTEGER,
DIMENSION(:),
INTENT(INOUT) :: dims
1527 TYPE(dbt_pgrid_type),
INTENT(OUT) :: pgrid
1528 INTEGER,
DIMENSION(:),
INTENT(IN),
OPTIONAL :: tensor_dims
1529 INTEGER,
DIMENSION(:),
ALLOCATABLE :: map1_2d, map2_2d
1534 ALLOCATE (map1_2d(ndims/2))
1535 ALLOCATE (map2_2d(ndims - ndims/2))
1536 map1_2d(:) = (/(i, i=1,
SIZE(map1_2d))/)
1537 map2_2d(:) = (/(i, i=
SIZE(map1_2d) + 1,
SIZE(map1_2d) +
SIZE(map2_2d))/)
1548 TYPE(dbt_pgrid_type),
INTENT(INOUT) :: pgrid
1559 TYPE(dbt_pgrid_type),
INTENT(INOUT) :: pgrid
1560 INTEGER,
DIMENSION(:),
INTENT(INOUT) :: pdims
1561 TYPE(dbt_pgrid_type) :: pgrid_tmp
1562 INTEGER :: nsplit, dimsplit
1563 INTEGER,
DIMENSION(ndims_mapping_row(pgrid%nd_index_grid)) :: map1_2d
1564 INTEGER,
DIMENSION(ndims_mapping_column(pgrid%nd_index_grid)) :: map2_2d
1565 TYPe(nd_to_2d_mapping) :: nd_index_grid
1566 INTEGER,
DIMENSION(2) :: pdims_2d
1568 cpassert(all(pdims > 0))
1573 IF (mod(pdims_2d(dimsplit), nsplit) == 0)
THEN
1575 nsplit=nsplit, dimsplit=dimsplit)
1588 TYPE(dbt_type),
INTENT(INOUT) ::
tensor
1589 REAL(
dp),
INTENT(IN) :: eps
1600 TYPE(dbt_type),
INTENT(IN) ::
tensor
1601 INTEGER,
INTENT(IN) :: idim
1617 TYPE(dbt_type),
INTENT(IN) ::
tensor
1618 INTEGER,
INTENT(IN) :: idim
1650 blks_local_1, blks_local_2, blks_local_3, blks_local_4, &
1651 proc_dist_1, proc_dist_2, proc_dist_3, proc_dist_4, &
1652 blk_size_1, blk_size_2, blk_size_3, blk_size_4, &
1653 blk_offset_1, blk_offset_2, blk_offset_3, blk_offset_4, &
1656 TYPE(dbt_type),
INTENT(IN) ::
tensor
1657 INTEGER,
INTENT(OUT),
OPTIONAL,
DIMENSION(ndims_tensor(tensor)) :: nblks_total
1658 INTEGER,
INTENT(OUT),
OPTIONAL,
DIMENSION(ndims_tensor(tensor)) :: nfull_total
1659 INTEGER,
INTENT(OUT),
OPTIONAL,
DIMENSION(ndims_tensor(tensor)) :: nblks_local
1660 INTEGER,
INTENT(OUT),
OPTIONAL,
DIMENSION(ndims_tensor(tensor)) :: nfull_local
1661 INTEGER,
INTENT(OUT),
OPTIONAL,
DIMENSION(ndims_tensor(tensor)) :: my_ploc
1662 INTEGER,
INTENT(OUT),
OPTIONAL,
DIMENSION(ndims_tensor(tensor)) :: pdims
1663 INTEGER,
DIMENSION(dbt_nblks_local(tensor, 1)),
INTENT(OUT),
OPTIONAL :: blks_local_1
1664 INTEGER,
DIMENSION(dbt_nblks_total(tensor, 1)),
INTENT(OUT),
OPTIONAL :: proc_dist_1
1665 INTEGER,
DIMENSION(dbt_nblks_total(tensor, 1)),
INTENT(OUT),
OPTIONAL :: blk_size_1
1666 INTEGER,
DIMENSION(dbt_nblks_total(tensor, 1)),
INTENT(OUT),
OPTIONAL :: blk_offset_1
1667 INTEGER,
DIMENSION(dbt_nblks_local(tensor, 2)),
INTENT(OUT),
OPTIONAL :: blks_local_2
1668 INTEGER,
DIMENSION(dbt_nblks_total(tensor, 2)),
INTENT(OUT),
OPTIONAL :: proc_dist_2
1669 INTEGER,
DIMENSION(dbt_nblks_total(tensor, 2)),
INTENT(OUT),
OPTIONAL :: blk_size_2
1670 INTEGER,
DIMENSION(dbt_nblks_total(tensor, 2)),
INTENT(OUT),
OPTIONAL :: blk_offset_2
1671 INTEGER,
DIMENSION(dbt_nblks_local(tensor, 3)),
INTENT(OUT),
OPTIONAL :: blks_local_3
1672 INTEGER,
DIMENSION(dbt_nblks_total(tensor, 3)),
INTENT(OUT),
OPTIONAL :: proc_dist_3
1673 INTEGER,
DIMENSION(dbt_nblks_total(tensor, 3)),
INTENT(OUT),
OPTIONAL :: blk_size_3
1674 INTEGER,
DIMENSION(dbt_nblks_total(tensor, 3)),
INTENT(OUT),
OPTIONAL :: blk_offset_3
1675 INTEGER,
DIMENSION(dbt_nblks_local(tensor, 4)),
INTENT(OUT),
OPTIONAL :: blks_local_4
1676 INTEGER,
DIMENSION(dbt_nblks_total(tensor, 4)),
INTENT(OUT),
OPTIONAL :: proc_dist_4
1677 INTEGER,
DIMENSION(dbt_nblks_total(tensor, 4)),
INTENT(OUT),
OPTIONAL :: blk_size_4
1678 INTEGER,
DIMENSION(dbt_nblks_total(tensor, 4)),
INTENT(OUT),
OPTIONAL :: blk_offset_4
1679 TYPE(dbt_distribution_type),
INTENT(OUT),
OPTIONAL :: distribution
1680 CHARACTER(len=*),
INTENT(OUT),
OPTIONAL :: name
1681 INTEGER,
DIMENSION(ndims_tensor(tensor)) :: pdims_tmp, my_ploc_tmp
1685 IF (
PRESENT(nblks_local)) nblks_local(:) =
tensor%nblks_local
1686 IF (
PRESENT(nfull_local)) nfull_local(:) =
tensor%nfull_local
1689 IF (
PRESENT(my_ploc)) my_ploc = my_ploc_tmp
1690 IF (
PRESENT(pdims)) pdims = pdims_tmp
1750 IF (
PRESENT(name)) name =
tensor%name
1759 TYPE(dbt_type),
INTENT(IN) ::
tensor
1760 INTEGER :: num_blocks
1769 TYPE(dbt_type),
INTENT(IN) ::
tensor
1770 INTEGER(KIND=int_8) :: num_blocks
1779 TYPE(dbt_type),
INTENT(INOUT) ::
tensor
1790 TYPE(dbt_type),
INTENT(INOUT) ::
tensor
1799 TYPE(dbt_type),
INTENT(INOUT) ::
tensor
1800 REAL(
dp),
INTENT(IN) :: alpha
1808 TYPE(dbt_type),
INTENT(IN) ::
tensor
1817 TYPE(dbt_type),
INTENT(IN) ::
tensor
1827 TYPE(dbt_type),
INTENT(IN) ::
tensor
1828 INTEGER,
DIMENSION(ndims_tensor(tensor)), &
1830 INTEGER,
INTENT(IN) :: idim
1831 INTEGER,
DIMENSION(ndims_tensor(tensor)) :: blk_size
1850 TYPE(dbt_type),
INTENT(IN) ::
tensor
1851 INTEGER :: blk_count, nproc
1852 INTEGER,
DIMENSION(ndims_tensor(tensor)) :: bdims
1853 INTEGER(int_8) :: blk_count_total
1854 INTEGER,
PARAMETER :: max_load_imbalance = 2
1858 blk_count_total = product(int(bdims,
int_8))
1861 nproc =
tensor%pgrid%nproc
1863 blk_count = int(blk_count_total/nproc*max_load_imbalance)
1876 INTEGER,
INTENT(IN) :: nblk
1877 INTEGER,
INTENT(IN) :: nproc
1878 INTEGER,
DIMENSION(nblk),
INTENT(IN) :: blk_size
1879 INTEGER,
DIMENSION(nblk),
INTENT(OUT) :: dist
1888 TYPE(dbt_type),
INTENT(IN) :: tensor_in
1889 TYPE(dbt_type),
INTENT(INOUT) :: tensor_out
1890 TYPE(dbt_contraction_storage),
ALLOCATABLE :: tensor_storage_tmp
1891 TYPE(dbt_tas_mm_storage),
ALLOCATABLE :: tas_storage_tmp
1893 IF (tensor_in%matrix_rep%do_batched > 0)
THEN
1894 ALLOCATE (tas_storage_tmp, source=tensor_in%matrix_rep%mm_storage)
1896 IF (
ALLOCATED(tensor_out%matrix_rep%mm_storage))
DEALLOCATE (tensor_out%matrix_rep%mm_storage)
1897 CALL move_alloc(tas_storage_tmp, tensor_out%matrix_rep%mm_storage)
1900 opt_grid=tensor_in%matrix_rep%has_opt_pgrid)
1901 IF (
ALLOCATED(tensor_in%contraction_storage))
THEN
1902 ALLOCATE (tensor_storage_tmp, source=tensor_in%contraction_storage)
1904 IF (
ALLOCATED(tensor_out%contraction_storage))
DEALLOCATE (tensor_out%contraction_storage)
1905 IF (
ALLOCATED(tensor_storage_tmp))
CALL move_alloc(tensor_storage_tmp, tensor_out%contraction_storage)
subroutine, public dbm_scale(matrix, alpha)
Multiplies all entries in the given matrix by the given factor alpha.
Wrapper for allocating, copying and reshaping arrays.
Representation of arbitrary number of 1d integer arrays with arbitrary sizes. This is needed for gene...
pure logical function, public array_eq_i(arr1, arr2)
check whether two arrays are equal
integer function, dimension(:), allocatable, public sum_of_arrays(list)
sum of all elements for each array stored in list
subroutine, public get_arrays(list, data_1, data_2, data_3, data_4, i_selected)
Get all arrays contained in list.
subroutine, public create_array_list(list, ndata, data_1, data_2, data_3, data_4)
collects any number of arrays of different sizes into a single array (listcol_data),...
subroutine, public destroy_array_list(list)
destroy array list.
integer function, dimension(:), allocatable, public sizes_of_arrays(list)
sizes of arrays stored in list
subroutine, public array_offsets(list_in, list_out)
partial sums of array elements.
pure integer function, dimension(number_of_arrays(list)), public get_array_elements(list, indices)
Get an element for each array.
subroutine, public get_ith_array(list, i, array_size, array)
get ith array
type(array_list) function, public array_sublist(list, i_selected)
extract a subset of arrays
tensor index and mapping to DBM index
subroutine, public create_nd_to_2d_mapping(map, dims, map1_2d, map2_2d, base, col_major)
Create all data needed to quickly map between nd index and 2d index.
pure integer function, dimension(map%ndim_nd), public get_nd_indices_pgrid(map, ind_in)
transform 2d index to nd index, using info from index mapping.
pure integer function, public ndims_mapping_row(map)
how many tensor dimensions are mapped to matrix row
pure integer(kind=int_8) function, dimension(2), public get_2d_indices_tensor(map, ind_in)
transform nd index to 2d index, using info from index mapping.
pure integer function, public ndims_mapping(map)
pure integer(kind=int_8) function, public combine_tensor_index(ind_in, dims)
transform nd index to flat index
pure subroutine, public dbt_get_mapping_info(map, ndim_nd, ndim1_2d, ndim2_2d, dims_2d_i8, dims_2d, dims_nd, dims1_2d, dims2_2d, map1_2d, map2_2d, map_nd, base, col_major)
get mapping info
pure integer function, public combine_pgrid_index(ind_in, dims)
transform nd index to flat index
pure integer function, public ndims_mapping_column(map)
how many tensor dimensions are mapped to matrix column
subroutine, public destroy_nd_to_2d_mapping(map)
pure integer function, dimension(size(dims)), public split_tensor_index(ind_in, dims)
transform flat index to nd index
pure integer function, dimension(size(dims)), public split_pgrid_index(ind_in, dims)
transform flat index to nd index
Tall-and-skinny matrices: base routines similar to DBM API, mostly wrappers around existing DBM routi...
integer(kind=int_8) function, public dbt_tas_get_nze_total(matrix)
Get total number of non-zero elements.
subroutine, public dbt_tas_distribution_destroy(dist)
...
subroutine, public dbt_tas_get_stored_coordinates(matrix, row, column, processor)
As dbt_get_stored_coordinates.
pure integer function, public dbt_tas_get_nze(matrix)
As dbt_get_nze: get number of local non-zero elements.
subroutine, public dbt_tas_get_info(matrix, nblkrows_total, nblkcols_total, local_rows, local_cols, proc_row_dist, proc_col_dist, row_blk_size, col_blk_size, distribution, name)
...
subroutine, public dbt_tas_finalize(matrix)
...
subroutine, public dbt_tas_distribution_new(dist, mp_comm, row_dist, col_dist, split_info, nosplit)
create new distribution. Exactly like dbm_distribution_new but with custom types for row_dist and col...
subroutine, public dbt_tas_filter(matrix, eps)
As dbm_filter.
subroutine, public dbt_tas_clear(matrix)
Clear matrix (erase all data)
subroutine, public dbt_tas_destroy(matrix)
...
integer(kind=int_8) function, public dbt_tas_get_num_blocks_total(matrix)
get total number of blocks
pure integer function, public dbt_tas_get_num_blocks(matrix)
As dbt_get_num_blocks: get number of local blocks.
Global data (distribution and block sizes) for tall-and-skinny matrices For very sparse matrices with...
subroutine, public dbt_tas_default_distvec(nblk, nproc, blk_size, dist)
get a load-balanced and randomized distribution along one tensor dimension
Matrix multiplication for tall-and-skinny matrices. This uses the k-split (non-recursive) CARMA algor...
subroutine, public dbt_tas_set_batched_state(matrix, state, opt_grid)
set state flags during batched multiplication
methods to split tall-and-skinny matrices along longest dimension. Basically, we are splitting proces...
subroutine, public dbt_tas_release_info(split_info)
...
subroutine, public dbt_tas_get_split_info(info, mp_comm, nsplit, igroup, mp_comm_group, split_rowcol, pgrid_offset)
Get info on split.
subroutine, public dbt_tas_create_split(split_info, mp_comm, split_rowcol, nsplit, own_comm, opt_nsplit)
Split Cartesian process grid using a default split heuristic.
subroutine, public dbt_tas_create_split_rows_or_cols(split_info, mp_comm, ngroup, igroup, split_rowcol, own_comm)
split mpi grid by rows or columns
subroutine, public dbt_tas_info_hold(split_info)
...
subroutine, public dbt_tas_set_strict_split(info)
freeze current split factor such that it is never changed during multiplication
DBT tall-and-skinny base types. Mostly wrappers around existing DBM routines.
DBT tensor framework for block-sparse tensor contraction: Types and create/destroy routines.
subroutine, public dbt_pgrid_destroy(pgrid, keep_comm)
destroy process grid
subroutine, public dbt_distribution_new(dist, pgrid, nd_dist_1, nd_dist_2, nd_dist_3, nd_dist_4)
Create a tensor distribution.
subroutine, public blk_dims_tensor(tensor, dims)
tensor block dimensions
subroutine, public dims_tensor(tensor, dims)
tensor dimensions
subroutine, public dbt_copy_contraction_storage(tensor_in, tensor_out)
type(dbt_pgrid_type) function, public dbt_nd_mp_comm(comm_2d, map1_2d, map2_2d, dims_nd, dims1_nd, dims2_nd, pdims_2d, tdims, nsplit, dimsplit)
Create a default nd process topology that is consistent with a given 2d topology. Purpose: a nd tenso...
subroutine, public dbt_blk_sizes(tensor, ind, blk_size)
Size of tensor block.
subroutine, public dbt_destroy(tensor)
Destroy a tensor.
pure integer function, public dbt_max_nblks_local(tensor)
returns an estimate of maximum number of local blocks in tensor (irrespective of the actual number of...
recursive subroutine, public dbt_mp_dims_create(nodes, dims, tensor_dims, lb_ratio)
Create process grid dimensions corresponding to one dimension of the matrix representation of a tenso...
subroutine, public dbt_get_info(tensor, nblks_total, nfull_total, nblks_local, nfull_local, pdims, my_ploc, blks_local_1, blks_local_2, blks_local_3, blks_local_4, proc_dist_1, proc_dist_2, proc_dist_3, proc_dist_4, blk_size_1, blk_size_2, blk_size_3, blk_size_4, blk_offset_1, blk_offset_2, blk_offset_3, blk_offset_4, distribution, name)
As block_get_info but for tensors.
subroutine, public dbt_distribution_new_expert(dist, pgrid, map1_2d, map2_2d, nd_dist_1, nd_dist_2, nd_dist_3, nd_dist_4, own_comm)
Create a tensor distribution.
type(dbt_distribution_type) function, public dbt_distribution(tensor)
get distribution from tensor
pure integer function, public ndims_tensor(tensor)
tensor rank
subroutine, public dbt_pgrid_set_strict_split(pgrid)
freeze current split factor such that it is never changed during contraction
pure integer function, public dbt_nblks_total(tensor, idim)
total numbers of blocks along dimension idim
pure integer function, public dbt_blk_size(tensor, ind, idim)
block size of block with index ind along dimension idim
pure integer function, public dbt_get_num_blocks(tensor)
As block_get_num_blocks: get number of local blocks.
subroutine, public dbt_default_distvec(nblk, nproc, blk_size, dist)
get a load-balanced and randomized distribution along one tensor dimension
subroutine, public dbt_hold(tensor)
reference counting for tensors (only needed for communicator handle that must be freed when no longer...
subroutine, public dbt_pgrid_create_expert(mp_comm, dims, pgrid, map1_2d, map2_2d, tensor_dims, nsplit, dimsplit)
Create an n-dimensional process grid. We can not use a n-dimensional MPI cartesian grid for tensors s...
subroutine, public dbt_clear(tensor)
Clear tensor (s.t. it does not contain any blocks)
subroutine, public dbt_finalize(tensor)
Finalize tensor, as block_finalize. This should be taken care of internally in DBT tensors,...
integer(kind=int_8) function, public dbt_get_nze_total(tensor)
pure integer function, public dbt_nblks_local(tensor, idim)
local number of blocks along dimension idim
subroutine, public mp_environ_pgrid(pgrid, dims, task_coor)
as mp_environ but for special pgrid type
subroutine, public dbt_get_stored_coordinates(tensor, ind_nd, processor)
Generalization of block_get_stored_coordinates for tensors.
pure integer function, public dbt_get_nze(tensor)
subroutine, public dbt_pgrid_create(mp_comm, dims, pgrid, tensor_dims)
integer(kind=int_8) function, public dbt_get_num_blocks_total(tensor)
Get total number of blocks.
pure integer(int_8) function, public ndims_matrix_row(tensor)
how many tensor dimensions are mapped to matrix row
subroutine, public dbt_pgrid_change_dims(pgrid, pdims)
change dimensions of an existing process grid.
pure integer(int_8) function, public ndims_matrix_column(tensor)
how many tensor dimensions are mapped to matrix column
subroutine, public dbt_nd_mp_free(mp_comm)
Release the MPI communicator.
subroutine, public dbt_blk_offsets(tensor, ind, blk_offset)
offset of tensor block
subroutine, public dbt_filter(tensor, eps)
As block_filter.
subroutine, public dbt_distribution_destroy(dist)
Destroy tensor distribution.
subroutine, public dbt_scale(tensor, alpha)
as block_scale
Defines the basic variable types.
integer, parameter, public int_8
integer, parameter, public dp
integer, parameter, public default_string_length
Interface to the message passing library MPI.
subroutine, public mp_dims_create(nodes, dims)
wrapper to MPI_Dims_create
All kind of helpful little routines.