Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
fix+activate rma test
[simgrid.git] / teshsuite / smpi / mpich3-test / rma / lockcontention2.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *  (C) 2010 by Argonne National Laboratory.
4  *      See COPYRIGHT in top-level directory.
5  */
6 #include "mpi.h"
7 #include "stdio.h"
8 #include "stdlib.h"
9 #include "mpitest.h"
10
11 /*
12  * Tests for lock contention, including special cases within the MPICH code
13  * (any MPI implementation should pass these tests; in the MPICH case, our
14  * coverage analysis showed that the lockcontention.c test was not covering
15  * all cases, and in fact, this test revealed a bug in the code).
16  *
17  * In all of these tests, each process writes (or accesses) the values
18  * rank + i*size_of_world for NELM times.
19  *
20  * This test strives to avoid operations not strictly permitted by MPI RMA,
21  * for example, it doesn't target the same locations with multiple put/get
22  * calls in the same access epoch.
23  */
24
25 #define NELM 200
26 #define NBLOCK 10
27 #define MAX_ERRS_REPORT 10
28
29 /*
30  *  Each process writes data into the rmabuf on the process with target rank
31  *  trank.  The final result in rmabuf are the consecutive integers starting
32  *  from 0.  Each process, however, does not write a consecutive block.
33  *  Instead, they write these locations:
34  *
35  *  for i=0,...,NELM-1
36  *     for j=0,...,NBLOCK-1
37  *         j + NBLOCK * (rank + i * wsize)
38  *
39  * The value written is the location.
40  *
41  * In many cases, multiple RMA operations are needed.  Where these must not
42  * overlap, the above pattern is replicated at NBLOCK*NELM*wsize.
43  * (NBLOCK is either 1 or NBLOCK in the code below, depending on use)
44  */
45
46 static int toterrs = 0;
47
48 int testValues(int, int, int, int *, const char *);
49
50 int main(int argc, char *argv[])
51 {
52     int rank, wsize, i, j, cnt;
53     int *rmabuf, *localbuf, *localbuf2, *vals;
54     MPI_Win win;
55     int trank = 0;
56     int windowsize;
57
58     MTest_Init(&argc, &argv);
59     MPI_Comm_size(MPI_COMM_WORLD, &wsize);
60     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
61
62     if (wsize < 2) {
63         fprintf(stderr, "Run this program with at least 2 processes\n");
64         MPI_Abort(MPI_COMM_WORLD, 1);
65     }
66
67     windowsize = (2 * NBLOCK + 2) * NELM * wsize;
68     rmabuf = (int *) malloc(windowsize * sizeof(int));
69     localbuf = (int *) malloc(NELM * sizeof(int));
70     localbuf2 = (int *) malloc(NELM * NBLOCK * sizeof(int));
71     vals = (int *) malloc(NELM * sizeof(int));
72
73     /*
74      * Initialize the buffers
75      */
76     for (i = 0; i < NELM; i++) {
77         localbuf[i] = rank + i * wsize;
78     }
79     cnt = 0;
80     for (i = 0; i < NELM; i++) {
81         for (j = 0; j < NBLOCK; j++) {
82             localbuf2[cnt++] = j + NBLOCK * (rank + i * wsize);
83         }
84     }
85     for (i = 0; i < windowsize; i++) {
86         rmabuf[i] = -1;
87     }
88
89     /* Create the window */
90     MPI_Win_create(rmabuf, windowsize * sizeof(int), sizeof(int), MPI_INFO_NULL,
91                    MPI_COMM_WORLD, &win);
92
93     /* Multiple puts, with contention at trank */
94     MPI_Barrier(MPI_COMM_WORLD);
95     for (i = 0; i < NELM; i++) {
96         MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
97         MPI_Put(&localbuf[i], 1, MPI_INT, trank, rank + i * wsize, 1, MPI_INT, win);
98         MPI_Put(&localbuf[i], 1, MPI_INT, trank, rank + (i + NELM) * wsize, 1, MPI_INT, win);
99         MPI_Win_unlock(trank, win);
100     }
101     MPI_Barrier(MPI_COMM_WORLD);
102     if (rank == trank) {
103         MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
104         toterrs += testValues(1, NELM, wsize, rmabuf, "Multiple puts (1)");
105         toterrs += testValues(1, NELM, wsize, rmabuf + wsize * NELM, "Multiple puts (2)");
106         MPI_Win_unlock(trank, win);
107     }
108     MPI_Barrier(MPI_COMM_WORLD);
109     /* Reinit the rmabuf */
110     for (i = 0; i < windowsize; i++) {
111         rmabuf[i] = -1;
112     }
113     MPI_Barrier(MPI_COMM_WORLD);
114
115     /* Single put with contention */
116     trank = 0;
117     for (i = 0; i < NELM; i++) {
118         MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
119         MPI_Put(&localbuf[i], 1, MPI_INT, trank, rank + i * wsize, 1, MPI_INT, win);
120         MPI_Win_unlock(trank, win);
121     }
122     MPI_Barrier(MPI_COMM_WORLD);
123     if (rank == trank) {
124         MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
125         toterrs += testValues(1, NELM, wsize, rmabuf, "Single put");
126         MPI_Win_unlock(trank, win);
127     }
128
129     /* Reinit the rmabuf */
130     for (i = 0; i < windowsize; i++) {
131         rmabuf[i] = -1;
132     }
133     /* Longer puts with contention at trank */
134     MPI_Barrier(MPI_COMM_WORLD);
135     for (i = 0; i < NELM; i++) {
136         MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
137         if (rank != trank) {
138             MPI_Put(&localbuf2[i * NBLOCK], NBLOCK, MPI_INT, trank,
139                     NELM * wsize + NBLOCK * (rank + i * wsize), NBLOCK, MPI_INT, win);
140             MPI_Put(&localbuf2[i * NBLOCK], NBLOCK, MPI_INT, trank,
141                     NELM * wsize + NBLOCK * (rank + (i + NELM) * wsize), NBLOCK, MPI_INT, win);
142         }
143         MPI_Put(&localbuf[i], 1, MPI_INT, trank, rank + i * wsize, 1, MPI_INT, win);
144         MPI_Win_unlock(trank, win);
145     }
146     MPI_Barrier(MPI_COMM_WORLD);
147     if (rank == trank) {
148         /* For simplicity in testing, set the values that rank==trank
149          * would have set. */
150         for (i = 0; i < NELM; i++) {
151             for (j = 0; j < NBLOCK; j++) {
152                 rmabuf[NELM * wsize + NBLOCK * (trank + i * wsize) + j] =
153                     j + NBLOCK * (trank + i * wsize);
154                 rmabuf[NELM * wsize + NBLOCK * (trank + (i + NELM) * wsize) + j] =
155                     j + NBLOCK * (trank + i * wsize);
156             }
157         }
158         MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
159         toterrs += testValues(1, NELM, wsize, rmabuf, "Long puts (1)");
160         toterrs += testValues(NBLOCK, NELM, wsize, rmabuf + NELM * wsize, "Long puts(2)");
161         toterrs += testValues(NBLOCK, NELM, wsize,
162                               rmabuf + NELM * wsize * (1 + NBLOCK), "Long puts(3)");
163         MPI_Win_unlock(trank, win);
164     }
165
166     /* Reinit the rmabuf */
167     for (i = 0; i < windowsize; i++) {
168         rmabuf[i] = -1;
169     }
170     for (i = 0; i < NELM; i++)
171         vals[i] = -2;
172
173     /* Put mixed with Get */
174     MPI_Barrier(MPI_COMM_WORLD);
175     for (i = 0; i < NELM; i++) {
176         MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
177         if (rank != trank) {
178             MPI_Put(&localbuf2[i], NBLOCK, MPI_INT, trank,
179                     NELM * wsize + NBLOCK * (rank + i * wsize), NBLOCK, MPI_INT, win);
180             MPI_Put(&localbuf[i], 1, MPI_INT, trank, rank + i * wsize, 1, MPI_INT, win);
181         }
182         else {
183             MPI_Get(&vals[i], 1, MPI_INT, trank, i, 1, MPI_INT, win);
184         }
185         MPI_Win_unlock(trank, win);
186     }
187     MPI_Barrier(MPI_COMM_WORLD);
188     if (rank == trank) {
189         /* Just test the Get */
190         for (i = 0; i < wsize; i++) {
191             if (i == trank) {
192                 if (vals[i] != -1) {
193                     toterrs++;
194                     if (toterrs < MAX_ERRS_REPORT) {
195                         printf("put/get: vals[%d] = %d, expected -1\n", i, vals[i]);
196                     }
197                 }
198             }
199             else if (vals[i] != i && vals[i] != -1) {
200                 toterrs++;
201                 if (toterrs < MAX_ERRS_REPORT) {
202                     printf("put/get: vals[%d] = %d, expected -1 or %d\n", i, vals[i], i);
203                 }
204             }
205         }
206     }
207
208     /* Contention only with get */
209     for (i = 0; i < windowsize; i++) {
210         rmabuf[i] = -i;
211     }
212     for (i = 0; i < NELM; i++)
213         vals[i] = -2;
214
215     MPI_Barrier(MPI_COMM_WORLD);
216     for (i = 0; i < NELM; i++) {
217         MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
218         MPI_Get(&vals[i], 1, MPI_INT, trank, i, 1, MPI_INT, win);
219         MPI_Win_unlock(trank, win);
220     }
221     MPI_Barrier(MPI_COMM_WORLD);
222     if (rank == trank) {
223         for (i = 0; i < NELM; i++) {
224             if (vals[i] != -i) {
225                 toterrs++;
226                 if (toterrs < MAX_ERRS_REPORT) {
227                     printf("single get: vals[%d] = %d, expected %d\n", i, vals[i], -i);
228                 }
229             }
230         }
231     }
232
233     /* Contention with accumulate */
234     MPI_Barrier(MPI_COMM_WORLD);
235     for (i = 0; i < NELM * wsize; i++) {
236         rmabuf[i] = 0;
237     }
238     MPI_Barrier(MPI_COMM_WORLD);
239     for (i = 0; i < NELM; i++) {
240         MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
241         MPI_Accumulate(&localbuf[i], 1, MPI_INT, trank, rank + i * wsize, 1, MPI_INT, MPI_SUM, win);
242         MPI_Accumulate(&localbuf[i], 1, MPI_INT, trank, rank + i * wsize, 1, MPI_INT, MPI_SUM, win);
243         MPI_Win_unlock(trank, win);
244     }
245     MPI_Barrier(MPI_COMM_WORLD);
246     if (rank == trank) {
247         MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
248         for (i = 0; i < NELM * wsize; i++) {
249             if (rmabuf[i] != 2 * i) {
250                 toterrs++;
251                 if (toterrs < MAX_ERRS_REPORT) {
252                     printf("2 accumulate: rmabuf[%d] = %d, expected %d\n", i, rmabuf[i], 2 * i);
253                 }
254             }
255         }
256         MPI_Win_unlock(trank, win);
257     }
258
259     MPI_Win_free(&win);
260
261     free(rmabuf);
262     free(localbuf);
263     free(localbuf2);
264     free(vals);
265
266     MTest_Finalize(toterrs);
267     MPI_Finalize();
268     return 0;
269 }
270
271 /* Test the values in the rmabuf against the expected values.  Return the
272    number of errors */
273 int testValues(int nb, int nelm, int wsize, int *rmabuf, const char *msg)
274 {
275     int i, errs = 0;
276
277     for (i = 0; i < nb * nelm * wsize; i++) {
278         if (rmabuf[i] != i) {
279             if (toterrs + errs < MAX_ERRS_REPORT) {
280                 printf("%s:rmabuf[%d] = %d expected %d\n", msg, i, rmabuf[i], i);
281             }
282             errs++;
283         }
284     }
285
286     return errs;
287 }