Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
remove warning with mc
[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) printf( "Panic!\n" );
42     for (nmat = 0; nmat < *count; nmat++) {
43         cin  = (const int *)cinPtr;
44         cout = (int *)coutPtr;
45         for (j=0; j<matSize; j++) {
46             for (i=0; i<matSize; i++) {
47                 tempCol[i] = 0;
48                 for (k=0; k<matSize; k++) {
49                     /* col[i] += cin(i,k) * cout(k,j) */
50                     tempCol[i] += cin[k+i*matSize] * cout[j+k*matSize];
51                 }
52             }
53             for (i=0; i<matSize; i++) {
54                 cout[j+i*matSize] = tempCol[i];
55             }
56         }
57         cinPtr = (int *)cinPtr + matSize*matSize;
58         coutPtr = (int *)coutPtr + matSize*matSize;
59     }
60 }
61
62 /* Initialize the integer matrix as a permutation of rank with rank+1.
63    If we call this matrix P_r, we know that product of P_0 P_1 ... P_{size-1}
64    is the matrix with rows ordered as
65    1,size,2,3,4,...,size-1
66    (The matrix is basically a circular shift right, 
67    shifting right n-1 steps for an n x n dimensional matrix, with the last
68    step swapping rows 1 and size)
69 */   
70
71 static void initMat( MPI_Comm comm, int mat[] )
72 {
73     int i, size, rank;
74     
75     MPI_Comm_rank( comm, &rank );
76     MPI_Comm_size( comm, &size );
77
78     /* Remember the matrix size */
79     matSize = size;
80
81     for (i=0; i<matSize*matSize; i++) mat[i] = 0;
82
83     for (i=0; i<matSize; i++) {
84         if (i == rank)                   
85             mat[((i+1)%matSize) + i * matSize] = 1;
86         else if (i == ((rank + 1)%matSize)) 
87             mat[((i+matSize-1)%matSize) + i * matSize] = 1;
88         else                             
89             mat[i+i*matSize] = 1;
90     }
91 }
92
93 /* Compare a matrix with the identity matrix */
94 /*
95 static int isIdentity( MPI_Comm comm, int mat[] )
96 {
97     int i, j, size, rank, errs = 0;
98     
99     MPI_Comm_rank( comm, &rank );
100     MPI_Comm_size( comm, &size );
101
102     for (i=0; i<size; i++) {
103         for (j=0; j<size; j++) {
104             if (j == i) {
105                 if (mat[j+i*size] != 1) {
106                     printf( "mat(%d,%d) = %d, should = 1\n", 
107                             i, j, mat[j+i*size] );
108                     errs++;
109                 }
110             }
111             else {
112                 if (mat[j+i*size] != 0) {
113                     printf( "mat(%d,%d) = %d, should = 0\n",
114                             i, j, mat[j+i*size] );
115                     errs++;
116                 }
117             }
118         }
119     }
120     return errs;
121 }
122 */
123
124 /* Compare a matrix with the identity matrix with rows permuted to as rows
125    1,size,2,3,4,5,...,size-1 */
126 static int isPermutedIdentity( MPI_Comm comm, int mat[] )
127 {
128     int i, j, size, rank, errs = 0;
129     
130     MPI_Comm_rank( comm, &rank );
131     MPI_Comm_size( comm, &size );
132
133     /* Check the first two last rows */
134     i = 0;
135     for (j=0; j<size; j++) {
136         if (j==0) { 
137             if (mat[j] != 1) {
138                 printf( "mat(%d,%d) = %d, should = 1\n", 
139                         i, j, mat[j] );
140                 errs++;
141             }
142         }
143         else {
144             if (mat[j] != 0) {
145                 printf( "mat(%d,%d) = %d, should = 0\n", 
146                         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", 
156                         i, j, mat[j+i*size] );
157                 errs++;
158             }
159         }
160         else {
161             if (mat[j+i*size] != 0) {
162                 printf( "mat(%d,%d) = %d, should = 0\n", 
163                         i, j, mat[j+i*size] );
164                 errs++;
165             }
166         }
167     }
168     /* The remaint rows are shifted down by one */
169     for (i=2; i<size; i++) {
170         for (j=0; j<size; j++) {
171             if (j == i-1) {
172                 if (mat[j+i*size] != 1) {
173                     printf( "mat(%d,%d) = %d, should = 1\n", 
174                             i, j, mat[j+i*size] );
175                     errs++;
176                 }
177             }
178             else {
179                 if (mat[j+i*size] != 0) {
180                     printf( "mat(%d,%d) = %d, should = 0\n",
181                             i, j, mat[j+i*size] );
182                     errs++;
183                 }
184             }
185         }
186     }
187     return errs;
188 }
189
190 int main( int argc, char *argv[] )
191 {
192     int errs = 0;
193     int rank, size, root;
194     int minsize = 2, count; 
195     MPI_Comm      comm;
196     int *buf, *bufout;
197     MPI_Op op;
198     MPI_Datatype mattype;
199
200     MTest_Init( &argc, &argv );
201
202     MPI_Op_create( uop, 0, &op );
203     
204     while (MTestGetIntracommGeneral( &comm, minsize, 1 )) {
205         if (comm == MPI_COMM_NULL) continue;
206         MPI_Comm_size( comm, &size );
207         MPI_Comm_rank( comm, &rank );
208
209         if (size > MAXCOL) {
210             /* Skip because there are too many processes */
211             MTestFreeComm( &comm );
212             continue;
213         }
214
215         /* Only one matrix for now */
216         count = 1;
217
218         /* A single matrix, the size of the communicator */
219         MPI_Type_contiguous( size*size, MPI_INT, &mattype );
220         MPI_Type_commit( &mattype );
221         
222         buf = (int *)malloc( count * size * size * sizeof(int) );
223         if (!buf) {
224           MPI_Abort( MPI_COMM_WORLD, 1 );
225           exit(1);
226         }
227         bufout = (int *)malloc( count * size * size * sizeof(int) );
228         if (!bufout) {
229           MPI_Abort( MPI_COMM_WORLD, 1 );
230           exit(1);
231         }
232
233         for (root = 0; root < size; root ++) {
234             initMat( comm, buf );
235             MPI_Reduce( buf, bufout, count, mattype, op, root, comm );
236             if (rank == root) {
237                 errs += isPermutedIdentity( comm, bufout );
238             }
239
240             /* Try the same test, but using MPI_IN_PLACE */
241             initMat( comm, bufout );
242             if (rank == root) {
243                 MPI_Reduce( MPI_IN_PLACE, bufout, count, mattype, op, root, comm );
244             }
245             else {
246                 MPI_Reduce( bufout, NULL, count, mattype, op, root, comm );
247             }
248             if (rank == root) {
249                 errs += isPermutedIdentity( comm, bufout );
250             }
251         }
252         MPI_Type_free( &mattype );
253
254         free( buf );
255         free( bufout );
256
257         MTestFreeComm( &comm );
258     }
259
260     MPI_Op_free( &op );
261
262     MTest_Finalize( errs );
263     MPI_Finalize();
264     return 0;
265 }