Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of https://github.com/mpoquet/simgrid
[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, 
98                  rank + i*wsize, 1, MPI_INT, win );
99         MPI_Put( &localbuf[i], 1, MPI_INT, trank, 
100                  rank + (i+NELM)*wsize, 1, MPI_INT, win );
101         MPI_Win_unlock( trank, win );
102     }
103     MPI_Barrier( MPI_COMM_WORLD );
104     if (rank == trank) {
105         MPI_Win_lock( MPI_LOCK_EXCLUSIVE, trank, 0, win );
106         toterrs += testValues( 1, NELM, wsize, rmabuf, "Multiple puts (1)" );
107         toterrs += testValues( 1, NELM, wsize, rmabuf + wsize*NELM,
108                                "Multiple puts (2)" );
109         MPI_Win_unlock( trank, win );
110     }
111     MPI_Barrier( MPI_COMM_WORLD );
112     /* Reinit the rmabuf */
113     for (i=0; i<windowsize; i++) {
114       rmabuf[i] = -1;
115     }
116     MPI_Barrier( MPI_COMM_WORLD );
117
118     /* Single put with contention */
119     trank = 0;
120     for (i=0; i<NELM; i++) {
121         MPI_Win_lock( MPI_LOCK_EXCLUSIVE, trank, 0, win );
122         MPI_Put( &localbuf[i], 1, MPI_INT, trank, rank + i*wsize, 1, MPI_INT, 
123                  win );
124         MPI_Win_unlock( trank, win );
125     }
126     MPI_Barrier( MPI_COMM_WORLD );
127     if (rank == trank) {
128         MPI_Win_lock( MPI_LOCK_EXCLUSIVE, trank, 0, win );
129         toterrs += testValues( 1, NELM, wsize, rmabuf, "Single put" );
130         MPI_Win_unlock( trank, win );
131     }
132
133     /* Reinit the rmabuf */
134     for (i=0; i<windowsize; i++) {
135         rmabuf[i] = -1;
136     }
137     /* Longer puts with contention at trank */
138     MPI_Barrier( MPI_COMM_WORLD );
139     for (i=0; i<NELM; i++) {
140         MPI_Win_lock( MPI_LOCK_EXCLUSIVE, trank, 0, win );
141         if (rank != trank) {
142             MPI_Put( &localbuf2[i*NBLOCK], NBLOCK, MPI_INT, trank, 
143                      NELM * wsize + NBLOCK*(rank+i*wsize), NBLOCK, 
144                      MPI_INT, win );
145             MPI_Put( &localbuf2[i*NBLOCK], NBLOCK, MPI_INT, trank, 
146                      NELM * wsize + NBLOCK*(rank+(i+NELM)*wsize), NBLOCK, 
147                      MPI_INT, win );
148         }
149         MPI_Put( &localbuf[i], 1, MPI_INT, trank, rank+i*wsize, 1, MPI_INT, 
150                  win );
151         MPI_Win_unlock( trank, win );
152     }
153     MPI_Barrier( MPI_COMM_WORLD );
154     if (rank == trank) {
155         /* For simplicity in testing, set the values that rank==trank
156            would have set. */
157         for (i=0; i<NELM; i++) {
158             for (j=0; j<NBLOCK; j++) {
159                 rmabuf[NELM*wsize + NBLOCK*(trank+i*wsize) + j] = 
160                     j + NBLOCK*(trank +i*wsize);
161                 rmabuf[NELM*wsize + NBLOCK*(trank+(i+NELM)*wsize) + j] = 
162                     j + NBLOCK*(trank + i*wsize);
163             }
164         }
165         MPI_Win_lock( MPI_LOCK_EXCLUSIVE, trank, 0, win );
166         toterrs += testValues( 1, NELM, wsize, rmabuf, "Long puts (1)" );
167         toterrs += testValues( NBLOCK, NELM, wsize, rmabuf + NELM * wsize,
168                                "Long puts(2)" );
169         toterrs += testValues( NBLOCK, NELM, wsize, 
170                                rmabuf + NELM * wsize * (1 + NBLOCK),
171                                "Long puts(3)" );
172         MPI_Win_unlock( trank, win );
173     }
174     
175     /* Reinit the rmabuf */
176     for (i=0; i<windowsize; i++) {
177         rmabuf[i] = -1;
178     }
179     for (i=0; i< NELM; i++) 
180         vals[i] = -2;
181     
182     /* Put mixed with Get */
183     MPI_Barrier( MPI_COMM_WORLD );
184     for (i=0; i<NELM; i++) {
185         MPI_Win_lock( MPI_LOCK_EXCLUSIVE, trank, 0, win );
186         if (rank != trank) {
187             MPI_Put( &localbuf2[i], NBLOCK, MPI_INT, trank, 
188                      NELM*wsize + NBLOCK*(rank + i*wsize), NBLOCK, MPI_INT, 
189                      win );
190             MPI_Put( &localbuf[i], 1, MPI_INT, trank, 
191                      rank + i*wsize, 1, MPI_INT, win );
192         }
193         else {
194             MPI_Get( &vals[i], 1, MPI_INT, trank, i, 1, MPI_INT, win );
195         }
196         MPI_Win_unlock( trank, win );
197     }
198     MPI_Barrier( MPI_COMM_WORLD );
199     if (rank == trank) {
200         /* Just test the Get */
201         for (i=0; i<wsize; i++) {
202             if (i == trank) {
203                 if (vals[i] != -1) {
204                     toterrs++;
205                     if (toterrs < MAX_ERRS_REPORT) {
206                         printf( "put/get: vals[%d] = %d, expected -1\n",
207                                 i, vals[i] );
208                     }
209                 }
210             }
211             else if (vals[i] != i && vals[i] != -1) {
212                 toterrs++;
213                 if (toterrs < MAX_ERRS_REPORT) {
214                     printf( "put/get: vals[%d] = %d, expected -1 or %d\n",
215                             i, vals[i], i );
216                 }
217             }
218         }
219     }
220
221     /* Contention only with get */
222     for (i=0; i<windowsize; i++) {
223         rmabuf[i] = -i;
224     }
225     for (i=0; i<NELM; i++)
226         vals[i] = -2;
227
228     MPI_Barrier( MPI_COMM_WORLD );
229     for (i=0; i<NELM; i++) {
230         MPI_Win_lock( MPI_LOCK_EXCLUSIVE, trank, 0, win );
231         MPI_Get( &vals[i], 1, MPI_INT, trank, i, 1, MPI_INT, win );
232         MPI_Win_unlock( trank, win );
233     }
234     MPI_Barrier( MPI_COMM_WORLD );
235     if (rank == trank) {
236         for (i=0; i<NELM; i++) {
237             if (vals[i] != -i) {
238                 toterrs++;
239                 if (toterrs < MAX_ERRS_REPORT) {
240                     printf( "single get: vals[%d] = %d, expected %d\n",
241                             i, vals[i], -i );
242                 }
243             }
244         }
245     }
246
247     /* Contention with accumulate */
248     MPI_Barrier( MPI_COMM_WORLD );
249     for (i=0; i<NELM*wsize; i++) {
250         rmabuf[i] = 0;
251     }
252     MPI_Barrier( MPI_COMM_WORLD );
253     for (i=0; i<NELM; i++) {
254         MPI_Win_lock( MPI_LOCK_EXCLUSIVE, trank, 0, win );
255         MPI_Accumulate( &localbuf[i], 1, MPI_INT, trank, rank+i*wsize, 
256                         1, MPI_INT, MPI_SUM, win );
257         MPI_Accumulate( &localbuf[i], 1, MPI_INT, trank, rank+i*wsize, 
258                         1, MPI_INT, MPI_SUM, win );
259         MPI_Win_unlock( trank, win );
260     }
261     MPI_Barrier( MPI_COMM_WORLD );
262     if (rank == trank) {
263         MPI_Win_lock( MPI_LOCK_EXCLUSIVE, trank, 0, win );
264         for (i=0; i<NELM * wsize; i++) {
265             if (rmabuf[i] != 2*i) {
266                 toterrs++;
267                 if (toterrs < MAX_ERRS_REPORT) {
268                     printf( "2 accumulate: rmabuf[%d] = %d, expected %d\n",
269                             i, rmabuf[i], 2*i );
270                 }
271             }
272         }
273         MPI_Win_unlock( trank, win );
274     }
275
276     MPI_Win_free( &win );
277
278     free( rmabuf );
279     free( localbuf );
280     free( localbuf2 );
281     free( vals );
282    
283     MTest_Finalize(toterrs);
284     MPI_Finalize(); 
285     return 0; 
286
287
288 /* Test the values in the rmabuf against the expected values.  Return the 
289    number of errors */
290 int testValues( int nb, int nelm, int wsize, int *rmabuf, const char *msg )
291 {
292     int i, errs = 0;
293                 
294     for (i=0; i<nb * nelm * wsize; i++) {
295         if (rmabuf[i] != i) {
296             if (toterrs + errs < MAX_ERRS_REPORT) {
297                 printf( "%s:rmabuf[%d] = %d expected %d\n", 
298                         msg, i, rmabuf[i], i );
299             }
300             errs++;
301         }
302     }
303
304     return errs;
305 }