Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'toufic' of github.com:Takishipp/simgrid
[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,
58              int getbufsize);
59 int RMACheck(int i, int *buf, MPI_Aint bufsize);
60 int RMACheckGet(int i, MPI_Win win, int *getbuf, MPI_Aint getsize);
61 void RMATestInit(int i, int *buf, MPI_Aint bufsize);
62
63 int main(int argc, char *argv[])
64 {
65     int errs = 0;
66     MPI_Win win;
67     int *rmabuffer = 0, *getbuf = 0;
68     MPI_Aint bufsize = 0, getbufsize = 0;
69     int master, partner, next, wrank, wsize, i;
70     int ntest = LAST_TEST;
71     int *srcbuf;
72
73     MTest_Init(&argc, &argv);
74
75     /* Determine who is responsible for each part of the test */
76     MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
77     MPI_Comm_size(MPI_COMM_WORLD, &wsize);
78     if (wsize < 3) {
79         fprintf(stderr, "This test requires at least 3 processes\n");
80         MPI_Abort(MPI_COMM_WORLD, 1);
81     }
82
83     master = 0;
84     partner = 1;
85     next = wrank + 1;
86     if (next == partner)
87         next++;
88     if (next >= wsize) {
89         next = 0;
90         if (next == partner)
91             next++;
92     }
93
94     /* Determine the last test to run (by default, run them all) */
95     for (i = 1; i < argc; i++) {
96         if (strcmp("-ntest", argv[i]) == 0) {
97             i++;
98             if (i < argc) {
99                 ntest = atoi(argv[i]);
100             }
101             else {
102                 fprintf(stderr, "Missing value for -ntest\n");
103                 MPI_Abort(MPI_COMM_WORLD, 1);
104             }
105         }
106     }
107
108     MPI_Type_vector(veccount, 1, stride, MPI_INT, &vectype);
109     MPI_Type_commit(&vectype);
110
111     /* Create the RMA window */
112     bufsize = 0;
113     if (wrank == master) {
114         bufsize = RMA_SIZE;
115         MPI_Alloc_mem(bufsize * sizeof(int), MPI_INFO_NULL, &rmabuffer);
116     }
117     else if (wrank == partner) {
118         getbufsize = RMA_SIZE;
119         getbuf = (int *) malloc(getbufsize * sizeof(int));
120         if (!getbuf) {
121             fprintf(stderr, "Unable to allocated %d bytes for getbuf\n", (int) getbufsize);
122             MPI_Abort(MPI_COMM_WORLD, 1);
123         }
124     }
125     srcbuf = malloc(RMA_SIZE * sizeof(*srcbuf));
126     assert(srcbuf);
127
128     MPI_Win_create(rmabuffer, bufsize * sizeof(int), sizeof(int), MPI_INFO_NULL,
129                    MPI_COMM_WORLD, &win);
130
131     /* Run a sequence of tests */
132     for (i = 0; i <= ntest; i++) {
133         if (wrank == master) {
134             MTestPrintfMsg(0, "Test %d\n", i);
135             /* Because this lock is local, it must return only when the
136              * lock is acquired */
137             MPI_Win_lock(MPI_LOCK_EXCLUSIVE, 0, master, win);
138             RMATestInit(i, rmabuffer, bufsize);
139             MPI_Send(MPI_BOTTOM, 0, MPI_INT, partner, i, MPI_COMM_WORLD);
140             MPI_Send(MPI_BOTTOM, 0, MPI_INT, next, i, MPI_COMM_WORLD);
141             MPI_Recv(MPI_BOTTOM, 0, MPI_INT, MPI_ANY_SOURCE, i, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
142             MPI_Win_unlock(master, win);
143             MPI_Recv(MPI_BOTTOM, 0, MPI_INT, partner, i, MPI_COMM_WORLD, 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, MPI_STATUS_IGNORE);
148             MPI_Win_lock(MPI_LOCK_EXCLUSIVE, 0, master, win);
149             RMATest(i, win, master, srcbuf, RMA_SIZE, getbuf, getbufsize);
150             MPI_Win_unlock(master, win);
151             errs += RMACheckGet(i, win, getbuf, getbufsize);
152             MPI_Send(MPI_BOTTOM, 0, MPI_INT, master, i, MPI_COMM_WORLD);
153         }
154         else {
155             MPI_Recv(MPI_BOTTOM, 0, MPI_INT, MPI_ANY_SOURCE, i, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
156             MPI_Send(MPI_BOTTOM, 0, MPI_INT, next, i, MPI_COMM_WORLD);
157         }
158     }
159
160     if (rmabuffer) {
161         MPI_Free_mem(rmabuffer);
162     }
163     if (getbuf) {
164         free(getbuf);
165     }
166     free(srcbuf);
167     MPI_Win_free(&win);
168     MPI_Type_free(&vectype);
169
170     MTest_Finalize(errs);
171     MPI_Finalize();
172     return MTestReturnValue(errs);
173 }
174
175 /* Perform the tests.
176  *
177  * The srcbuf must be passed in because the buffer must remain valid
178  * until the subsequent unlock call. */
179 void RMATest(int i, MPI_Win win, int master, int *srcbuf, int srcbufsize, int *getbuf,
180              int getbufsize)
181 {
182     int j, k;
183     int *source = srcbuf;
184     assert(srcbufsize == RMA_SIZE);
185
186     for (j = 0; j < srcbufsize; j++)
187         source[j] = -j;
188
189     switch (i) {
190     case 0:    /* Single short put (1 word at OFFSET_1) */
191         source[0] = PUT_VAL;
192         MPI_Put(source, 1, MPI_INT, master, OFFSET_1, 1, MPI_INT, win);
193         break;
194     case 1:    /* Single short accumulate (1 word of value 17 at OFFSET_2) */
195         source[0] = ACC_VAL;
196         MPI_Accumulate(source, 1, MPI_INT, master, 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, OFFSET_2, 1, vectype, MPI_SUM, win);
213         break;
214     case 5:    /* Datatype single get (strided get) */
215         for (j = 0; j < veccount; j++) {
216             getbuf[j] = -j;
217         }
218         MPI_Get(getbuf, 1, vectype, master, OFFSET_3, 1, vectype, win);
219         break;
220     case 6:    /* a few small puts (like strided put, but 1 word at a time) */
221         for (j = 0; j < veccount; j++) {
222             source[j * stride] = PUT_VAL + j;
223         }
224         for (j = 0; j < veccount; j++) {
225             MPI_Put(source + j * stride, 1, MPI_INT, master,
226                     OFFSET_1 + j * stride, 1, MPI_INT, win);
227         }
228         break;
229     case 7:    /* a few small accumulates (like strided acc, but 1 word at a time) */
230         for (j = 0; j < veccount; j++) {
231             source[j * stride] = ACC_VAL + j;
232         }
233         for (j = 0; j < veccount; j++) {
234             MPI_Accumulate(source + j * stride, 1, MPI_INT, master,
235                            OFFSET_2 + j * stride, 1, MPI_INT, MPI_SUM, win);
236         }
237         break;
238     case 8:    /* a few small gets (like strided get, but 1 word at a time) */
239         for (j = 0; j < veccount; j++) {
240             getbuf[j * stride] = -j;
241         }
242         for (j = 0; j < veccount; j++) {
243             MPI_Get(getbuf + j * stride, 1, MPI_INT, master,
244                     OFFSET_3 + j * stride, 1, MPI_INT, win);
245         }
246         break;
247     case 9:    /* Single long put (OFFSET_1) */
248         for (j = 0; j < longcount; j++)
249             source[j] = j;
250         MPI_Put(source, longcount, MPI_INT, master, OFFSET_1, longcount, MPI_INT, win);
251         break;
252     case 10:   /* Single long accumulate (OFFSET_2) */
253         for (j = 0; j < longcount; j++)
254             source[j] = j;
255         MPI_Accumulate(source, longcount, MPI_INT, master,
256                        OFFSET_2, longcount, MPI_INT, MPI_SUM, win);
257         break;
258     case 11:   /* Single long get (OFFSET_3) */
259         for (j = 0; j < longcount; j++)
260             getbuf[j] = -j;
261         MPI_Get(getbuf, longcount, MPI_INT, master, OFFSET_3, longcount, MPI_INT, win);
262         break;
263     case 12:   /* a few long puts (start at OFFSET_1, medcount) */
264         for (j = 0; j < mednum; j++) {
265             for (k = 0; k < medcount; k++) {
266                 source[j * medcount + k] = j * 2 * medcount + k;
267             }
268             MPI_Put(source + j * medcount, medcount, MPI_INT, master,
269                     OFFSET_1 + j * 2 * medcount, medcount, MPI_INT, win);
270         }
271         break;
272     case 13:   /* a few long accumulates (start at OFFSET_2, medcount) */
273         for (j = 0; j < mednum; j++) {
274             for (k = 0; k < medcount; k++) {
275                 source[j * medcount + k] = ACC_VAL + j * 2 * medcount + k;
276             }
277             MPI_Accumulate(source + j * medcount, medcount, MPI_INT, master,
278                            OFFSET_2 + j * 2 * medcount, medcount, MPI_INT, MPI_SUM, win);
279         }
280         break;
281     case 14:   /* a few long gets (start at OFFSET_3, medcount) */
282         for (j = 0; j < mednum; j++) {
283             for (k = 0; k < medcount; k++) {
284                 getbuf[j * medcount + k] = -(j * medcount + k);
285             }
286             MPI_Get(getbuf + j * medcount, medcount, MPI_INT, master,
287                     OFFSET_3 + j * 2 * medcount, medcount, MPI_INT, win);
288         }
289         break;
290     }
291 }
292
293 int RMACheck(int i, int *buf, MPI_Aint bufsize)
294 {
295     int j, k;
296     int errs = 0;
297
298     switch (i) {
299     case 0:    /* Single short put (1 word at OFFSET_1) */
300         if (buf[OFFSET_1] != PUT_VAL) {
301             errs++;
302             printf("case 0: value is %d should be %d\n", buf[OFFSET_1], PUT_VAL);
303         }
304         break;
305     case 1:    /* Single short accumulate (1 word of value 17 at OFFSET_2) */
306         if (buf[OFFSET_2] != ACC_VAL + OFFSET_2) {
307             errs++;
308             printf("case 1: value is %d should be %d\n", buf[OFFSET_2], ACC_VAL + OFFSET_2);
309         }
310         break;
311     case 2:    /* Single short get (1 word at OFFSET_3) */
312         /* See RMACheckGet */
313         break;
314     case 3:    /* Datatype single put (strided put) */
315     case 6:    /* a few small puts (like strided put, but 1 word at a time) */
316         /* FIXME: The conditional and increment are reversed below.  This looks
317          * like a bug, and currently prevents the following test from running. */
318         for (j = 0; j < veccount; j++) {
319             if (buf[j * stride] != PUT_VAL + j) {
320                 errs++;
321                 printf("case %d: value is %d should be %d\n", i, buf[j * stride], PUT_VAL + j);
322             }
323         }
324         break;
325     case 4:    /* Datatype single accumulate (strided acc) */
326     case 7:    /* a few small accumulates (like strided acc, but 1 word at a time) */
327         /* FIXME: The conditional and increment are reversed below.  This looks
328          * like a bug, and currently prevents the following test from running. */
329         for (j = 0; j < veccount;j++) {
330             if (buf[j * stride] != ACC_VAL + j + OFFSET_2 + j * stride) {
331                 errs++;
332                 printf("case %d: value is %d should be %d\n", i,
333                        buf[j * stride], ACC_VAL + j + OFFSET_2 + j * stride);
334             }
335         }
336         break;
337     case 5:    /* Datatype single get (strided get) */
338     case 8:    /* a few small gets (like strided get, but 1 word at a time) */
339         /* See RMACheckGet */
340         break;
341     case 9:    /* Single long put (OFFSET_1) */
342         for (j = 0; j < longcount; j++) {
343             if (buf[OFFSET_1 + j] != j) {
344                 errs++;
345                 printf("case 9: value is %d should be %d\n", buf[OFFSET_1 + j], OFFSET_1 + j);
346             }
347         }
348         break;
349     case 10:   /* Single long accumulate (OFFSET_2) */
350         for (j = 0; j < longcount; j++) {
351             if (buf[OFFSET_2 + j] != OFFSET_2 + j + j) {
352                 errs++;
353                 printf("case 10: value is %d should be %d\n", buf[OFFSET_2 + j], OFFSET_2 + j + j);
354             }
355         }
356         break;
357     case 11:   /* Single long get (OFFSET_3) */
358         /* See RMACheckGet */
359         break;
360     case 12:   /* a few long puts (start at OFFSET_1, medcount) */
361         for (j = 0; j < mednum; j++) {
362             for (k = 0; k < medcount; k++) {
363                 if (buf[OFFSET_1 + j * 2 * medcount + k] != j * 2 * medcount + k) {
364                     errs++;
365                     printf("case 12: value is %d should be %d\n",
366                            buf[OFFSET_1 + j * 2 * medcount + k], j * 2 * medcount + k);
367                 }
368             }
369         }
370         break;
371     case 13:   /* a few long accumulates (start at OFFSET_2, medcount) */
372         for (j = 0; j < mednum; j++) {
373             for (k = 0; k < medcount; k++) {
374                 if (buf[OFFSET_2 + j * 2 * medcount + k] !=
375                     OFFSET_2 + 2 * j * 2 * medcount + 2 * k + ACC_VAL) {
376                     errs++;
377                     printf("case 13: value is %d should be %d\n",
378                            buf[OFFSET_2 + j * 2 * medcount + k],
379                            OFFSET_2 + 2 * j * 2 * medcount + k + ACC_VAL);
380                 }
381             }
382         }
383         break;
384     case 14:   /* a few long gets (start at OFFSET_3, medcount) */
385         /* See RMACheckGet */
386         break;
387     default:
388         fprintf(stderr, "Unrecognized case %d\n", i);
389         errs++;
390         break;
391     }
392     return errs;
393 }
394
395 int RMACheckGet(int i, MPI_Win win, int *getbuf, MPI_Aint getsize)
396 {
397     int errs = 0;
398     int j, k;
399
400     /* */
401     switch (i) {
402     case 0:    /* Single short put (1 word at OFFSET_1) */
403         break;
404     case 1:    /* Single short accumulate (1 word of value 17 at OFFSET_2) */
405         break;
406     case 2:    /* Single short get (1 word at OFFSET_3) */
407         if (getbuf[0] != OFFSET_3) {
408             errs++;
409             printf("case 2: value is %d should be %d\n", getbuf[0], OFFSET_3);
410         }
411         break;
412     case 3:    /* Datatype single put (strided put) */
413         break;
414     case 4:    /* Datatype single accumulate (strided acc) */
415         break;
416     case 5:    /* Datatype single get (strided get) */
417     case 8:    /* a few small gets (like strided get, but 1 word at a time) */
418         for (j = 0; j < veccount; j++) {
419             if (getbuf[j * stride] != OFFSET_3 + j * stride) {
420                 errs++;
421                 printf("case %d: value is %d should be %d\n", i,
422                        getbuf[j * stride], OFFSET_3 + j * stride);
423             }
424         }
425
426         break;
427     case 6:    /* a few small puts (like strided put, but 1 word at a time) */
428         break;
429     case 7:    /* a few small accumulates (like strided acc, but 1 word at a time) */
430         break;
431     case 9:    /* Single long put (OFFSET_1) */
432         break;
433     case 10:   /* Single long accumulate (OFFSET_2) */
434         break;
435     case 11:   /* Single long get (OFFSET_3) */
436         for (j = 0; j < longcount; j++) {
437             if (getbuf[j] != OFFSET_3 + j) {
438                 errs++;
439                 printf("case 11: value is %d should be %d\n", getbuf[j], OFFSET_3 + j);
440             }
441         }
442         break;
443     case 12:   /* a few long puts (start at OFFSET_1, medcount) */
444         break;
445     case 13:   /* a few long accumulates (start at OFFSET_2, medcount) */
446         break;
447     case 14:   /* a few long gets (start at OFFSET_3, medcount) */
448         for (j = 0; j < mednum; j++) {
449             for (k = 0; k < medcount; k++) {
450                 if (getbuf[j * medcount + k] != OFFSET_3 + j * 2 * medcount + k) {
451                     errs++;
452                     printf("case 14: buf[%d] value is %d should be %d\n",
453                            j * medcount + k,
454                            getbuf[j * medcount + k], OFFSET_3 + j * 2 * medcount + k);
455                 }
456             }
457         }
458         break;
459     default:
460         fprintf(stderr, "Unrecognized case %d\n", i);
461         errs++;
462         break;
463     }
464     return errs;
465 }
466
467
468 void RMATestInit(int i, int *buf, MPI_Aint bufsize)
469 {
470     int j;
471     for (j = 0; j < bufsize; j++) {
472         buf[j] = j;
473     }
474 }