Yet Another eXchange Tool  DO_NOT_EDIT_HERE
test_redist_collection_parallel_f.f90
1 
13 
14 !
15 ! Keywords:
16 ! Maintainer: Jörg Behrens <behrens@dkrz.de>
17 ! Moritz Hanke <hanke@dkrz.de>
18 ! Thomas Jahns <jahns@dkrz.de>
19 ! URL: https://doc.redmine.dkrz.de/yaxt/html/
20 !
21 ! Redistribution and use in source and binary forms, with or without
22 ! modification, are permitted provided that the following conditions are
23 ! met:
24 !
25 ! Redistributions of source code must retain the above copyright notice,
26 ! this list of conditions and the following disclaimer.
27 !
28 ! Redistributions in binary form must reproduce the above copyright
29 ! notice, this list of conditions and the following disclaimer in the
30 ! documentation and/or other materials provided with the distribution.
31 !
32 ! Neither the name of the DKRZ GmbH nor the names of its contributors
33 ! may be used to endorse or promote products derived from this software
34 ! without specific prior written permission.
35 !
36 ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
37 ! IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
38 ! TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
39 ! PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
40 ! OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
41 ! EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
42 ! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
43 ! PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
44 ! LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
45 ! NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46 ! SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 !
48 PROGRAM test_redist_collection_parallel
49  USE mpi
50  USE ftest_common, ONLY: init_mpi, finish_mpi, test_abort
51  USE test_idxlist_utils, ONLY: test_err_count
52  USE yaxt, ONLY: xt_initialize, xt_finalize, xt_int_kind, xi => xt_int_kind, &
58  xt_idxlist_get_indices, xt_int_mpidt
59  ! older PGI compilers do not handle generic interface correctly
60 #if defined __PGI && (__PGIC__ < 12 || (__PGIC__ == 12 && __PGIC_MINOR__ <= 10))
62 #endif
63  USE iso_c_binding, ONLY: c_loc, c_ptr
64  IMPLICIT NONE
65  INTEGER :: rank, world_size, ierror
66  CALL init_mpi
67  CALL xt_initialize(mpi_comm_world)
68 
69  CALL mpi_comm_rank(mpi_comm_world, rank, ierror)
70  IF (ierror /= mpi_success) &
71  CALL test_abort('mpi_comm_rank failed', &
72  __file__, &
73  __line__)
74  CALL mpi_comm_size(mpi_comm_world, world_size, ierror)
75  IF (ierror /= mpi_success) &
76  CALL test_abort('mpi_comm_size failed', &
77  __file__, &
78  __line__)
79 
80  IF (world_size > 1) THEN
81  CALL test_4redist
82  CALL test_rr_exchange
83  END IF
84 
85  IF (test_err_count() /= 0) &
86  CALL test_abort("non-zero error count!", &
87  __file__, &
88  __line__)
89  CALL xt_finalize
90  CALL finish_mpi
91 CONTAINS
92  SUBROUTINE build_idxlists(indices_a, indices_b, indices_all)
93  TYPE(xt_idxlist), INTENT(out) :: indices_a, indices_b, indices_all
94 
95  TYPE(xt_idxlist) :: indices_a_(2)
96  INTEGER :: i
97  INTEGER(xt_int_kind), PARAMETER :: start = 0
98  INTEGER(xt_int_kind) :: global_size(2), local_start(2, 2)
99  INTEGER :: local_size(2)
100 
101  TYPE(xt_stripe) :: stripe
102 
103  global_size(1) = int(2 * world_size, xi)
104  global_size(2) = int(world_size**2, xi)
105  local_size = world_size
106  local_start = reshape((/ 0_xi, int(rank*world_size, xi), &
107  int(world_size, xi), &
108  int((world_size-(rank+1))*world_size, xi) /), (/ 2, 2 /))
109 
110  DO i = 1, 2
111  indices_a_(i) = xt_idxsection_new(start, global_size, local_size, &
112  local_start(:, i))
113  END DO
114  indices_a = xt_idxlist_collection_new(indices_a_)
115 
116  CALL xt_idxlist_delete(indices_a_(1))
117  CALL xt_idxlist_delete(indices_a_(2))
118 
119  stripe = xt_stripe(int(rank * 2 * world_size**2, xi), 1_xi, 2*world_size**2)
120  indices_b = xt_idxstripes_new(stripe)
121 
122  stripe = xt_stripe(0_xi, 1_xi, 2*world_size**3)
123  indices_all = xt_idxstripes_new(stripe)
124  END SUBROUTINE build_idxlists
125 
126  SUBROUTINE test_4redist
127  ! redist test with four different redists
128  INTEGER, PARAMETER :: num_tx = 4
129  TYPE(xt_idxlist) :: indices_a, indices_b, indices_all
130  INTEGER(xt_int_kind), ALLOCATABLE :: index_vector_a(:), &
131  index_vector_b(:)
132  TYPE(xt_xmap) :: xmaps(num_tx)
133  TYPE(xt_redist) :: redists(num_tx), redist, redist_copy
134  INTEGER :: i
135 
136  ALLOCATE(index_vector_a(2*world_size**2), index_vector_b(2*world_size**2))
137  CALL build_idxlists(indices_a, indices_b, indices_all)
138 
139  xmaps(1) = xt_xmap_all2all_new(indices_a, indices_b, mpi_comm_world)
140  xmaps(2) = xt_xmap_all2all_new(indices_b, indices_a, mpi_comm_world)
141  xmaps(3) = xt_xmap_all2all_new(indices_a, indices_all, mpi_comm_world)
142  xmaps(4) = xt_xmap_all2all_new(indices_b, indices_all, mpi_comm_world)
143 
144  CALL xt_idxlist_get_indices(indices_a, index_vector_a)
145  CALL xt_idxlist_get_indices(indices_b, index_vector_b)
146 
147  CALL xt_idxlist_delete(indices_a)
148  CALL xt_idxlist_delete(indices_b)
149  CALL xt_idxlist_delete(indices_all)
150 
151  DO i = 1, num_tx
152  redists(i) = xt_redist_p2p_new(xmaps(i), xt_int_mpidt)
153  CALL xt_xmap_delete(xmaps(i))
154  END DO
155 
156  redist = xt_redist_collection_new(redists, num_tx, -1, mpi_comm_world)
157 
158  ! test communicator of redist
159  ! if (!test_communicator(xt_redist_get_MPI_Comm(redist), MPI_COMM_WORLD))
160  ! PUT_ERR("error in xt_redist_get_MPI_Comm\n");
161 
162  CALL xt_redist_delete(redists)
163 
164  CALL exchange_4redist(redist, index_vector_a, index_vector_b)
165  redist_copy = xt_redist_copy(redist)
166  CALL xt_redist_delete(redist)
167  CALL exchange_4redist(redist_copy, index_vector_a, index_vector_b)
168 
169  ! clean up
170  CALL xt_redist_delete(redist_copy)
171  END SUBROUTINE test_4redist
172 
173  SUBROUTINE exchange_4redist(redist, index_vector_a, index_vector_b)
174  TYPE(xt_redist), INTENT(in) :: redist
175  INTEGER(xt_int_kind), INTENT(in) :: index_vector_a(2*world_size**2), &
176  index_vector_b(2*world_size**2)
177  INTEGER(xt_int_kind), TARGET, ALLOCATABLE :: buf(:)
178  INTEGER(xt_int_kind), POINTER :: results_1(:), &
179  results_2(:), results_3(:), results_4(:)
180  INTEGER :: result_sizes(4), buf_size, ofs
181  INTEGER, PARAMETER :: result_spacing(4) = (/ 2, 14, 5, 8 /)
182 
183  result_sizes(1) = 2*world_size**2
184  result_sizes(2) = 2*world_size**2
185  result_sizes(3) = 2*world_size**3
186  result_sizes(4) = 2*world_size**3
187 
188  buf_size = sum(result_spacing) + sum(result_sizes)
189  ALLOCATE(buf(buf_size))
190 
191  ofs = result_spacing(1)
192  results_1 => buf(ofs+1:ofs+result_sizes(1))
193  ofs = ofs + result_sizes(1) + result_spacing(2)
194  results_2 => buf(ofs+1:ofs+result_sizes(2))
195  ofs = ofs + result_sizes(2) + result_spacing(3)
196  results_3 => buf(ofs+1:ofs+result_sizes(3))
197  ofs = ofs + result_sizes(3) + result_spacing(4)
198  results_4 => buf(ofs+1:ofs+result_sizes(4))
199 
200  CALL do_4redist(redist, index_vector_a, index_vector_b, &
201  results_1, results_2, results_3, results_4)
202 
203  CALL check_4redist_results(results_1, results_2, results_3, results_4, &
204  index_vector_a, index_vector_b)
205 
206  ! shift addresses around
207  IF (rank == 0) THEN
208  ofs = sum(result_spacing(1:2)) + sum(result_sizes(1:2))
209  results_3 => buf(ofs+1:ofs+result_sizes(3))
210  END IF
211 
212  CALL do_4redist(redist, index_vector_a, index_vector_b, &
213  results_1, results_2, results_3, results_4)
214 
215  CALL check_4redist_results(results_1, results_2, results_3, results_4, &
216  index_vector_a, index_vector_b)
217  ! clean up
218  DEALLOCATE(buf)
219  END SUBROUTINE exchange_4redist
220 
221  SUBROUTINE do_4redist(redist, index_vector_a, index_vector_b, &
222  results_1, results_2, results_3, results_4)
223  TYPE(xt_redist), INTENT(in) :: redist
224  INTEGER(xt_int_kind), INTENT(in), TARGET :: &
225  index_vector_a(*), index_vector_b(*)
226  INTEGER(xt_int_kind), INTENT(inout), TARGET :: &
227  results_1(*), results_2(*), results_3(*), results_4(*)
228 
229  TYPE(c_ptr) :: results(4), input(4)
230  results(1) = c_loc(results_1)
231  results(2) = c_loc(results_2)
232  results(3) = c_loc(results_3)
233  results(4) = c_loc(results_4)
234 
235  input(1) = c_loc(index_vector_a)
236  input(2) = c_loc(index_vector_b)
237  input(3) = c_loc(index_vector_a)
238  input(4) = c_loc(index_vector_b)
239 
240  CALL xt_redist_s_exchange(redist, 4, input, results)
241 
242  END SUBROUTINE do_4redist
243 
244  SUBROUTINE check_4redist_results(results_1, results_2, results_3, results_4, &
245  index_vector_a, index_vector_b)
246  INTEGER(xt_int_kind), INTENT(in) :: index_vector_a(:), index_vector_b(:), &
247  results_1(:), results_2(:), results_3(0:), results_4(0:)
248  INTEGER(xt_int_kind) :: i, n
249  LOGICAL :: p
250 
251  IF (any(results_1 /= index_vector_b)) &
252  CALL test_abort("error on xt_redist_s_exchange", &
253  __file__, &
254  __line__)
255 
256  IF (any(results_2 /= index_vector_a)) &
257  CALL test_abort("error on xt_redist_s_exchange", &
258  __file__, &
259  __line__)
260 
261  n = SIZE(results_3)
262  n = int(SIZE(results_3), xt_int_kind)
263  p = .false.
264  DO i = 0, n - 1
265  p = p .OR. results_3(i) /= i
266  END DO
267  IF (p) &
268  CALL test_abort("error on xt_redist_s_exchange", &
269  __file__, &
270  __line__)
271 
272  DO i = 0, n - 1
273  p = p .OR. results_4(i) /= i
274  END DO
275  IF (p) &
276  CALL test_abort("error on xt_redist_s_exchange", &
277  __file__, &
278  __line__)
279  END SUBROUTINE check_4redist_results
280 
281 
282  ! redist test with two redists that do a round robin exchange in
283  ! different directions
284  SUBROUTINE test_rr_exchange
285  TYPE(xt_idxlist) :: src_indices, dst_indices(2)
286  INTEGER(xt_int_kind) :: src_indices_(5)
287  INTEGER(xt_int_kind) :: i, temp, dst_indices_(5, 2)
288  TYPE(xt_xmap) :: xmaps(2)
289  TYPE(xt_redist) :: redists(2), redist, redist_copy
290 
291  DO i = 1_xi, 5_xi
292  src_indices_(i) = int(rank, xi) * 5_xi + (i - 1_xi)
293  dst_indices_(i, 1) = mod(src_indices_(i) + 1_xi, &
294  & int(world_size, xi) * 5_xi)
295  temp = src_indices_(i) - 1_xi
296  dst_indices_(i, 2) = merge(int(world_size, xi) * 5_xi - 1_xi, &
297  & temp, temp < 0_xi)
298  END DO
299 
300  src_indices = xt_idxvec_new(src_indices_, 5)
301  dst_indices(1) = xt_idxvec_new(dst_indices_(:, 1))
302  dst_indices(2) = xt_idxvec_new(dst_indices_(:, 2))
303 
304  xmaps(1) = xt_xmap_all2all_new(src_indices, dst_indices(1), mpi_comm_world)
305  xmaps(2) = xt_xmap_all2all_new(src_indices, dst_indices(2), mpi_comm_world)
306 
307  CALL xt_idxlist_delete(src_indices)
308  CALL xt_idxlist_delete(dst_indices)
309 
310  redists(1) = xt_redist_p2p_new(xmaps(1), xt_int_mpidt)
311  redists(2) = xt_redist_p2p_new(xmaps(2), xt_int_mpidt)
312 
313  CALL xt_xmap_delete(xmaps)
314 
315  redist = xt_redist_collection_new(redists, 2, -1, mpi_comm_world)
316 
317  ! test communicator of redist
318  ! IF (!test_communicator(xt_redist_get_MPI_Comm(redist), MPI_COMM_WORLD))
319  ! PUT_ERR("error in xt_redist_get_MPI_Comm\n");
320 
321  CALL xt_redist_delete(redists)
322 
323  CALL rr_exchange(redist, src_indices_, dst_indices_)
324  redist_copy = xt_redist_copy(redist)
325  CALL xt_redist_delete(redist)
326  CALL rr_exchange(redist_copy, src_indices_, dst_indices_)
327 
328  ! clean up
329  CALL xt_redist_delete(redist_copy)
330  END SUBROUTINE test_rr_exchange
331 
332  SUBROUTINE rr_exchange(redist, src_indices_, ref_dst_indices_)
333  TYPE(xt_redist), INTENT(in) :: redist
334  INTEGER(xt_int_kind), TARGET, INTENT(in) :: src_indices_(5)
335  INTEGER(xt_int_kind), INTENT(in) :: ref_dst_indices_(5, 2)
336 
337 
338  INTEGER(xt_int_kind), TARGET :: results(5,2)
339  TYPE(c_ptr) :: results_p(2), input(2)
340 
341  results = -1
342 
343  CALL xt_slice_c_loc(results(:,1), results_p(1))
344  CALL xt_slice_c_loc(results(:,2), results_p(2))
345 
346  input(1) = c_loc(src_indices_)
347  input(2) = c_loc(src_indices_)
348 
349  CALL xt_redist_s_exchange(redist, input, results_p)
350 
351  ! check results
352  IF (any(results /= ref_dst_indices_)) &
353  CALL test_abort("error on xt_redist_s_exchange", &
354  __file__, &
355  __line__)
356  END SUBROUTINE rr_exchange
357 
358 END PROGRAM test_redist_collection_parallel
359 !
360 ! Local Variables:
361 ! f90-continuation-indent: 5
362 ! coding: utf-8
363 ! indent-tabs-mode: nil
364 ! show-trailing-whitespace: t
365 ! require-trailing-newline: t
366 ! End:
367 !