Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief tall-and-skinny matrices: Input / Output
10 : !> \author Patrick Seewald
11 : ! **************************************************************************************************
12 : MODULE dbt_tas_io
13 : USE dbm_api, ONLY: dbm_distribution_col_dist,&
14 : dbm_distribution_obj,&
15 : dbm_distribution_row_dist,&
16 : dbm_get_distribution
17 : USE dbt_tas_base, ONLY: dbt_tas_get_info,&
18 : dbt_tas_get_num_blocks,&
19 : dbt_tas_get_num_blocks_total,&
20 : dbt_tas_get_nze,&
21 : dbt_tas_get_nze_total,&
22 : dbt_tas_nblkcols_total,&
23 : dbt_tas_nblkrows_total
24 : USE dbt_tas_global, ONLY: dbt_tas_distribution,&
25 : dbt_tas_rowcol_data
26 : USE dbt_tas_split, ONLY: colsplit,&
27 : dbt_tas_get_split_info,&
28 : rowsplit
29 : USE dbt_tas_types, ONLY: dbt_tas_split_info,&
30 : dbt_tas_type
31 : USE kinds, ONLY: default_string_length,&
32 : dp,&
33 : int_8
34 : USE message_passing, ONLY: mp_cart_type
35 : #include "../../base/base_uses.f90"
36 :
37 : IMPLICIT NONE
38 : PRIVATE
39 :
40 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dbt_tas_io'
41 :
42 : PUBLIC :: &
43 : dbt_tas_write_dist, &
44 : dbt_tas_write_matrix_info, &
45 : dbt_tas_write_split_info, &
46 : prep_output_unit
47 :
48 : CONTAINS
49 :
50 : ! **************************************************************************************************
51 : !> \brief Write basic infos of tall-and-skinny matrix:
52 : !> block dimensions, full dimensions, process grid dimensions
53 : !> \param matrix ...
54 : !> \param unit_nr ...
55 : !> \param full_info Whether to print distribution and block size vectors
56 : !> \author Patrick Seewald
57 : ! **************************************************************************************************
58 128436 : SUBROUTINE dbt_tas_write_matrix_info(matrix, unit_nr, full_info)
59 : TYPE(dbt_tas_type), INTENT(IN) :: matrix
60 : INTEGER, INTENT(IN) :: unit_nr
61 : LOGICAL, INTENT(IN), OPTIONAL :: full_info
62 :
63 : INTEGER :: unit_nr_prv
64 : INTEGER(KIND=int_8) :: nblkcols_total, nblkrows_total
65 :
66 385308 : CLASS(dbt_tas_distribution), ALLOCATABLE :: proc_row_dist, proc_col_dist
67 385308 : CLASS(dbt_tas_rowcol_data), ALLOCATABLE :: row_blk_size, col_blk_size
68 : INTEGER(KIND=int_8) :: iblk
69 : CHARACTER(default_string_length) :: name
70 :
71 128436 : unit_nr_prv = prep_output_unit(unit_nr)
72 128436 : IF (unit_nr_prv == 0) RETURN
73 :
74 : CALL dbt_tas_get_info(matrix, nblkrows_total=nblkrows_total, nblkcols_total=nblkcols_total, &
75 : proc_row_dist=proc_row_dist, proc_col_dist=proc_col_dist, &
76 128436 : row_blk_size=row_blk_size, col_blk_size=col_blk_size, name=name)
77 :
78 128436 : IF (unit_nr_prv > 0) THEN
79 102 : WRITE (unit_nr_prv, "(T2,A)") "GLOBAL INFO OF "//TRIM(name)
80 102 : WRITE (unit_nr_prv, "(T4,A,1X)", advance="no") "block dimensions:"
81 102 : WRITE (unit_nr_prv, "(I12,I12)", advance="no") nblkrows_total, nblkcols_total
82 102 : WRITE (unit_nr_prv, "(/T4,A,1X)", advance="no") "full dimensions:"
83 102 : WRITE (unit_nr_prv, "(I14,I14)", advance="no") row_blk_size%nfullrowcol, col_blk_size%nfullrowcol
84 102 : WRITE (unit_nr_prv, "(/T4,A,1X)", advance="no") "process grid dimensions:"
85 102 : WRITE (unit_nr_prv, "(I10,I10)", advance="no") proc_row_dist%nprowcol, proc_col_dist%nprowcol
86 102 : IF (PRESENT(full_info)) THEN
87 30 : IF (full_info) THEN
88 0 : WRITE (unit_nr_prv, '(/T4,A)', advance='no') "Block sizes:"
89 0 : WRITE (unit_nr_prv, '(/T8,A)', advance='no') 'Row:'
90 0 : DO iblk = 1, row_blk_size%nmrowcol
91 0 : WRITE (unit_nr_prv, '(I4,1X)', advance='no') row_blk_size%data(iblk)
92 : END DO
93 0 : WRITE (unit_nr_prv, '(/T8,A)', advance='no') 'Column:'
94 0 : DO iblk = 1, col_blk_size%nmrowcol
95 0 : WRITE (unit_nr_prv, '(I4,1X)', advance='no') col_blk_size%data(iblk)
96 : END DO
97 0 : WRITE (unit_nr_prv, '(/T4,A)', advance='no') "Block distribution:"
98 0 : WRITE (unit_nr_prv, '(/T8,A)', advance='no') 'Row:'
99 0 : DO iblk = 1, proc_row_dist%nmrowcol
100 0 : WRITE (unit_nr_prv, '(I4,1X)', advance='no') proc_row_dist%dist(iblk)
101 : END DO
102 0 : WRITE (unit_nr_prv, '(/T8,A)', advance='no') 'Column:'
103 0 : DO iblk = 1, proc_col_dist%nmrowcol
104 0 : WRITE (unit_nr_prv, '(I4,1X)', advance='no') proc_col_dist%dist(iblk)
105 : END DO
106 :
107 : END IF
108 : END IF
109 102 : WRITE (unit_nr_prv, *)
110 : END IF
111 :
112 641988 : END SUBROUTINE
113 :
114 : ! **************************************************************************************************
115 : !> \brief Write info on tall-and-skinny matrix distribution & load balance
116 : !> \param matrix ...
117 : !> \param unit_nr ...
118 : !> \param full_info Whether to print subgroup DBM distribution
119 : !> \author Patrick Seewald
120 : ! **************************************************************************************************
121 140670 : SUBROUTINE dbt_tas_write_dist(matrix, unit_nr, full_info)
122 : TYPE(dbt_tas_type), INTENT(IN) :: matrix
123 : INTEGER, INTENT(IN) :: unit_nr
124 : LOGICAL, INTENT(IN), OPTIONAL :: full_info
125 :
126 : CHARACTER(default_string_length) :: name
127 : INTEGER :: icol, igroup, irow, nblock, ndbt_p_max, &
128 : nelement, nelement_p_max, ngroup, &
129 : nproc, split_rowcol, unit_nr_prv
130 : INTEGER(KIND=int_8) :: ndbt_p_sum, ndbt_s, ndbt_s_max, &
131 : ndbt_tot, nelement_p_sum, nelement_s, &
132 : nelement_s_max
133 : INTEGER(KIND=int_8), DIMENSION(2) :: tmp_i8
134 : INTEGER, DIMENSION(2) :: tmp
135 140670 : INTEGER, DIMENSION(:), POINTER :: coldist, rowdist
136 : REAL(KIND=dp) :: occupation
137 : TYPE(dbm_distribution_obj) :: dist
138 140670 : TYPE(mp_cart_type) :: mp_comm, mp_comm_group
139 :
140 140670 : unit_nr_prv = prep_output_unit(unit_nr)
141 140670 : IF (unit_nr_prv == 0) RETURN
142 :
143 140670 : CALL dbt_tas_get_split_info(matrix%dist%info, mp_comm, ngroup, igroup, mp_comm_group, split_rowcol)
144 140670 : CALL dbt_tas_get_info(matrix, name=name)
145 140670 : nproc = mp_comm%num_pe
146 :
147 140670 : nblock = dbt_tas_get_num_blocks(matrix)
148 140670 : nelement = dbt_tas_get_nze(matrix)
149 :
150 140670 : ndbt_p_sum = dbt_tas_get_num_blocks_total(matrix)
151 140670 : nelement_p_sum = dbt_tas_get_nze_total(matrix)
152 :
153 422010 : tmp = (/nblock, nelement/)
154 140670 : CALL mp_comm%max(tmp)
155 140670 : ndbt_p_max = tmp(1); nelement_p_max = tmp(2)
156 :
157 140670 : ndbt_s = nblock
158 140670 : nelement_s = nelement
159 :
160 140670 : CALL mp_comm_group%sum(ndbt_s)
161 140670 : CALL mp_comm_group%sum(nelement_s)
162 :
163 422010 : tmp_i8 = (/ndbt_s, nelement_s/)
164 140670 : CALL mp_comm%max(tmp_i8)
165 140670 : ndbt_s_max = tmp_i8(1); nelement_s_max = tmp_i8(2)
166 :
167 140670 : ndbt_tot = dbt_tas_nblkrows_total(matrix)*dbt_tas_nblkcols_total(matrix)
168 140670 : occupation = -1.0_dp
169 140670 : IF (ndbt_tot .NE. 0) occupation = 100.0_dp*REAL(ndbt_p_sum, dp)/REAL(ndbt_tot, dp)
170 :
171 140670 : dist = dbm_get_distribution(matrix%matrix)
172 140670 : rowdist => dbm_distribution_row_dist(dist)
173 140670 : coldist => dbm_distribution_col_dist(dist)
174 :
175 140670 : IF (unit_nr_prv > 0) THEN
176 : WRITE (unit_nr_prv, "(T2,A)") &
177 102 : "DISTRIBUTION OF "//TRIM(name)
178 102 : WRITE (unit_nr_prv, "(T15,A,T68,I13)") "Number of non-zero blocks:", ndbt_p_sum
179 102 : WRITE (unit_nr_prv, "(T15,A,T75,F6.2)") "Percentage of non-zero blocks:", occupation
180 102 : WRITE (unit_nr_prv, "(T15,A,T68,I13)") "Average number of blocks per group:", (ndbt_p_sum + ngroup - 1)/ngroup
181 102 : WRITE (unit_nr_prv, "(T15,A,T68,I13)") "Maximum number of blocks per group:", ndbt_s_max
182 102 : WRITE (unit_nr_prv, "(T15,A,T68,I13)") "Average number of matrix elements per group:", (nelement_p_sum + ngroup - 1)/ngroup
183 102 : WRITE (unit_nr_prv, "(T15,A,T68,I13)") "Maximum number of matrix elements per group:", nelement_s_max
184 102 : WRITE (unit_nr_prv, "(T15,A,T68,I13)") "Average number of blocks per CPU:", (ndbt_p_sum + nproc - 1)/nproc
185 102 : WRITE (unit_nr_prv, "(T15,A,T68,I13)") "Maximum number of blocks per CPU:", ndbt_p_max
186 102 : WRITE (unit_nr_prv, "(T15,A,T68,I13)") "Average number of matrix elements per CPU:", (nelement_p_sum + nproc - 1)/nproc
187 102 : WRITE (unit_nr_prv, "(T15,A,T68,I13)") "Maximum number of matrix elements per CPU:", nelement_p_max
188 102 : IF (PRESENT(full_info)) THEN
189 10 : IF (full_info) THEN
190 0 : WRITE (unit_nr_prv, "(T15,A)") "Row distribution on subgroup:"
191 0 : WRITE (unit_nr_prv, '(T15)', advance='no')
192 0 : DO irow = 1, SIZE(rowdist)
193 0 : WRITE (unit_nr_prv, '(I3, 1X)', advance='no') rowdist(irow)
194 : END DO
195 0 : WRITE (unit_nr_prv, "(/T15,A)") "Column distribution on subgroup:"
196 0 : WRITE (unit_nr_prv, '(T15)', advance='no')
197 0 : DO icol = 1, SIZE(coldist)
198 0 : WRITE (unit_nr_prv, '(I3, 1X)', advance='no') coldist(icol)
199 : END DO
200 0 : WRITE (unit_nr_prv, *)
201 : END IF
202 : END IF
203 : END IF
204 281340 : END SUBROUTINE
205 :
206 : ! **************************************************************************************************
207 : !> \brief Print info on how matrix is split
208 : !> \param info ...
209 : !> \param unit_nr ...
210 : !> \param name ...
211 : !> \author Patrick Seewald
212 : ! **************************************************************************************************
213 46902 : SUBROUTINE dbt_tas_write_split_info(info, unit_nr, name)
214 : TYPE(dbt_tas_split_info), INTENT(IN) :: info
215 : INTEGER, INTENT(IN) :: unit_nr
216 : CHARACTER(len=*), INTENT(IN), OPTIONAL :: name
217 :
218 46902 : CHARACTER(len=:), ALLOCATABLE :: name_prv
219 : INTEGER :: igroup, mynode, nsplit, split_rowcol, &
220 : unit_nr_prv
221 : INTEGER, DIMENSION(2) :: dims, groupdims, pgrid_offset
222 46902 : TYPE(mp_cart_type) :: mp_comm, mp_comm_group
223 :
224 46902 : unit_nr_prv = prep_output_unit(unit_nr)
225 46902 : IF (unit_nr_prv == 0) RETURN
226 :
227 46902 : IF (PRESENT(name)) THEN
228 12 : ALLOCATE (name_prv, SOURCE=TRIM(name))
229 : ELSE
230 46890 : ALLOCATE (name_prv, SOURCE="")
231 : END IF
232 :
233 46902 : CALL dbt_tas_get_split_info(info, mp_comm, nsplit, igroup, mp_comm_group, split_rowcol, pgrid_offset)
234 :
235 46902 : mynode = mp_comm%mepos
236 140706 : dims = mp_comm%num_pe_cart
237 140706 : groupdims = mp_comm_group%num_pe_cart
238 :
239 46902 : IF (unit_nr_prv > 0) THEN
240 35 : SELECT CASE (split_rowcol)
241 : CASE (rowsplit)
242 35 : WRITE (unit_nr_prv, "(T4,A,I4,1X,A,I4)") name_prv//"splitting rows by factor", nsplit
243 : CASE (colsplit)
244 40 : WRITE (unit_nr_prv, "(T4,A,I4,1X,A,I4)") name_prv//"splitting columns by factor", nsplit
245 : END SELECT
246 40 : WRITE (unit_nr_prv, "(T4,A,I4,A1,I4)") name_prv//"global grid sizes:", dims(1), "x", dims(2)
247 : END IF
248 :
249 : IF (unit_nr_prv > 0) THEN
250 : WRITE (unit_nr_prv, "(T4,A,I4,A1,I4)") &
251 40 : name_prv//"grid sizes on subgroups:", &
252 80 : groupdims(1), "x", groupdims(2)
253 : END IF
254 :
255 46902 : END SUBROUTINE
256 :
257 : ! **************************************************************************************************
258 : !> \brief ...
259 : !> \param unit_nr ...
260 : !> \return ...
261 : !> \author Patrick Seewald
262 : ! **************************************************************************************************
263 924855 : FUNCTION prep_output_unit(unit_nr) RESULT(unit_nr_out)
264 : INTEGER, INTENT(IN), OPTIONAL :: unit_nr
265 : INTEGER :: unit_nr_out
266 :
267 924855 : IF (PRESENT(unit_nr)) THEN
268 661651 : unit_nr_out = unit_nr
269 : ELSE
270 : unit_nr_out = 0
271 : END IF
272 :
273 924855 : END FUNCTION
274 :
275 : END MODULE
276 :
|