1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
3 * (C) 2010 by Argonne National Laboratory.
4 * See COPYRIGHT in top-level directory.
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).
17 * In all of these tests, each process writes (or accesses) the values
18 * rank + i*size_of_world for NELM times.
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.
27 #define MAX_ERRS_REPORT 10
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:
36 * for j=0,...,NBLOCK-1
37 * j + NBLOCK * (rank + i * wsize)
39 * The value written is the location.
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)
46 static int toterrs = 0;
48 int testValues( int, int, int, int *, const char * );
50 int main(int argc, char *argv[])
52 int rank, wsize, i, j, cnt;
53 int *rmabuf, *localbuf, *localbuf2, *vals;
58 MTest_Init(&argc,&argv);
59 MPI_Comm_size(MPI_COMM_WORLD,&wsize);
60 MPI_Comm_rank(MPI_COMM_WORLD,&rank);
63 fprintf(stderr, "Run this program with at least 2 processes\n");
64 MPI_Abort(MPI_COMM_WORLD,1);
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) );
74 * Initialize the buffers
76 for (i=0; i<NELM; i++) {
77 localbuf[i] = rank + i*wsize;
80 for (i=0; i<NELM; i++) {
81 for (j=0; j<NBLOCK; j++) {
82 localbuf2[cnt++] = j + NBLOCK * (rank + i*wsize);
85 for (i=0; i<windowsize; i++) {
89 /* Create the window */
90 MPI_Win_create(rmabuf, windowsize*sizeof(int), sizeof(int), MPI_INFO_NULL,
91 MPI_COMM_WORLD, &win);
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 );
103 MPI_Barrier( MPI_COMM_WORLD );
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 );
111 MPI_Barrier( MPI_COMM_WORLD );
112 /* Reinit the rmabuf */
113 for (i=0; i<windowsize; i++) {
116 MPI_Barrier( MPI_COMM_WORLD );
118 /* Single put with contention */
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,
124 MPI_Win_unlock( trank, win );
126 MPI_Barrier( MPI_COMM_WORLD );
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 );
133 /* Reinit the rmabuf */
134 for (i=0; i<windowsize; i++) {
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 );
142 MPI_Put( &localbuf2[i*NBLOCK], NBLOCK, MPI_INT, trank,
143 NELM * wsize + NBLOCK*(rank+i*wsize), NBLOCK,
145 MPI_Put( &localbuf2[i*NBLOCK], NBLOCK, MPI_INT, trank,
146 NELM * wsize + NBLOCK*(rank+(i+NELM)*wsize), NBLOCK,
149 MPI_Put( &localbuf[i], 1, MPI_INT, trank, rank+i*wsize, 1, MPI_INT,
151 MPI_Win_unlock( trank, win );
153 MPI_Barrier( MPI_COMM_WORLD );
155 /* For simplicity in testing, set the values that rank==trank
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);
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,
169 toterrs += testValues( NBLOCK, NELM, wsize,
170 rmabuf + NELM * wsize * (1 + NBLOCK),
172 MPI_Win_unlock( trank, win );
175 /* Reinit the rmabuf */
176 for (i=0; i<windowsize; i++) {
179 for (i=0; i< NELM; i++)
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 );
187 MPI_Put( &localbuf2[i], NBLOCK, MPI_INT, trank,
188 NELM*wsize + NBLOCK*(rank + i*wsize), NBLOCK, MPI_INT,
190 MPI_Put( &localbuf[i], 1, MPI_INT, trank,
191 rank + i*wsize, 1, MPI_INT, win );
194 MPI_Get( &vals[i], 1, MPI_INT, trank, i, 1, MPI_INT, win );
196 MPI_Win_unlock( trank, win );
198 MPI_Barrier( MPI_COMM_WORLD );
200 /* Just test the Get */
201 for (i=0; i<wsize; i++) {
205 if (toterrs < MAX_ERRS_REPORT) {
206 printf( "put/get: vals[%d] = %d, expected -1\n",
211 else if (vals[i] != i && vals[i] != -1) {
213 if (toterrs < MAX_ERRS_REPORT) {
214 printf( "put/get: vals[%d] = %d, expected -1 or %d\n",
221 /* Contention only with get */
222 for (i=0; i<windowsize; i++) {
225 for (i=0; i<NELM; i++)
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 );
234 MPI_Barrier( MPI_COMM_WORLD );
236 for (i=0; i<NELM; i++) {
239 if (toterrs < MAX_ERRS_REPORT) {
240 printf( "single get: vals[%d] = %d, expected %d\n",
247 /* Contention with accumulate */
248 MPI_Barrier( MPI_COMM_WORLD );
249 for (i=0; i<NELM*wsize; i++) {
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 );
261 MPI_Barrier( MPI_COMM_WORLD );
263 MPI_Win_lock( MPI_LOCK_EXCLUSIVE, trank, 0, win );
264 for (i=0; i<NELM * wsize; i++) {
265 if (rmabuf[i] != 2*i) {
267 if (toterrs < MAX_ERRS_REPORT) {
268 printf( "2 accumulate: rmabuf[%d] = %d, expected %d\n",
273 MPI_Win_unlock( trank, win );
276 MPI_Win_free( &win );
283 MTest_Finalize(toterrs);
288 /* Test the values in the rmabuf against the expected values. Return the
290 int testValues( int nb, int nelm, int wsize, int *rmabuf, const char *msg )
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 );