1 /*
2 * Copyright (C) by Argonne National Laboratory
3 * See COPYRIGHT in top-level directory
4 */
5
6 /* This test checks accumulate ordering in three cases:
7 * 1) Default (most restricted)
8 * 2) None (no ordering)
9 * 3) Mixture of REPLACE and MIN_LOC/MAX_LOC.
10 * (In CH4/OFI, REPLACE may go through OFI but MIN_LOC/MAX_LOC has to go through active message.)
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <mpi.h>
16 #include <limits.h>
17 #include "mpitest.h"
18
19 typedef struct {
20 int val;
21 int loc;
22 } twoint_t;
23
24 #define ARRAY_LEN (8192/(sizeof(twoint_t)))
25
26 static int errs = 0;
27
verify_result(twoint_t * data,int len,twoint_t expected,const char * test_name)28 void verify_result(twoint_t * data, int len, twoint_t expected, const char *test_name)
29 {
30 int i;
31 for (i = 0; i < len; i++) {
32 if ((data[i].val != expected.val) || (data[i].loc != expected.loc)) {
33 errs++;
34 printf("%s: Expected: { loc = %d, val = %d } Actual: { loc = %d, val = %d }\n",
35 test_name, expected.loc, expected.val, data[i].loc, data[i].val);
36 }
37 }
38 }
39
40 /* Check non-deterministic result of none ordering.
41 * Expected result has two possibilities. */
verify_nondeterministic_result(twoint_t * data,int len,twoint_t * expected,const char * test_name)42 void verify_nondeterministic_result(twoint_t * data,
43 int len, twoint_t * expected, const char *test_name)
44 {
45 int i;
46 for (i = 0; i < len; i++) {
47 if (!((data[i].loc == expected[0].loc && data[0].val == expected[0].val)
48 || (data[i].loc == expected[1].loc && data[i].val == expected[1].val))) {
49 errs++;
50 printf
51 ("%s: Expected: { loc = %d, val = %d } or { loc = %d, val = %d }; Actual: { loc = %d, val = %d }\n",
52 test_name, expected[0].loc, expected[0].val, expected[1].loc, expected[1].val,
53 data[i].loc, data[i].val);
54 }
55 }
56 }
57
main(int argc,char ** argv)58 int main(int argc, char **argv)
59 {
60 int me, nproc, i;
61 twoint_t *data, *mine, *mine_plus, *expected;
62 MPI_Win win;
63 MPI_Info info_in;
64
65 MTest_Init(&argc, &argv);
66
67 MPI_Comm_rank(MPI_COMM_WORLD, &me);
68 MPI_Comm_size(MPI_COMM_WORLD, &nproc);
69
70 if (nproc < 2) {
71 printf("Run this program with 2 or more processes\n");
72 MPI_Abort(MPI_COMM_WORLD, 1);
73 }
74
75 data = (twoint_t *) calloc(ARRAY_LEN, sizeof(twoint_t));
76 if (me == 0) {
77 /* length of 2 in order to store all results for none ordering. */
78 expected = (twoint_t *) malloc(2 * sizeof(twoint_t));
79 }
80 if (me == nproc - 1) {
81 mine = (twoint_t *) malloc(ARRAY_LEN * sizeof(twoint_t));
82 mine_plus = (twoint_t *) malloc(ARRAY_LEN * sizeof(twoint_t));
83 for (i = 0; i < ARRAY_LEN; i++) {
84 mine[i].val = me + 1;
85 mine[i].loc = me;
86 mine_plus[i].val = me + 2;
87 mine_plus[i].loc = me + 1;
88 }
89 }
90
91 /* 1. Default ordering */
92 MPI_Win_create(data, sizeof(twoint_t) * ARRAY_LEN, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &win);
93 MPI_Win_fence(0, win);
94
95 /* Rank np-1 performs 2 WRITE to rank 0. */
96 /* 1.a. Single data test */
97 if (me == nproc - 1) {
98 MPI_Accumulate(mine, 1, MPI_2INT, 0, 0, 1, MPI_2INT, MPI_REPLACE, win);
99 MPI_Accumulate(mine_plus, 1, MPI_2INT, 0, 0, 1, MPI_2INT, MPI_REPLACE, win);
100 }
101
102 MPI_Win_fence(0, win);
103 if (me == 0) {
104 expected[0].loc = nproc;
105 expected[0].val = nproc + 1;
106 verify_result(data, 1, expected[0], "Single data test case for default ordering");
107 }
108
109 if (me == 0) {
110 data[0].loc = 0;
111 data[0].val = 0;
112 }
113 MPI_Win_fence(0, win);
114 /* 1.b. Large arrary test */
115 if (me == nproc - 1) {
116 MPI_Accumulate(mine, ARRAY_LEN, MPI_2INT, 0, 0, ARRAY_LEN, MPI_2INT, MPI_REPLACE, win);
117 MPI_Accumulate(mine_plus, ARRAY_LEN, MPI_2INT, 0, 0, ARRAY_LEN, MPI_2INT, MPI_REPLACE, win);
118 }
119
120 MPI_Win_fence(0, win);
121 if (me == 0) {
122 verify_result(data, ARRAY_LEN, expected[0], "Large array test case for default ordering");
123 }
124 /* MPI Implementation may ignore window info changes once created.
125 * Thus we should free current window and create a new window with required info. */
126 MPI_Win_free(&win);
127
128 /* 2. None ordering */
129 if (me == 0) {
130 /* reset data on rank 0. */
131 memset((void *) data, 0, ARRAY_LEN * sizeof(twoint_t));
132 }
133
134 MPI_Info_create(&info_in);
135 MPI_Info_set(info_in, "accumulate_ordering", "none");
136 MPI_Win_create(data, sizeof(twoint_t) * ARRAY_LEN, 1, info_in, MPI_COMM_WORLD, &win);
137 MPI_Info_free(&info_in);
138
139 MPI_Win_fence(0, win);
140
141 /* Rank np-1 performs 2 WRITE to rank 0. */
142 /* 2.a. Single data test */
143 if (me == nproc - 1) {
144 MPI_Accumulate(mine, 1, MPI_2INT, 0, 0, 1, MPI_2INT, MPI_REPLACE, win);
145 MPI_Accumulate(mine_plus, 1, MPI_2INT, 0, 0, 1, MPI_2INT, MPI_REPLACE, win);
146 }
147
148 MPI_Win_fence(0, win);
149 if (me == 0) {
150 expected[0].loc = nproc - 1;
151 expected[0].val = nproc;
152 expected[1].loc = nproc;
153 expected[1].val = nproc + 1;
154 verify_nondeterministic_result(data, 1, expected,
155 "Single data test case for none ordering");
156 }
157
158 if (me == 0) {
159 data[0].loc = 0;
160 data[0].val = 0;
161 }
162 MPI_Win_fence(0, win);
163 /* 2.b. Large array test */
164 if (me == nproc - 1) {
165 MPI_Accumulate(mine, ARRAY_LEN, MPI_2INT, 0, 0, ARRAY_LEN, MPI_2INT, MPI_REPLACE, win);
166 MPI_Accumulate(mine_plus, ARRAY_LEN, MPI_2INT, 0, 0, ARRAY_LEN, MPI_2INT, MPI_REPLACE, win);
167 }
168
169 MPI_Win_fence(0, win);
170 if (me == 0) {
171 verify_nondeterministic_result(data, ARRAY_LEN, expected,
172 "Large array test case for none ordering");
173 }
174
175 MPI_Win_free(&win);
176
177 /* 3. Mix MAX_LOC/MIN_LOC and MPI_REPLACE */
178 if (me == 0) {
179 /* reset data on rank 0. */
180 memset((void *) data, 0, ARRAY_LEN * sizeof(twoint_t));
181 }
182
183 MPI_Win_create(data, sizeof(twoint_t) * ARRAY_LEN, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &win);
184
185 MPI_Win_fence(0, win);
186
187 /* Rank np-1 performs 2 WRITE to rank 0. */
188 /* Test MAXLOC */
189 /* 3.a. Single data test */
190 if (me == nproc - 1) {
191 MPI_Accumulate(mine_plus, 1, MPI_2INT, 0, 0, 1, MPI_2INT, MPI_MAXLOC, win);
192 MPI_Accumulate(mine, 1, MPI_2INT, 0, 0, 1, MPI_2INT, MPI_REPLACE, win);
193 }
194
195 MPI_Win_fence(0, win);
196 if (me == 0) {
197 expected[0].loc = nproc - 1;
198 expected[0].val = nproc;
199 verify_result(data, 1, expected[0], "Single data test case for MAXLOC and REPLACE");
200 }
201
202 if (me == 0) {
203 data[0].loc = 0;
204 data[0].val = 0;
205 }
206 MPI_Win_fence(0, win);
207 /* 3.b. Large array test */
208 if (me == nproc - 1) {
209 MPI_Accumulate(mine_plus, ARRAY_LEN, MPI_2INT, 0, 0, ARRAY_LEN, MPI_2INT, MPI_MAXLOC, win);
210 MPI_Accumulate(mine, ARRAY_LEN, MPI_2INT, 0, 0, ARRAY_LEN, MPI_2INT, MPI_REPLACE, win);
211 }
212
213 MPI_Win_fence(0, win);
214 if (me == 0) {
215 verify_result(data, ARRAY_LEN, expected[0], "Large array test case for MAXLOC and REPLACE");
216 }
217
218 /* Test MINLOC */
219 if (me == 0) {
220 for (i = 0; i < ARRAY_LEN; i++) {
221 data[i].loc = INT_MAX;
222 data[i].val = INT_MAX;
223 }
224 }
225 MPI_Win_fence(0, win);
226 /* Rank np-1 performs 2 WRITE to rank 0. */
227 /* 3.c. Single data test */
228 if (me == nproc - 1) {
229 MPI_Accumulate(mine_plus, 1, MPI_2INT, 0, 0, 1, MPI_2INT, MPI_REPLACE, win);
230 MPI_Accumulate(mine, 1, MPI_2INT, 0, 0, 1, MPI_2INT, MPI_MINLOC, win);
231 }
232
233 MPI_Win_fence(0, win);
234 if (me == 0) {
235 expected[0].loc = nproc - 1;
236 expected[0].val = nproc;
237 verify_result(data, 1, expected[0], "Single data test case for REPLACE and MINLOC");
238 }
239
240 if (me == 0) {
241 data[0].loc = INT_MAX;
242 data[0].val = INT_MAX;
243 }
244 MPI_Win_fence(0, win);
245 /* 3.d. Large array test */
246 if (me == nproc - 1) {
247 MPI_Accumulate(mine_plus, ARRAY_LEN, MPI_2INT, 0, 0, ARRAY_LEN, MPI_2INT, MPI_REPLACE, win);
248 MPI_Accumulate(mine, ARRAY_LEN, MPI_2INT, 0, 0, ARRAY_LEN, MPI_2INT, MPI_MINLOC, win);
249 }
250
251 MPI_Win_fence(0, win);
252 if (me == 0) {
253 verify_result(data, ARRAY_LEN, expected[0], "Single data test case for REPLACE and MINLOC");
254 }
255
256 MPI_Win_free(&win);
257 if (me == nproc - 1) {
258 free(mine);
259 free(mine_plus);
260 }
261 if (me == 0)
262 free(expected);
263
264 MTest_Finalize(errs);
265 free(data);
266
267 return MTestReturnValue(errs);
268 }
269