Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Upgrade coll mpich testlist to new mpich
[simgrid.git] / teshsuite / smpi / mpich3-test / coll / red3.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";
14 */
15 /*
16  * This tests that the reduce operation respects the noncommutative flag.
17  * See red4.c for a version that can distinguish between P_{root} P_{root+1}
18  * ... P_{root-1} and P_0 ... P_{size-1} .  The MPI standard clearly
19  * specifies that the result is P_0 ... P_{size-1}, independent of the root
20  * (see 4.9.4 in MPI-1)
21  */
22
23 /* This implements a simple matrix-matrix multiply.  This is an associative
24    but not commutative operation.  The matrix size is set in matSize;
25    the number of matrices is the count argument. The matrix is stored
26    in C order, so that
27      c(i,j) is cin[j+i*matSize]
28  */
29 #define MAXCOL 256
30 static int matSize = 0;         /* Must be < MAXCOL */
31 void uop(void *cinPtr, void *coutPtr, int *count, MPI_Datatype * dtype);
32 void uop(void *cinPtr, void *coutPtr, int *count, MPI_Datatype * dtype)
33 {
34     const int *cin = (const int *) cinPtr;
35     int *cout = (int *) coutPtr;
36     int i, j, k, nmat;
37     int tempCol[MAXCOL];
38
39     for (nmat = 0; nmat < *count; nmat++) {
40         for (j = 0; j < matSize; j++) {
41             for (i = 0; i < matSize; i++) {
42                 tempCol[i] = 0;
43                 for (k = 0; k < matSize; k++) {
44                     /* col[i] += cin(i,k) * cout(k,j) */
45                     tempCol[i] += cin[k + i * matSize] * cout[j + k * matSize];
46                 }
47             }
48             for (i = 0; i < matSize; i++) {
49                 cout[j + i * matSize] = tempCol[i];
50             }
51         }
52     }
53 }
54
55 /* Initialize the integer matrix as a permutation of rank with rank+1.
56    If we call this matrix P_r, we know that product of P_0 P_1 ... P_{size-2}
57    is a left shift by 1.
58 */
59
60 static void initMat(MPI_Comm comm, int mat[])
61 {
62     int i, size, rank;
63
64     MPI_Comm_rank(comm, &rank);
65     MPI_Comm_size(comm, &size);
66
67     for (i = 0; i < size * size; i++)
68         mat[i] = 0;
69
70     /* For each row */
71     for (i = 0; i < size; i++) {
72         if (rank != size - 1) {
73             if (i == rank)
74                 mat[((i + 1) % size) + i * size] = 1;
75             else if (i == ((rank + 1) % size))
76                 mat[((i + size - 1) % size) + i * size] = 1;
77             else
78                 mat[i + i * size] = 1;
79         }
80         else {
81             mat[i + i * size] = 1;
82         }
83     }
84 }
85
86 #ifdef FOO
87 /* Compare a matrix with the identity matrix */
88 static int isIdentity(MPI_Comm comm, int mat[])
89 {
90     int i, j, size, rank, errs = 0;
91
92     MPI_Comm_rank(comm, &rank);
93     MPI_Comm_size(comm, &size);
94
95     for (i = 0; i < size; i++) {
96         for (j = 0; j < size; j++) {
97             if (i == j) {
98                 if (mat[j + i * size] != 1) {
99                     errs++;
100                 }
101             }
102             else {
103                 if (mat[j + i * size] != 0) {
104                     errs++;
105                 }
106             }
107         }
108     }
109     return errs;
110 }
111 #endif
112
113 /* Compare a matrix with the identity matrix */
114 static int isShiftLeft(MPI_Comm comm, int mat[])
115 {
116     int i, j, size, rank, errs = 0;
117
118     MPI_Comm_rank(comm, &rank);
119     MPI_Comm_size(comm, &size);
120
121     for (i = 0; i < size; i++) {
122         for (j = 0; j < size; j++) {
123             if (i == ((j + 1) % size)) {
124                 if (mat[j + i * size] != 1) {
125                     errs++;
126                 }
127             }
128             else {
129                 if (mat[j + i * size] != 0) {
130                     errs++;
131                 }
132             }
133         }
134     }
135     return errs;
136 }
137
138 int main(int argc, char *argv[])
139 {
140     int errs = 0;
141     int rank, size, root;
142     int minsize = 2, count;
143     MPI_Comm comm;
144     int *buf, *bufout;
145     MPI_Op op;
146     MPI_Datatype mattype;
147
148     MTest_Init(&argc, &argv);
149
150     MPI_Op_create(uop, 0, &op);
151
152     while (MTestGetIntracommGeneral(&comm, minsize, 1)) {
153         if (comm == MPI_COMM_NULL)
154             continue;
155
156         MPI_Comm_size(comm, &size);
157         MPI_Comm_rank(comm, &rank);
158
159         matSize = size; /* used by the user-defined operation */
160         /* Only one matrix for now */
161         count = 1;
162
163         /* A single matrix, the size of the communicator */
164         MPI_Type_contiguous(size * size, MPI_INT, &mattype);
165         MPI_Type_commit(&mattype);
166
167         buf = (int *) malloc(count * size * size * sizeof(int));
168         if (!buf)
169             MPI_Abort(MPI_COMM_WORLD, 1);
170         bufout = (int *) malloc(count * size * size * sizeof(int));
171         if (!bufout)
172             MPI_Abort(MPI_COMM_WORLD, 1);
173
174         for (root = 0; root < size; root++) {
175             initMat(comm, buf);
176             MPI_Reduce(buf, bufout, count, mattype, op, root, comm);
177             if (rank == root) {
178                 errs += isShiftLeft(comm, bufout);
179             }
180
181             /* Try the same test, but using MPI_IN_PLACE */
182             initMat(comm, bufout);
183             if (rank == root) {
184                 MPI_Reduce(MPI_IN_PLACE, bufout, count, mattype, op, root, comm);
185             }
186             else {
187                 MPI_Reduce(bufout, NULL, count, mattype, op, root, comm);
188             }
189             if (rank == root) {
190                 errs += isShiftLeft(comm, bufout);
191             }
192         }
193
194         free(buf);
195         free(bufout);
196
197         MPI_Type_free(&mattype);
198
199         MTestFreeComm(&comm);
200     }
201
202     MPI_Op_free(&op);
203
204     MTest_Finalize(errs);
205     MPI_Finalize();
206     return 0;
207 }