1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
3 * (C) 2012 by Argonne National Laboratory.
4 * See COPYRIGHT in top-level directory.
19 #define PUT_VAL 0xdcba97
20 #define ACC_VAL 10771134
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
32 * Provide a delay so that
33 * the partner will see the
36 * lock // Note: this may block
37 * rma operations (see below)
40 * unlock send back to partner
41 * receive from partner
42 * check for correct data
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
48 /* Define a datatype to be used with */
52 /* Define long RMA ops size */
57 void RMATest(int i, MPI_Win win, int master, int *srcbuf, int srcbufsize, int *getbuf,
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);
63 int main(int argc, char *argv[])
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;
73 MTest_Init(&argc, &argv);
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);
79 fprintf(stderr, "This test requires at least 3 processes\n");
80 MPI_Abort(MPI_COMM_WORLD, 1);
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) {
99 ntest = atoi(argv[i]);
102 fprintf(stderr, "Missing value for -ntest\n");
103 MPI_Abort(MPI_COMM_WORLD, 1);
108 MPI_Type_vector(veccount, 1, stride, MPI_INT, &vectype);
109 MPI_Type_commit(&vectype);
111 /* Create the RMA window */
113 if (wrank == master) {
115 MPI_Alloc_mem(bufsize * sizeof(int), MPI_INFO_NULL, &rmabuffer);
117 else if (wrank == partner) {
118 getbufsize = RMA_SIZE;
119 getbuf = (int *) malloc(getbufsize * sizeof(int));
121 fprintf(stderr, "Unable to allocated %d bytes for getbuf\n", (int) getbufsize);
122 MPI_Abort(MPI_COMM_WORLD, 1);
125 srcbuf = malloc(RMA_SIZE * sizeof(*srcbuf));
128 MPI_Win_create(rmabuffer, bufsize * sizeof(int), sizeof(int), MPI_INFO_NULL,
129 MPI_COMM_WORLD, &win);
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);
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);
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);
161 MPI_Free_mem(rmabuffer);
168 MPI_Type_free(&vectype);
170 MTest_Finalize(errs);
172 return MTestReturnValue(errs);
175 /* Perform the tests.
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,
183 int *source = srcbuf;
184 assert(srcbufsize == RMA_SIZE);
186 for (j = 0; j < srcbufsize; j++)
190 case 0: /* Single short put (1 word at OFFSET_1) */
192 MPI_Put(source, 1, MPI_INT, master, OFFSET_1, 1, MPI_INT, win);
194 case 1: /* Single short accumulate (1 word of value 17 at OFFSET_2) */
196 MPI_Accumulate(source, 1, MPI_INT, master, OFFSET_2, 1, MPI_INT, MPI_SUM, win);
198 case 2: /* Single short get (1 word at OFFSET_3) */
200 MPI_Get(getbuf, 1, MPI_INT, master, OFFSET_3, 1, MPI_INT, win);
202 case 3: /* Datatype single put (strided put) */
203 for (j = 0; j < veccount; j++) {
204 source[j * stride] = PUT_VAL + j;
206 MPI_Put(source, 1, vectype, master, OFFSET_1, 1, vectype, win);
208 case 4: /* Datatype single accumulate (strided acc) */
209 for (j = 0; j < veccount; j++) {
210 source[j * stride] = ACC_VAL + j;
212 MPI_Accumulate(source, 1, vectype, master, OFFSET_2, 1, vectype, MPI_SUM, win);
214 case 5: /* Datatype single get (strided get) */
215 for (j = 0; j < veccount; j++) {
218 MPI_Get(getbuf, 1, vectype, master, OFFSET_3, 1, vectype, win);
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;
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);
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;
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);
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;
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);
247 case 9: /* Single long put (OFFSET_1) */
248 for (j = 0; j < longcount; j++)
250 MPI_Put(source, longcount, MPI_INT, master, OFFSET_1, longcount, MPI_INT, win);
252 case 10: /* Single long accumulate (OFFSET_2) */
253 for (j = 0; j < longcount; j++)
255 MPI_Accumulate(source, longcount, MPI_INT, master,
256 OFFSET_2, longcount, MPI_INT, MPI_SUM, win);
258 case 11: /* Single long get (OFFSET_3) */
259 for (j = 0; j < longcount; j++)
261 MPI_Get(getbuf, longcount, MPI_INT, master, OFFSET_3, longcount, MPI_INT, win);
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;
268 MPI_Put(source + j * medcount, medcount, MPI_INT, master,
269 OFFSET_1 + j * 2 * medcount, medcount, MPI_INT, win);
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;
277 MPI_Accumulate(source + j * medcount, medcount, MPI_INT, master,
278 OFFSET_2 + j * 2 * medcount, medcount, MPI_INT, MPI_SUM, win);
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);
286 MPI_Get(getbuf + j * medcount, medcount, MPI_INT, master,
287 OFFSET_3 + j * 2 * medcount, medcount, MPI_INT, win);
293 int RMACheck(int i, int *buf, MPI_Aint bufsize)
299 case 0: /* Single short put (1 word at OFFSET_1) */
300 if (buf[OFFSET_1] != PUT_VAL) {
302 printf("case 0: value is %d should be %d\n", buf[OFFSET_1], PUT_VAL);
305 case 1: /* Single short accumulate (1 word of value 17 at OFFSET_2) */
306 if (buf[OFFSET_2] != ACC_VAL + OFFSET_2) {
308 printf("case 1: value is %d should be %d\n", buf[OFFSET_2], ACC_VAL + OFFSET_2);
311 case 2: /* Single short get (1 word at OFFSET_3) */
312 /* See RMACheckGet */
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 for (j = 0; j < veccount; j++) {
317 if (buf[j * stride+OFFSET_1] != PUT_VAL + j) {
319 printf("case %d: value is %d should be %d\n", i, buf[j * stride+OFFSET_1], PUT_VAL + j);
323 case 4: /* Datatype single accumulate (strided acc) */
324 case 7: /* a few small accumulates (like strided acc, but 1 word at a time) */
325 for (j = 0; j < veccount;j++) {
326 if (buf[j * stride+OFFSET_2] != ACC_VAL + j + OFFSET_2 + j * stride) {
328 printf("case %d: value is %d should be %d\n", i,
329 buf[j * stride+OFFSET_2], ACC_VAL + j + OFFSET_2 + j * stride);
333 case 5: /* Datatype single get (strided get) */
334 case 8: /* a few small gets (like strided get, but 1 word at a time) */
335 /* See RMACheckGet */
337 case 9: /* Single long put (OFFSET_1) */
338 for (j = 0; j < longcount; j++) {
339 if (buf[OFFSET_1 + j] != j) {
341 printf("case 9: value is %d should be %d\n", buf[OFFSET_1 + j], OFFSET_1 + j);
345 case 10: /* Single long accumulate (OFFSET_2) */
346 for (j = 0; j < longcount; j++) {
347 if (buf[OFFSET_2 + j] != OFFSET_2 + j + j) {
349 printf("case 10: value is %d should be %d\n", buf[OFFSET_2 + j], OFFSET_2 + j + j);
353 case 11: /* Single long get (OFFSET_3) */
354 /* See RMACheckGet */
356 case 12: /* a few long puts (start at OFFSET_1, medcount) */
357 for (j = 0; j < mednum; j++) {
358 for (k = 0; k < medcount; k++) {
359 if (buf[OFFSET_1 + j * 2 * medcount + k] != j * 2 * medcount + k) {
361 printf("case 12: value is %d should be %d\n",
362 buf[OFFSET_1 + j * 2 * medcount + k], j * 2 * medcount + k);
367 case 13: /* a few long accumulates (start at OFFSET_2, medcount) */
368 for (j = 0; j < mednum; j++) {
369 for (k = 0; k < medcount; k++) {
370 if (buf[OFFSET_2 + j * 2 * medcount + k] !=
371 OFFSET_2 + 2 * j * 2 * medcount + 2 * k + ACC_VAL) {
373 printf("case 13: value is %d should be %d\n",
374 buf[OFFSET_2 + j * 2 * medcount + k],
375 OFFSET_2 + 2 * j * 2 * medcount + k + ACC_VAL);
380 case 14: /* a few long gets (start at OFFSET_3, medcount) */
381 /* See RMACheckGet */
384 fprintf(stderr, "Unrecognized case %d\n", i);
391 int RMACheckGet(int i, MPI_Win win, int *getbuf, MPI_Aint getsize)
398 case 0: /* Single short put (1 word at OFFSET_1) */
400 case 1: /* Single short accumulate (1 word of value 17 at OFFSET_2) */
402 case 2: /* Single short get (1 word at OFFSET_3) */
403 if (getbuf[0] != OFFSET_3) {
405 printf("case 2: value is %d should be %d\n", getbuf[0], OFFSET_3);
408 case 3: /* Datatype single put (strided put) */
410 case 4: /* Datatype single accumulate (strided acc) */
412 case 5: /* Datatype single get (strided get) */
413 case 8: /* a few small gets (like strided get, but 1 word at a time) */
414 for (j = 0; j < veccount; j++) {
415 if (getbuf[j * stride] != OFFSET_3 + j * stride) {
417 printf("case %d: value is %d should be %d\n", i,
418 getbuf[j * stride], OFFSET_3 + j * stride);
423 case 6: /* a few small puts (like strided put, but 1 word at a time) */
425 case 7: /* a few small accumulates (like strided acc, but 1 word at a time) */
427 case 9: /* Single long put (OFFSET_1) */
429 case 10: /* Single long accumulate (OFFSET_2) */
431 case 11: /* Single long get (OFFSET_3) */
432 for (j = 0; j < longcount; j++) {
433 if (getbuf[j] != OFFSET_3 + j) {
435 printf("case 11: value is %d should be %d\n", getbuf[j], OFFSET_3 + j);
439 case 12: /* a few long puts (start at OFFSET_1, medcount) */
441 case 13: /* a few long accumulates (start at OFFSET_2, medcount) */
443 case 14: /* a few long gets (start at OFFSET_3, medcount) */
444 for (j = 0; j < mednum; j++) {
445 for (k = 0; k < medcount; k++) {
446 if (getbuf[j * medcount + k] != OFFSET_3 + j * 2 * medcount + k) {
448 printf("case 14: buf[%d] value is %d should be %d\n",
450 getbuf[j * medcount + k], OFFSET_3 + j * 2 * medcount + k);
456 fprintf(stderr, "Unrecognized case %d\n", i);
464 void RMATestInit(int i, int *buf, MPI_Aint bufsize)
467 for (j = 0; j < bufsize; j++) {