Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Fix dist
[simgrid.git] / teshsuite / smpi / mpich3-test / coll / red4.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *
4  *  (C) 2003 by Argonne National Laboratory.
5  *      See COPYRIGHT in top-level directory.
6  */
7 #include "mpi.h"
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include "mpitest.h"
11
12 /*
13 static char MTEST_Descrip[] = "Test MPI_Reduce with non-commutative user-define operations and arbitrary root";
14 */
15
16 /*
17  * This tests that the reduce operation respects the noncommutative flag.
18  * and that can distinguish between P_{root} P_{root+1}
19  * ... P_{root-1} and P_0 ... P_{size-1} .  The MPI standard clearly
20  * specifies that the result is P_0 ... P_{size-1}, independent of the root
21  * (see 4.9.4 in MPI-1)
22  */
23
24 /* This implements a simple matrix-matrix multiply.  This is an associative
25    but not commutative operation.  The matrix size is set in matSize;
26    the number of matrices is the count argument. The matrix is stored
27    in C order, so that
28      c(i,j) is cin[j+i*matSize]
29  */
30 #define MAXCOL 256
31 static int matSize = 0;         /* Must be < MAXCOL */
32
33 void uop(void *cinPtr, void *coutPtr, int *count, MPI_Datatype * dtype);
34 void uop(void *cinPtr, void *coutPtr, int *count, MPI_Datatype * dtype)
35 {
36     const int *cin;
37     int *cout;
38     int i, j, k, nmat;
39     int tempCol[MAXCOL];
40
41     if (*count != 1)
42         printf("Panic!\n");
43     for (nmat = 0; nmat < *count; nmat++) {
44         cin = (const int *) cinPtr;
45         cout = (int *) coutPtr;
46         for (j = 0; j < matSize; j++) {
47             for (i = 0; i < matSize; i++) {
48                 tempCol[i] = 0;
49                 for (k = 0; k < matSize; k++) {
50                     /* col[i] += cin(i,k) * cout(k,j) */
51                     tempCol[i] += cin[k + i * matSize] * cout[j + k * matSize];
52                 }
53             }
54             for (i = 0; i < matSize; i++) {
55                 cout[j + i * matSize] = tempCol[i];
56             }
57         }
58         cinPtr = (int *) cinPtr + matSize * matSize;
59         coutPtr = (int *) coutPtr + matSize * matSize;
60     }
61 }
62
63 /* Initialize the integer matrix as a permutation of rank with rank+1.
64    If we call this matrix P_r, we know that product of P_0 P_1 ... P_{size-1}
65    is the matrix with rows ordered as
66    1,size,2,3,4,...,size-1
67    (The matrix is basically a circular shift right,
68    shifting right n-1 steps for an n x n dimensional matrix, with the last
69    step swapping rows 1 and size)
70 */
71
72 static void initMat(MPI_Comm comm, int mat[])
73 {
74     int i, size, rank;
75
76     MPI_Comm_rank(comm, &rank);
77     MPI_Comm_size(comm, &size);
78
79     /* Remember the matrix size */
80     matSize = size;
81
82     for (i = 0; i < matSize * matSize; i++)
83         mat[i] = 0;
84
85     for (i = 0; i < matSize; i++) {
86         if (i == rank)
87             mat[((i + 1) % matSize) + i * matSize] = 1;
88         else if (i == ((rank + 1) % matSize))
89             mat[((i + matSize - 1) % matSize) + i * matSize] = 1;
90         else
91             mat[i + i * matSize] = 1;
92     }
93 }
94
95 /* Compare a matrix with the identity matrix */
96 /*
97 static int isIdentity(MPI_Comm comm, int mat[])
98 {
99     int i, j, size, rank, errs = 0;
100
101     MPI_Comm_rank(comm, &rank);
102     MPI_Comm_size(comm, &size);
103
104     for (i=0; i<size; i++) {
105         for (j=0; j<size; j++) {
106             if (j == i) {
107                 if (mat[j+i*size] != 1) {
108                     printf("mat(%d,%d) = %d, should = 1\n",
109                             i, j, mat[j+i*size]);
110                     errs++;
111                 }
112             }
113             else {
114                 if (mat[j+i*size] != 0) {
115                     printf("mat(%d,%d) = %d, should = 0\n",
116                             i, j, mat[j+i*size]);
117                     errs++;
118                 }
119             }
120         }
121     }
122     return errs;
123 }
124 */
125
126 /* Compare a matrix with the identity matrix with rows permuted to as rows
127    1,size,2,3,4,5,...,size-1 */
128 static int isPermutedIdentity(MPI_Comm comm, int mat[])
129 {
130     int i, j, size, rank, errs = 0;
131
132     MPI_Comm_rank(comm, &rank);
133     MPI_Comm_size(comm, &size);
134
135     /* Check the first two last rows */
136     i = 0;
137     for (j = 0; j < size; j++) {
138         if (j == 0) {
139             if (mat[j] != 1) {
140                 printf("mat(%d,%d) = %d, should = 1\n", i, j, mat[j]);
141                 errs++;
142             }
143         }
144         else {
145             if (mat[j] != 0) {
146                 printf("mat(%d,%d) = %d, should = 0\n", i, j, mat[j]);
147                 errs++;
148             }
149         }
150     }
151     i = 1;
152     for (j = 0; j < size; j++) {
153         if (j == size - 1) {
154             if (mat[j + i * size] != 1) {
155                 printf("mat(%d,%d) = %d, should = 1\n", i, j, mat[j + i * size]);
156                 errs++;
157             }
158         }
159         else {
160             if (mat[j + i * size] != 0) {
161                 printf("mat(%d,%d) = %d, should = 0\n", i, j, mat[j + i * size]);
162                 errs++;
163             }
164         }
165     }
166     /* The remaint rows are shifted down by one */
167     for (i = 2; i < size; i++) {
168         for (j = 0; j < size; j++) {
169             if (j == i - 1) {
170                 if (mat[j + i * size] != 1) {
171                     printf("mat(%d,%d) = %d, should = 1\n", i, j, mat[j + i * size]);
172                     errs++;
173                 }
174             }
175             else {
176                 if (mat[j + i * size] != 0) {
177                     printf("mat(%d,%d) = %d, should = 0\n", i, j, mat[j + i * size]);
178                     errs++;
179                 }
180             }
181         }
182     }
183     return errs;
184 }
185
186 int main(int argc, char *argv[])
187 {
188     int errs = 0;
189     int rank, size, root;
190     int minsize = 2, count;
191     MPI_Comm comm;
192     int *buf, *bufout;
193     MPI_Op op;
194     MPI_Datatype mattype;
195
196     MTest_Init(&argc, &argv);
197
198     MPI_Op_create(uop, 0, &op);
199
200     while (MTestGetIntracommGeneral(&comm, minsize, 1)) {
201         if (comm == MPI_COMM_NULL)
202             continue;
203         MPI_Comm_size(comm, &size);
204         MPI_Comm_rank(comm, &rank);
205
206         if (size > MAXCOL) {
207             /* Skip because there are too many processes */
208             MTestFreeComm(&comm);
209             continue;
210         }
211
212         /* Only one matrix for now */
213         count = 1;
214
215         /* A single matrix, the size of the communicator */
216         MPI_Type_contiguous(size * size, MPI_INT, &mattype);
217         MPI_Type_commit(&mattype);
218
219         buf = (int *) malloc(count * size * size * sizeof(int));
220         if (!buf)
221             MPI_Abort(MPI_COMM_WORLD, 1);
222         bufout = (int *) malloc(count * size * size * sizeof(int));
223         if (!bufout)
224             MPI_Abort(MPI_COMM_WORLD, 1);
225
226         for (root = 0; root < size; root++) {
227             initMat(comm, buf);
228             MPI_Reduce(buf, bufout, count, mattype, op, root, comm);
229             if (rank == root) {
230                 errs += isPermutedIdentity(comm, bufout);
231             }
232
233             /* Try the same test, but using MPI_IN_PLACE */
234             initMat(comm, bufout);
235             if (rank == root) {
236                 MPI_Reduce(MPI_IN_PLACE, bufout, count, mattype, op, root, comm);
237             }
238             else {
239                 MPI_Reduce(bufout, NULL, count, mattype, op, root, comm);
240             }
241             if (rank == root) {
242                 errs += isPermutedIdentity(comm, bufout);
243             }
244         }
245         MPI_Type_free(&mattype);
246
247         free(buf);
248         free(bufout);
249
250         MTestFreeComm(&comm);
251     }
252
253     MPI_Op_free(&op);
254
255     MTest_Finalize(errs);
256     MPI_Finalize();
257     return 0;
258 }