Octopus
mpi_test.F90
Go to the documentation of this file.
1!! Copyright (C) 2022 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
21module mpi_test_oct_m
22 use global_oct_m
23 use math_oct_m
25 use mpi_oct_m
27 implicit none
28 private
29
30 public :: test_mpiwrappers
31
32contains
33
34 subroutine test_mpiwrappers
35 if (test_scatterv()) then
36 write(message(1), *) "scatterv: PASS"
37 else
38 write(message(1), *) "scatterv: FAIL"
39 end if
40 call messages_info(1)
41
42 if (test_gatherv()) then
43 write(message(1), *) "gatherv: PASS"
44 else
45 write(message(1), *) "gatherv: FAIL"
46 end if
47 call messages_info(1)
48
49 if (test_allgatherv()) then
50 write(message(1), *) "allgatherv: PASS"
51 else
52 write(message(1), *) "allgatherv: FAIL"
53 end if
54 call messages_info(1)
55
56 if (test_alltoallv()) then
57 write(message(1), *) "alltoallv: PASS"
58 else
59 write(message(1), *) "alltoallv: FAIL"
60 end if
61 call messages_info(1)
62 end subroutine test_mpiwrappers
63
64 logical function test_scatterv()
65 real(real64), allocatable :: sendbuf(:), irecvbuf(:), lrecvbuf(:)
66 integer, allocatable :: sendcnts(:), recvcounts(:)
67 integer(int32), allocatable :: isdispls(:)
68 integer(int64), allocatable :: lsdispls(:)
69 integer, parameter :: N = 10003
70 integer :: ii
71 logical :: equal, allequal
72
73 safe_allocate(sendcnts(1:mpi_world%size))
74 safe_allocate(isdispls(1:mpi_world%size))
75 safe_allocate(lsdispls(1:mpi_world%size))
76 safe_allocate(recvcounts(1:1))
77 do ii = 1, mpi_world%size
78 isdispls(ii) = (ii-1) * n / mpi_world%size
79 lsdispls(ii) = (ii-1) * n / mpi_world%size
80 sendcnts(ii) = ii * n / mpi_world%size - isdispls(ii)
81 end do
82 if (mpi_world%is_root()) then
83 safe_allocate(sendbuf(1:n))
84 do ii = 1, n
85 sendbuf(ii) = ii
86 end do
87 else
88 ! MPI_Scatterv ignores sendbuf on non-root ranks, but an unallocated
89 ! array must not be passed to the assumed-shape dummy argument
90 safe_allocate(sendbuf(1:1))
91 end if
92 recvcounts(1) = sendcnts(mpi_world%rank+1)
93 safe_allocate(irecvbuf(1:recvcounts(1)))
94 safe_allocate(lrecvbuf(1:recvcounts(1)))
95
96 call mpi_world%scatterv(sendbuf, sendcnts, isdispls, mpi_double_precision, irecvbuf, recvcounts(1), mpi_double_precision, 0)
97 call mpi_world%scatterv(sendbuf, sendcnts, lsdispls, mpi_double_precision, lrecvbuf, recvcounts(1), mpi_double_precision, 0)
98
99 equal = all(is_close(irecvbuf, lrecvbuf))
100 call mpi_world%allreduce(equal, allequal, 1, mpi_logical, mpi_land)
101 test_scatterv = allequal
102
103 safe_deallocate_a(sendcnts)
104 safe_deallocate_a(isdispls)
105 safe_deallocate_a(lsdispls)
106 safe_deallocate_a(recvcounts)
107 safe_deallocate_a(sendbuf)
108 safe_deallocate_a(irecvbuf)
109 safe_deallocate_a(lrecvbuf)
110 end function test_scatterv
111
112 logical function test_gatherv()
113 real(real64), allocatable :: sendbuf(:), irecvbuf(:), lrecvbuf(:)
114 integer, allocatable :: sendcnts(:), recvcounts(:)
115 integer(int32), allocatable :: irdispls(:)
116 integer(int64), allocatable :: lrdispls(:)
117 integer, parameter :: N = 10003
118 integer :: ii
119 logical :: equal, allequal
120
121 safe_allocate(recvcounts(1:mpi_world%size))
122 safe_allocate(irdispls(1:mpi_world%size))
123 safe_allocate(lrdispls(1:mpi_world%size))
124 safe_allocate(sendcnts(1:1))
125 do ii = 1, mpi_world%size
126 irdispls(ii) = (ii-1) * n / mpi_world%size
127 lrdispls(ii) = (ii-1) * n / mpi_world%size
128 recvcounts(ii) = ii * n / mpi_world%size - irdispls(ii)
129 end do
130 if (mpi_world%is_root()) then
131 safe_allocate(irecvbuf(1:n))
132 safe_allocate(lrecvbuf(1:n))
133 else
134 ! MPI_Gatherv ignores recvbuf on non-root ranks, but unallocated
135 ! arrays must not be passed to the assumed-shape dummy arguments
136 safe_allocate(irecvbuf(1:1))
137 safe_allocate(lrecvbuf(1:1))
138 end if
139 sendcnts(1) = recvcounts(mpi_world%rank+1)
140 safe_allocate(sendbuf(1:sendcnts(1)))
141 do ii = 1, sendcnts(1)
142 sendbuf(ii) = ii
143 end do
144
145 call mpi_world%gatherv(sendbuf, sendcnts(1), mpi_double_precision, irecvbuf, recvcounts, irdispls, mpi_double_precision, 0)
146 call mpi_world%gatherv(sendbuf, sendcnts(1), mpi_double_precision, lrecvbuf, recvcounts, lrdispls, mpi_double_precision, 0)
147
148 equal = .true.
149 if (mpi_world%is_root()) then
150 equal = all(is_close(irecvbuf, lrecvbuf))
151 end if
152 call mpi_world%allreduce(equal, allequal, 1, mpi_logical, mpi_land)
153 test_gatherv = allequal
154
155 safe_deallocate_a(recvcounts)
156 safe_deallocate_a(irdispls)
157 safe_deallocate_a(lrdispls)
158 safe_deallocate_a(sendcnts)
159 safe_deallocate_a(irecvbuf)
160 safe_deallocate_a(lrecvbuf)
161 safe_deallocate_a(sendbuf)
162 end function test_gatherv
163
164 logical function test_allgatherv()
165 real(real64), allocatable :: sendbuf(:), irecvbuf(:), lrecvbuf(:)
166 integer, allocatable :: sendcnts(:), recvcounts(:)
167 integer(int32), allocatable :: irdispls(:)
168 integer(int64), allocatable :: lrdispls(:)
169 integer, parameter :: n = 10003
170 integer :: ii
171 logical :: equal, allequal
172
173 safe_allocate(recvcounts(1:mpi_world%size))
174 safe_allocate(irdispls(1:mpi_world%size))
175 safe_allocate(lrdispls(1:mpi_world%size))
176 safe_allocate(sendcnts(1:1))
177 do ii = 1, mpi_world%size
178 irdispls(ii) = (ii-1) * n / mpi_world%size
179 lrdispls(ii) = (ii-1) * n / mpi_world%size
180 recvcounts(ii) = ii * n / mpi_world%size - irdispls(ii)
181 end do
182 safe_allocate(irecvbuf(1:n))
183 safe_allocate(lrecvbuf(1:n))
184 sendcnts(1) = recvcounts(mpi_world%rank+1)
185 safe_allocate(sendbuf(1:sendcnts(1)))
186 do ii = 1, sendcnts(1)
187 sendbuf(ii) = ii
188 end do
189
190 call mpi_world%allgatherv(sendbuf, sendcnts(1), mpi_double_precision, irecvbuf, recvcounts, irdispls, mpi_double_precision)
191 call mpi_world%allgatherv(sendbuf, sendcnts(1), mpi_double_precision, lrecvbuf, recvcounts, lrdispls, mpi_double_precision)
192
193 equal = all(is_close(irecvbuf, lrecvbuf))
194 call mpi_world%allreduce(equal, allequal, 1, mpi_logical, mpi_land)
195 test_allgatherv = allequal
196
197 safe_deallocate_a(recvcounts)
198 safe_deallocate_a(irdispls)
199 safe_deallocate_a(lrdispls)
200 safe_deallocate_a(sendcnts)
201 safe_deallocate_a(irecvbuf)
202 safe_deallocate_a(lrecvbuf)
203 safe_deallocate_a(sendbuf)
204 end function test_allgatherv
205
206 logical function test_alltoallv()
207 real(real64), allocatable :: sendbuf(:), irecvbuf(:), lrecvbuf(:)
208 integer, allocatable :: sendcnts(:), recvcounts(:)
209 integer(int32), allocatable :: isdispls(:), irdispls(:)
210 integer(int64), allocatable :: lsdispls(:), lrdispls(:)
211 integer, parameter :: n = 10003
212 integer :: ii
213 logical :: equal, allequal
214
215 safe_allocate(sendcnts(1:mpi_world%size))
216 safe_allocate(isdispls(1:mpi_world%size))
217 safe_allocate(lsdispls(1:mpi_world%size))
218 safe_allocate(irdispls(1:mpi_world%size))
219 safe_allocate(lrdispls(1:mpi_world%size))
220 safe_allocate(recvcounts(1:mpi_world%size))
221 do ii = 1, mpi_world%size
222 isdispls(ii) = (ii-1) * n / mpi_world%size
223 lsdispls(ii) = (ii-1) * n / mpi_world%size
224 sendcnts(ii) = ii * n / mpi_world%size - isdispls(ii)
225 end do
226 safe_allocate(sendbuf(1:n))
227 do ii = 1, n
228 sendbuf(ii) = ii
229 end do
230 call mpi_world%alltoall(sendcnts, 1, mpi_integer, recvcounts, 1, mpi_integer)
231 safe_allocate(irecvbuf(1:sum(recvcounts)))
232 safe_allocate(lrecvbuf(1:sum(recvcounts)))
233 irdispls(1) = 0
234 lrdispls(1) = 0
235 do ii = 2, mpi_world%size
236 irdispls(ii) = irdispls(ii-1) + recvcounts(ii-1)
237 lrdispls(ii) = lrdispls(ii-1) + recvcounts(ii-1)
238 end do
239
240 call mpi_world%alltoallv(sendbuf, sendcnts, isdispls, mpi_double_precision, &
241 irecvbuf, recvcounts, irdispls, mpi_double_precision)
242 call mpi_world%alltoallv(sendbuf, sendcnts, lsdispls, mpi_double_precision, &
243 lrecvbuf, recvcounts, lrdispls, mpi_double_precision)
244
245 equal = all(is_close(irecvbuf, lrecvbuf))
246 call mpi_world%allreduce(equal, allequal, 1, mpi_logical, mpi_land)
247 test_alltoallv = allequal
248
249 safe_deallocate_a(sendcnts)
250 safe_deallocate_a(isdispls)
251 safe_deallocate_a(lsdispls)
252 safe_deallocate_a(irdispls)
253 safe_deallocate_a(lrdispls)
254 safe_deallocate_a(recvcounts)
255 safe_deallocate_a(sendbuf)
256 safe_deallocate_a(irecvbuf)
257 safe_deallocate_a(lrecvbuf)
258 end function test_alltoallv
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_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:272
subroutine, public test_mpiwrappers
Definition: mpi_test.F90:130
logical function test_allgatherv()
Definition: mpi_test.F90:260
logical function test_gatherv()
Definition: mpi_test.F90:208
logical function test_scatterv()
Definition: mpi_test.F90:160
logical function test_alltoallv()
Definition: mpi_test.F90:302
int true(void)