Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'mc'
[simgrid.git] / teshsuite / smpi / mpich3-test / rma / lockcontention3.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *  (C) 2012 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 #include <assert.h>
11 #include <string.h>
12
13 #define LAST_TEST 14
14 #define RMA_SIZE  2048
15 #define OFFSET_1  7
16 #define OFFSET_2  83
17 #define OFFSET_3  157
18
19 #define PUT_VAL 0xdcba97
20 #define ACC_VAL 10771134
21
22 /* 
23  * Additional tests for lock contention.  These are designed to exercise
24  * some of the optimizations within MPICH, but all are valid MPI programs.
25  * Tests structure includes
26  *    lock local (must happen at this time since application can use load
27  *                store after the lock)
28  *    send message to partner
29  *                                  receive message
30  *                                  send ack
31  *    receive ack
32  *    Provide a delay so that
33  *      the partner will see the
34  *      conflict
35  *                                  partner executes:
36  *                                  lock         // Note: this may block
37  *                                     rma operations (see below)
38  *                                  unlock
39  *    
40  *    unlock                        send back to partner
41  *    receive from partner 
42  *    check for correct data
43  *
44  * The delay may be implemented as a ring of message communication; this
45  * is likely to automatically scale the time to what is needed
46  */
47
48 /* Define a datatype to be used with */
49 int stride    = 11;
50 int veccount  = 7;
51 MPI_Datatype  vectype;
52 /* Define long RMA ops size */
53 int longcount = 512;
54 int medcount  = 127;
55 int mednum    = 4;
56
57 void RMATest( int i, MPI_Win win, int master, int *srcbuf, int srcbufsize, int *getbuf, int getbufsize );
58 int  RMACheck( int i, int *buf, MPI_Aint bufsize );
59 int  RMACheckGet( int i, MPI_Win win, int *getbuf, MPI_Aint getsize);
60 void RMATestInit( int i, int *buf, MPI_Aint bufsize );
61
62 int main( int argc, char *argv[] )
63 {
64     int      errs = 0;
65     MPI_Win  win;
66     int  *rmabuffer=0, *getbuf=0;
67     MPI_Aint bufsize=0, getbufsize=0;
68     int      master, partner, next, wrank, wsize, i;
69     int      ntest = LAST_TEST;
70     int *srcbuf;
71
72     MTest_Init( &argc, &argv );
73
74     /* Determine who is responsible for each part of the test */
75     MPI_Comm_rank( MPI_COMM_WORLD, &wrank );
76     MPI_Comm_size( MPI_COMM_WORLD, &wsize );
77     if (wsize < 3) {
78         fprintf( stderr, "This test requires at least 3 processes\n" );
79         MPI_Abort( MPI_COMM_WORLD, 1 );
80     }
81
82     master  = 0;
83     partner = 1;
84     next = wrank + 1;
85     if (next == partner) next++;
86     if (next >= wsize) {
87         next = 0;
88         if (next == partner) next++;
89     }
90
91     /* Determine the last test to run (by default, run them all) */
92     for (i=1; i<argc; i++) {
93         if (strcmp( "-ntest", argv[i] ) == 0) { 
94             i++;
95             if (i < argc) {
96                 ntest = atoi( argv[i] );
97             }
98             else {
99                 fprintf( stderr, "Missing value for -ntest\n" );
100                 MPI_Abort( MPI_COMM_WORLD, 1 );
101             }
102         }
103     }
104
105     MPI_Type_vector( veccount, 1, stride, MPI_INT, &vectype );
106     MPI_Type_commit( &vectype );
107
108     /* Create the RMA window */
109     bufsize = 0;
110     if (wrank == master) {
111         bufsize = RMA_SIZE;
112         MPI_Alloc_mem( bufsize*sizeof(int), MPI_INFO_NULL, &rmabuffer );
113     }
114     else if (wrank == partner) {
115         getbufsize = RMA_SIZE;
116         getbuf = (int *)malloc( getbufsize*sizeof(int) );
117         if (!getbuf) {
118             fprintf( stderr, "Unable to allocated %d bytes for getbuf\n", 
119                     (int)getbufsize );
120             MPI_Abort( MPI_COMM_WORLD, 1 );
121         }
122     }
123     srcbuf = malloc(RMA_SIZE*sizeof(*srcbuf));
124     assert(srcbuf);
125
126     MPI_Win_create( rmabuffer, bufsize, sizeof(int), MPI_INFO_NULL,
127                     MPI_COMM_WORLD, &win );
128     
129     /* Run a sequence of tests */
130     for (i=0; i<=ntest; i++) {
131         if (wrank == master) {
132             MTestPrintfMsg( 0, "Test %d\n", i );
133             /* Because this lock is local, it must return only when the
134              lock is acquired */
135             MPI_Win_lock( MPI_LOCK_EXCLUSIVE, 0, master, win );
136             RMATestInit( i, rmabuffer, bufsize );
137             MPI_Send( MPI_BOTTOM, 0, MPI_INT, partner, i, MPI_COMM_WORLD );
138             MPI_Send( MPI_BOTTOM, 0, MPI_INT, next, i, MPI_COMM_WORLD );
139             MPI_Recv( MPI_BOTTOM, 0, MPI_INT, MPI_ANY_SOURCE, i, 
140                       MPI_COMM_WORLD, MPI_STATUS_IGNORE );
141             MPI_Win_unlock( master, win );
142             MPI_Recv( MPI_BOTTOM, 0, MPI_INT, partner, i, MPI_COMM_WORLD, 
143                       MPI_STATUS_IGNORE );
144             errs += RMACheck( i, rmabuffer, bufsize );
145         }
146         else if (wrank == partner) {
147             MPI_Recv( MPI_BOTTOM, 0, MPI_INT, master, i, MPI_COMM_WORLD,
148                       MPI_STATUS_IGNORE );
149             MPI_Win_lock( MPI_LOCK_EXCLUSIVE, 0, master, win );
150             RMATest( i, win, master, srcbuf, RMA_SIZE, getbuf, getbufsize );
151             MPI_Win_unlock( master, win );
152             errs += RMACheckGet( i, win, getbuf, getbufsize );
153             MPI_Send( MPI_BOTTOM, 0, MPI_INT, master, i, MPI_COMM_WORLD );
154         }
155         else {
156             MPI_Recv( MPI_BOTTOM, 0, MPI_INT, MPI_ANY_SOURCE, i, 
157                       MPI_COMM_WORLD, MPI_STATUS_IGNORE );
158             MPI_Send( MPI_BOTTOM, 0, MPI_INT, next, i, MPI_COMM_WORLD );
159         }
160     }
161
162     if (rmabuffer) {
163         MPI_Free_mem( rmabuffer );
164     }
165     if (getbuf) {
166         free( getbuf );
167     }
168     MPI_Win_free( &win );
169     MPI_Type_free( &vectype );
170
171     MTest_Finalize( errs );
172     MPI_Finalize();
173     return MTestReturnValue( errs );
174 }
175
176 /* Perform the tests.
177  *
178  * The srcbuf must be passed in because the buffer must remain valid
179  * until the subsequent unlock call. */
180 void RMATest( int i, MPI_Win win, int master, int *srcbuf, int srcbufsize, int *getbuf, int getbufsize )
181 {
182     int j, k;
183     int *source = srcbuf;
184     assert(srcbufsize == RMA_SIZE);
185
186     for (j=0; j<srcbufsize; j++) source[j] = -j;
187
188     switch (i) {
189     case 0: /* Single short put (1 word at OFFSET_1) */
190         source[0] = PUT_VAL;
191         MPI_Put( source, 1, MPI_INT, master, OFFSET_1, 1, MPI_INT, win );
192         break;
193     case 1: /* Single short accumulate (1 word of value 17 at OFFSET_2) */
194         source[0] = ACC_VAL;
195         MPI_Accumulate( source, 1, MPI_INT, master, 
196                         OFFSET_2, 1, MPI_INT, MPI_SUM, win );
197         break;
198     case 2: /* Single short get (1 word at OFFSET_3) */
199         getbuf[0] = -1;
200         MPI_Get( getbuf, 1, MPI_INT, master, OFFSET_3, 1, MPI_INT, win );
201         break;
202     case 3: /* Datatype single put (strided put) */
203         for (j=0; j<veccount; j++) {
204             source[j*stride] = PUT_VAL + j;
205         }
206         MPI_Put( source, 1, vectype, master, OFFSET_1, 1, vectype, win );
207         break;
208     case 4: /* Datatype single accumulate (strided acc) */
209         for (j=0; j<veccount; j++) {
210             source[j*stride] = ACC_VAL + j;
211         }
212         MPI_Accumulate( source, 1, vectype, master, 
213                         OFFSET_2, 1, vectype, MPI_SUM, win );
214         break;
215     case 5: /* Datatype single get (strided get) */
216         for (j=0; j<veccount; j++) {
217             getbuf[j] = -j;
218         }
219         MPI_Get( getbuf, 1, vectype, master,
220                  OFFSET_3, 1, vectype, win );
221         break;
222     case 6: /* a few small puts (like strided put, but 1 word at a time) */
223         for (j=0; j<veccount; j++) {
224             source[j*stride] = PUT_VAL + j;
225         }
226         for (j=0; j<veccount; j++) {
227             MPI_Put( source + j*stride, 1, MPI_INT, master, 
228                      OFFSET_1+j*stride, 1, MPI_INT, win );
229         }
230         break;
231     case 7: /* a few small accumulates (like strided acc, but 1 word at a time )*/
232         for (j=0; j<veccount; j++) {
233             source[j*stride] = ACC_VAL + j;
234         }
235         for (j=0; j<veccount; j++) {
236             MPI_Accumulate( source + j*stride, 1, MPI_INT, master, 
237                             OFFSET_2+j*stride, 1, MPI_INT, MPI_SUM, win );
238         }
239         break;
240     case 8: /* a few small gets (like strided get, but 1 word at a time) */
241         for (j=0; j<veccount; j++) {
242             getbuf[j*stride] = -j;
243         }
244         for (j=0; j<veccount; j++) {
245             MPI_Get( getbuf + j*stride, 1, MPI_INT, master, 
246                      OFFSET_3+j*stride, 1, MPI_INT, win );
247         }
248         break;
249     case 9: /* Single long put (OFFSET_1) */
250         for (j=0; j<longcount; j++) source[j] = j;
251         MPI_Put( source, longcount, MPI_INT, master,
252                  OFFSET_1, longcount, MPI_INT, win ); 
253         break;
254     case 10: /* Single long accumulate (OFFSET_2) */
255         for (j=0; j<longcount; j++) source[j] = j;
256         MPI_Accumulate( source, longcount, MPI_INT, master, 
257                         OFFSET_2, longcount, MPI_INT, MPI_SUM, win );
258         break;
259     case 11: /* Single long get (OFFSET_3) */
260         for (j=0; j<longcount; j++) getbuf[j] = -j;
261         MPI_Get( getbuf, longcount, MPI_INT, master,
262                  OFFSET_3, longcount, MPI_INT, win ); 
263         break;
264     case 12: /* a few long puts (start at OFFSET_1, medcount ) */
265         for (j=0; j<mednum; j++) {
266             for (k=0; k<medcount; k++) {
267                 source[j*medcount+k] = j*2*medcount+k;
268             }
269             MPI_Put( source + j*medcount, medcount, MPI_INT, master,
270                      OFFSET_1 + j*2*medcount, medcount, MPI_INT, win );
271         }
272         break;
273     case 13: /* a few long accumulates (start at OFFSET_2, medcount) */
274         for (j=0; j<mednum; j++) {
275             for (k=0; k<medcount; k++) {
276                 source[j*medcount+k] = ACC_VAL + j*2*medcount+k;
277             }
278             MPI_Accumulate( source + j*medcount, medcount, MPI_INT, master,
279                             OFFSET_2 + j*2*medcount, medcount, MPI_INT, 
280                             MPI_SUM, win );
281         }
282         break;
283     case 14: /* a few long gets (start at OFFSET_3, medcount) */
284         for (j=0; j<mednum; j++) {
285             for (k=0; k<medcount; k++) {
286                 getbuf[j*medcount+k] = -(j*medcount+k);
287             }
288             MPI_Get( getbuf + j*medcount, medcount, MPI_INT, master,
289                             OFFSET_3 + j*2*medcount, medcount, MPI_INT, win );
290         }
291         break;
292     }
293 }
294
295 int RMACheck( int i, int *buf, MPI_Aint bufsize )
296 {
297     int j, k;
298     int errs = 0;
299
300     switch (i) {
301     case 0: /* Single short put (1 word at OFFSET_1) */
302         if (buf[OFFSET_1] != PUT_VAL) {
303             errs++;
304             printf( "case 0: value is %d should be %d\n", 
305                     buf[OFFSET_1], PUT_VAL );
306         }
307         break;
308     case 1: /* Single short accumulate (1 word of value 17 at OFFSET_2) */
309         if (buf[OFFSET_2] != ACC_VAL + OFFSET_2) {
310             errs++;
311             printf( "case 1: value is %d should be %d\n", 
312                     buf[OFFSET_2], ACC_VAL + OFFSET_2 );
313         }
314         break;
315     case 2: /* Single short get (1 word at OFFSET_3) */
316         /* See RMACheckGet */
317         break;
318     case 3: /* Datatype single put (strided put) */
319     case 6: /* a few small puts (like strided put, but 1 word at a time) */
320         /* FIXME: The conditional and increment are reversed below.  This looks
321          * like a bug, and currently prevents the following test from running. */
322         for (j=0; j++; j<veccount) {
323             if (buf[j*stride] != PUT_VAL + j) {
324                 errs++;
325                 printf( "case %d: value is %d should be %d\n", i,
326                         buf[j*stride], PUT_VAL+j );
327             }
328         }
329         break;
330     case 4: /* Datatype single accumulate (strided acc) */
331     case 7: /* a few small accumulates (like strided acc, but 1 word at a time )*/
332         /* FIXME: The conditional and increment are reversed below.  This looks
333          * like a bug, and currently prevents the following test from running. */
334         for (j=0; j++; j<veccount) {
335             if (buf[j*stride] != ACC_VAL + j + OFFSET_2 + j*stride) {
336                 errs++;
337                 printf( "case %d: value is %d should be %d\n", i,
338                         buf[j*stride], ACC_VAL+j+OFFSET_2+j*stride );
339             }
340         }
341         break;
342     case 5: /* Datatype single get (strided get) */
343     case 8: /* a few small gets (like strided get, but 1 word at a time) */
344         /* See RMACheckGet */
345         break;
346     case 9: /* Single long put (OFFSET_1) */
347         for (j=0; j<longcount; j++) {
348             if (buf[OFFSET_1+j] != j) {
349                 errs++;
350                 printf( "case 9: value is %d should be %d\n",
351                         buf[OFFSET_1+j], OFFSET_1 + j );
352             }
353         }
354         break;
355     case 10: /* Single long accumulate (OFFSET_2) */
356         for (j=0; j<longcount; j++) {
357             if (buf[OFFSET_2+j] != OFFSET_2 + j + j) {
358                 errs++;
359                 printf( "case 10: value is %d should be %d\n", 
360                         buf[OFFSET_2+j], OFFSET_2 + j + j );
361             }
362         }
363         break;
364     case 11: /* Single long get (OFFSET_3) */
365         /* See RMACheckGet */
366         break;
367     case 12: /* a few long puts (start at OFFSET_1, medcount ) */
368         for (j=0; j<mednum; j++) {
369             for (k=0; k<medcount; k++) {
370                 if (buf[OFFSET_1 + j*2*medcount + k] != 
371                     j*2*medcount+k ) {
372                     errs++;
373                     printf( "case 12: value is %d should be %d\n", 
374                             buf[OFFSET_1+j*2*medcount + k], j*2*medcount + k );
375                 }
376             }
377         }
378         break;
379     case 13: /* a few long accumulates (start at OFFSET_2, medcount) */
380         for (j=0; j<mednum; j++) {
381             for (k=0; k<medcount; k++) {
382                 if (buf[OFFSET_2 + j*2*medcount + k] != 
383                     OFFSET_2 + 2*j*2*medcount+2*k + ACC_VAL ) {
384                     errs++;
385                     printf( "case 13: value is %d should be %d\n", 
386                             buf[OFFSET_2+j*2*medcount + k], 
387                             OFFSET_2 + 2*j*2*medcount + k +ACC_VAL);
388                 }
389             }
390         }
391         break;
392     case 14: /* a few long gets (start at OFFSET_3, medcount) */
393         /* See RMACheckGet */
394         break;
395     default:
396         fprintf( stderr, "Unrecognized case %d\n", i );
397         errs++;
398         break;
399     }
400     return errs;
401 }
402
403 int RMACheckGet( int i, MPI_Win win, int *getbuf, MPI_Aint getsize)
404 {
405     int errs = 0;
406     int j, k;
407
408     /* */
409     switch (i) {
410     case 0: /* Single short put (1 word at OFFSET_1) */
411         break;
412     case 1: /* Single short accumulate (1 word of value 17 at OFFSET_2) */
413         break;
414     case 2: /* Single short get (1 word at OFFSET_3) */
415         if (getbuf[0] != OFFSET_3) {
416             errs++;
417             printf( "case 2: value is %d should be %d\n", 
418                     getbuf[0], OFFSET_3 );
419         }
420         break;
421     case 3: /* Datatype single put (strided put) */
422         break;
423     case 4: /* Datatype single accumulate (strided acc) */
424         break;
425     case 5: /* Datatype single get (strided get) */
426     case 8: /* a few small gets (like strided get, but 1 word at a time) */
427         for (j=0; j<veccount; j++) {
428             if (getbuf[j*stride] != OFFSET_3 + j*stride) {
429                 errs++;
430                 printf( "case %d: value is %d should be %d\n", i,
431                         getbuf[j*stride], OFFSET_3 + j*stride );
432             }
433         }
434         
435         break;
436     case 6: /* a few small puts (like strided put, but 1 word at a time) */
437         break;
438     case 7: /* a few small accumulates (like strided acc, but 1 word at a time )*/
439         break;
440     case 9: /* Single long put (OFFSET_1) */
441         break;
442     case 10: /* Single long accumulate (OFFSET_2) */
443         break;
444     case 11: /* Single long get (OFFSET_3) */
445         for (j=0; j<longcount; j++) {
446             if (getbuf[j] != OFFSET_3 + j) {
447                 errs++;
448                 printf( "case 11: value is %d should be %d\n",
449                         getbuf[j], OFFSET_3 + j );
450             }
451         }
452         break;
453     case 12: /* a few long puts (start at OFFSET_1, medcount ) */
454         break;
455     case 13: /* a few long accumulates (start at OFFSET_2, medcount) */
456         break;
457     case 14: /* a few long gets (start at OFFSET_3, medcount) */
458         for (j=0; j<mednum; j++) {
459             for (k=0; k<medcount; k++) {
460                 if (getbuf[j*medcount + k] != 
461                     OFFSET_3 + j*2*medcount+k ) {
462                     errs++;
463                     printf( "case 14: buf[%d] value is %d should be %d\n", 
464                             j*medcount + k,
465                             getbuf[j*medcount + k], 
466                             OFFSET_3 + j*2*medcount + k );
467                 }
468             }
469         }
470         break;
471     default:
472         fprintf( stderr, "Unrecognized case %d\n", i );
473         errs++;
474         break;
475     }
476     return errs;
477 }
478
479
480 void RMATestInit( int i, int *buf, MPI_Aint bufsize )
481 {
482     int j;
483     for (j=0; j<bufsize; j++) {
484         buf[j] = j;
485     }
486 }
487