Yet Another eXchange Tool  DO_NOT_EDIT_HERE
test_redist_p2p_parallel_f.f90
1 !
2 ! @file test_redist_p2p_parallel_f.f90
3 !
4 ! @copyright Copyright (C) 2016 Jörg Behrens <behrens@dkrz.de>
5 ! Moritz Hanke <hanke@dkrz.de>
6 ! Thomas Jahns <jahns@dkrz.de>
7 !
8 ! @author Jörg Behrens <behrens@dkrz.de>
9 ! Moritz Hanke <hanke@dkrz.de>
10 ! Thomas Jahns <jahns@dkrz.de>
11 !
12 !
13 ! Keywords:
14 ! Maintainer: Jörg Behrens <behrens@dkrz.de>
15 ! Moritz Hanke <hanke@dkrz.de>
16 ! Thomas Jahns <jahns@dkrz.de>
17 ! URL: https://doc.redmine.dkrz.de/yaxt/html/
18 !
19 ! Redistribution and use in source and binary forms, with or without
20 ! modification, are permitted provided that the following conditions are
21 ! met:
22 !
23 ! Redistributions of source code must retain the above copyright notice,
24 ! this list of conditions and the following disclaimer.
25 !
26 ! Redistributions in binary form must reproduce the above copyright
27 ! notice, this list of conditions and the following disclaimer in the
28 ! documentation and/or other materials provided with the distribution.
29 !
30 ! Neither the name of the DKRZ GmbH nor the names of its contributors
31 ! may be used to endorse or promote products derived from this software
32 ! without specific prior written permission.
33 !
34 ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
35 ! IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
36 ! TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37 ! PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
38 ! OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
39 ! EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
40 ! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
41 ! PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
42 ! LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
43 ! NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
44 ! SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 !
46 PROGRAM test_redist_p2p_parallel
47  USE ftest_common, ONLY: init_mpi, finish_mpi, test_abort
48  USE iso_c_binding, ONLY: c_loc
49  USE mpi
50  USE yaxt, ONLY: xt_initialize, xt_finalize, &
51  xt_int_kind, xi => xt_int_kind, &
52  xt_idxlist, xt_idxvec_new, xt_idxlist_delete, &
54  xt_redist, xt_redist_p2p_new, xt_redist_get_mpi_comm, &
57  USE test_idxlist_utils, ONLY: test_err_count
58  USE test_redist_common, ONLY: communicators_are_congruent, &
59  check_redist
60  ! older PGI compilers do not handle generic interface correctly
61 #if defined __PGI && __PGIC__ == 15
64 #endif
65  IMPLICIT NONE
66 
67  INTEGER :: comm_rank, comm_size, ierror
68 
69  CALL init_mpi
70  CALL xt_initialize(mpi_comm_world)
71 
72  CALL mpi_comm_rank(mpi_comm_world, comm_rank, ierror)
73  IF (ierror /= mpi_success) &
74  CALL test_abort("MPI error!", &
75  __file__, &
76  __line__)
77 
78  CALL mpi_comm_size(mpi_comm_world, comm_size, ierror)
79  IF (ierror /= mpi_success) &
80  CALL test_abort("MPI error!", &
81  __file__, &
82  __line__)
83 
84  CALL simple_test
85  CALL nonuniform_test
86  CALL block_redist_test
87 
88  IF (test_err_count() /= 0) &
89  CALL test_abort("non-zero error count!", &
90  __file__, &
91  __line__)
92  CALL xt_finalize
93  CALL finish_mpi
94 
95 
96 CONTAINS
97  SUBROUTINE simple_test
98  INTEGER, PARAMETER :: data_size = 10
99  INTEGER, PARAMETER :: src_num_indices = data_size, &
100  dst_num_indices = data_size
101  INTEGER(xt_int_kind) :: src_index_list(data_size), &
102  dst_index_list(data_size)
103  TYPE(xt_idxlist) :: src_idxlist, dst_idxlist
104  TYPE(xt_xmap) :: xmap
105  TYPE(xt_redist) :: redist
106  DOUBLE PRECISION :: src_data(data_size), dst_data(data_size)
107  INTEGER :: i
108 
109  ! source index list
110  DO i = 1, src_num_indices
111  src_index_list(i) = int(comm_rank * data_size + (i - 1), xi)
112  END DO
113 
114  src_idxlist = xt_idxvec_new(src_index_list)
115  ! destination index list
116  DO i = 1, dst_num_indices
117  dst_index_list(i) &
118  = int(mod(comm_rank * data_size + i + 1, comm_size * data_size), xi)
119  END DO
120  dst_idxlist = xt_idxvec_new(dst_index_list)
121  ! xmap
122  xmap = xt_xmap_all2all_new(src_idxlist, dst_idxlist, mpi_comm_world)
123  ! redist_p2p
124  redist = xt_redist_p2p_new(xmap, mpi_double_precision)
125 
126  ! test communicator of redist
127  IF (.NOT. communicators_are_congruent(xt_redist_get_mpi_comm(redist), &
128  mpi_comm_world)) &
129  CALL test_abort("error in xt_redist_get_mpi_comm", &
130  __file__, &
131  __line__)
132 
133  ! test exchange
134  dst_data(:) = -1.0d0
135 
136  DO i = 1, src_num_indices
137  src_data(i) = dble(comm_rank * data_size + i - 1)
138  END DO
139 
140  CALL check_redist(redist, src_data, dst_data, dst_index_list)
141 
142  ! clean up
143  CALL xt_redist_delete(redist)
144  CALL xt_xmap_delete(xmap)
145  CALL xt_idxlist_delete(src_idxlist)
146  CALL xt_idxlist_delete(dst_idxlist)
147  END SUBROUTINE simple_test
148 
149  ! test nonuniform numbers of send and receive partners
150  SUBROUTINE nonuniform_test
151  ! source index list
152  INTEGER(xt_int_kind), ALLOCATABLE :: src_index_list(:), dst_index_list(:)
153  DOUBLE PRECISION, ALLOCATABLE, TARGET :: src_data(:), dst_data(:)
154  TYPE(xt_idxlist) :: src_idxlist, dst_idxlist
155  TYPE(xt_xmap) :: xmap
156  TYPE(xt_redist) :: redist
157  INTEGER :: i, src_num_indices, dst_num_indices
158 
159  ALLOCATE(src_index_list(comm_size), dst_index_list(comm_size), &
160  src_data(comm_size), dst_data(comm_size))
161  src_num_indices = merge(comm_size, 0, comm_rank == 0)
162  DO i = 1, src_num_indices
163  src_index_list(i) = int(i - 1, xi)
164  END DO
165 
166  src_idxlist = xt_idxvec_new(src_index_list, src_num_indices)
167 
168  ! destination index list
169  dst_num_indices = comm_size
170  DO i = 1, dst_num_indices
171  dst_index_list(i) = int(i - 1, xi)
172  END DO
173 
174  dst_idxlist = xt_idxvec_new(dst_index_list, dst_num_indices)
175 
176  ! xmap
177  xmap = xt_xmap_all2all_new(src_idxlist, dst_idxlist, mpi_comm_world)
178 
179  ! redist_p2p
180  redist = xt_redist_p2p_new(xmap, mpi_double_precision)
181 
182  ! test communicator of redist
183  IF (.NOT. communicators_are_congruent(xt_redist_get_mpi_comm(redist), &
184  mpi_comm_world)) &
185  CALL test_abort("error in xt_redist_get_mpi_comm", &
186  __file__, &
187  __line__)
188 
189  ! test exchange
190  IF (comm_rank == 0) THEN
191  DO i = 1, comm_size
192  src_data(i) = dble(i - 1)
193  END DO
194  ELSE
195  src_data(:) = -2.0d0
196  END IF
197  dst_data(:) = -1.0d0
198 
199  CALL xt_redist_s_exchange(redist, src_data, dst_data)
200 
201  DO i = 1, comm_size
202  IF (dst_data(i) /= dble(i - 1)) EXIT
203  END DO
204  IF (i <= comm_size) &
205  CALL test_abort("error in xt_redist_s_exchange", &
206  __file__, &
207  __line__)
208 
209  ! clean up
210  CALL xt_redist_delete(redist)
211  CALL xt_xmap_delete(xmap)
212  CALL xt_idxlist_delete(src_idxlist)
213  CALL xt_idxlist_delete(dst_idxlist)
214  END SUBROUTINE nonuniform_test
215 
216  ! test redist with blocks
217  SUBROUTINE block_redist_test
218  ! gvol_size: volume of deep ocean
219  INTEGER :: ngdom, gvol_size, i, nwin, ig0, ig, j, p, qa, qb, &
220  a_vol_size, b_vol_size
221  ! gdepth: ocean depth of an one dim. ocean
222  INTEGER, ALLOCATABLE :: gdoma(:), gdomb(:), gsurfdata(:), &
223  gdepth(:), ig2col_off(:), b_surfdata_ref(:), gvoldata(:), &
224  src_block_offsets(:), src_block_sizes(:), dst_block_offsets(:), &
225  dst_block_sizes(:), b_voldata_ref(:)
226  INTEGER, ALLOCATABLE :: a_surfdata(:), b_surfdata(:), &
227  a_voldata(:), b_voldata(:)
228  INTEGER(xi), ALLOCATABLE :: iveca(:), ivecb(:)
229  INTEGER(xi) :: ia, ib
230  TYPE(xt_idxlist) :: idxlist_a, idxlist_b
231  TYPE(xt_xmap) :: xmap
232  TYPE(xt_redist) :: redist, block_redist, block_redist2
233 
234  IF (2 * comm_size > huge(1_xt_int_kind)) &
235  CALL test_abort('too large number of tasks', &
236  __file__, &
237  __line__)
238  ! the global index domain (1dim problem):
239  ngdom = 2 * comm_size
240  ! start state (index distribution) of global domain
241  ALLOCATE(gdoma(ngdom), gdomb(ngdom))
242  ! end state ""
243  ALLOCATE(gsurfdata(ngdom), gdepth(ngdom))
244  ALLOCATE(ig2col_off(ngdom)) ! offset of surface DATA within vol
245  gvol_size = 0
246  DO i = 1, ngdom
247  gdoma(i) = i - 1
248  gdomb(i) = ngdom - i
249  gsurfdata(i) = 99 + i
250  gdepth(i) = i
251  ig2col_off(i) = gvol_size
252  gvol_size = gvol_size + gdepth(i)
253  END DO
254 
255  nwin = ngdom / comm_size ! my local window size of the global surface domain
256  ! start of my window within global index domain (== global offset)
257  ig0 = comm_rank * nwin
258  IF (nwin * comm_size /= ngdom) &
259  CALL test_abort("internal error", &
260  __file__, &
261  __line__)
262 
263  ! local index
264  ALLOCATE(iveca(nwin), ivecb(nwin))
265  DO i = 1, nwin
266  ig = ig0 + i
267  iveca(i) = int(gdoma(ig), xi)
268  ivecb(i) = int(gdomb(ig), xi)
269  END DO
270 
271  idxlist_a = xt_idxvec_new(iveca, nwin)
272  idxlist_b = xt_idxvec_new(ivecb, nwin)
273 
274  xmap = xt_xmap_all2all_new(idxlist_a, idxlist_b, mpi_comm_world)
275 
276  ! simple redist
277  redist = xt_redist_p2p_new(xmap, mpi_integer)
278 
279  ! test communicator of redist
280  IF (.NOT. communicators_are_congruent(xt_redist_get_mpi_comm(redist), &
281  mpi_comm_world)) &
282  CALL test_abort("error in xt_redist_get_mpi_comm", &
283  __file__, &
284  __line__)
285 
286  ALLOCATE(a_surfdata(nwin), b_surfdata(nwin), b_surfdata_ref(nwin))
287  DO i = 1, nwin
288  a_surfdata(i) = gsurfdata(iveca(i) + 1)
289  b_surfdata(i) = -1
290  b_surfdata_ref(i) = gsurfdata(ivecb(i) + 1)
291  END DO
292 
293  CALL check_redist(redist, a_surfdata, b_surfdata, b_surfdata_ref)
294  CALL xt_redist_delete(redist)
295 
296  ! generate global volume data
297  ALLOCATE(gvoldata(gvol_size))
298  DO i = 1, ngdom
299  DO j = 1, gdepth(i)
300  p = ig2col_off(i) + j
301  gvoldata(p) = (i - 1) * 100 + j - 1
302  END DO
303  END DO
304 
305  ! generate blocks
306  ALLOCATE(src_block_offsets(nwin), src_block_sizes(nwin), &
307  dst_block_offsets(nwin), dst_block_sizes(nwin))
308  a_vol_size = 0 ! state a volume of my proc
309  b_vol_size = 0 ! state b volume of my proc
310  ! we only need local size but simply oversize here
311  ALLOCATE(a_voldata(gvol_size), b_voldata(gvol_size), &
312  b_voldata_ref(gvol_size))
313  a_voldata(:) = -1
314  b_voldata_ref(:) = -1
315 
316  qa = 1
317  DO i = 1, nwin
318  ia = iveca(i)
319  IF (i > 1) THEN
320  src_block_offsets(i) = src_block_offsets(i - 1) + src_block_sizes(i - 1)
321  ELSE
322  src_block_offsets(i) = 0
323  END IF
324  src_block_sizes(i) = gdepth(int(ia) + 1)
325  DO j = 1, gdepth(int(ia) + 1)
326  p = ig2col_off(int(ia) + 1) + j
327  a_voldata(qa) = gvoldata(p)
328  qa = qa + 1
329  END DO
330  a_vol_size = a_vol_size + src_block_sizes(i)
331  END DO
332 
333  qb = 1
334  DO i = 1, nwin
335  ib = ivecb(i)
336  IF (i > 1) THEN
337  dst_block_offsets(i) = dst_block_offsets(i - 1) + dst_block_sizes(i - 1)
338  ELSE
339  dst_block_offsets(i) = 0
340  END IF
341  dst_block_sizes(i) = gdepth(int(ib) + 1)
342  DO j = 1, gdepth(int(ib) + 1)
343  p = ig2col_off(int(ib) + 1) + j
344  b_voldata_ref(qb) = gvoldata(p)
345  qb = qb + 1
346  END DO
347  b_vol_size = b_vol_size + dst_block_sizes(i)
348  END DO
349 
350  ! redist with blocks
351  block_redist &
353  src_block_offsets, src_block_sizes, nwin, &
354  dst_block_offsets, dst_block_sizes, nwin, mpi_integer)
355  ! test communicator of redist
356  IF (.NOT. communicators_are_congruent(xt_redist_get_mpi_comm(block_redist), &
357  mpi_comm_world)) &
358  CALL test_abort("error in xt_redist_get_mpi_comm", &
359  __file__, &
360  __line__)
361 
362  CALL check_redist(block_redist, a_voldata, b_voldata, b_voldata_ref)
363 
364  ! redist with blocks but without explicit offsets:
365  block_redist2 = xt_redist_p2p_blocks_new(xmap, &
366  src_block_sizes, nwin, dst_block_sizes, nwin, mpi_integer)
367  ! test communicator of redist
368 
369  IF (.NOT. communicators_are_congruent(xt_redist_get_mpi_comm(block_redist2), &
370  mpi_comm_world)) &
371  CALL test_abort("error in xt_redist_get_mpi_comm", &
372  __file__, &
373  __line__)
374 
375  CALL check_redist(block_redist2, a_voldata, b_voldata, b_voldata_ref)
376 
377  ! cleanup
378  CALL xt_redist_delete(block_redist2)
379  CALL xt_redist_delete(block_redist)
380  CALL xt_xmap_delete(xmap)
381  CALL xt_idxlist_delete(idxlist_a)
382  CALL xt_idxlist_delete(idxlist_b)
383  END SUBROUTINE block_redist_test
384 
385 END PROGRAM test_redist_p2p_parallel
386 !
387 ! Local Variables:
388 ! f90-continuation-indent: 5
389 ! coding: utf-8
390 ! indent-tabs-mode: nil
391 ! show-trailing-whitespace: t
392 ! require-trailing-newline: t
393 ! End:
394 !