Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Add mpich3 test suite, to replace older one.
[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++) mat[i] = 0;
68
69     /* For each row */
70     for (i=0; i<size; i++) {
71         if (rank != size - 1) {
72             if (i == rank)                   mat[((i+1)%size) + i * size] = 1;
73             else if (i == ((rank + 1)%size)) mat[((i+size-1)%size) + i * size] = 1;
74             else                             mat[i+i*size] = 1;
75         }
76         else {
77             mat[i+i*size] = 1;
78         }
79     }
80 }
81
82 #ifdef FOO
83 /* Compare a matrix with the identity matrix */
84 static int isIdentity( MPI_Comm comm, int mat[] )
85 {
86     int i, j, size, rank, errs = 0;
87     
88     MPI_Comm_rank( comm, &rank );
89     MPI_Comm_size( comm, &size );
90
91     for (i=0; i<size; i++) {
92         for (j=0; j<size; j++) {
93             if (i == j) {
94                 if (mat[j+i*size] != 1) {
95                     errs++;
96                 }
97             }
98             else {
99                 if (mat[j+i*size] != 0) {
100                     errs++;
101                 }
102             }
103         }
104     }
105     return errs;
106 }
107 #endif
108
109 /* Compare a matrix with the identity matrix */
110 static int isShiftLeft( MPI_Comm comm, int mat[] )
111 {
112     int i, j, size, rank, errs = 0;
113     
114     MPI_Comm_rank( comm, &rank );
115     MPI_Comm_size( comm, &size );
116
117     for (i=0; i<size; i++) {
118         for (j=0; j<size; j++) {
119             if (i == ((j + 1) % size)) {
120                 if (mat[j+i*size] != 1) {
121                     errs++;
122                 }
123             }
124             else {
125                 if (mat[j+i*size] != 0) {
126                     errs++;
127                 }
128             }
129         }
130     }
131     return errs;
132 }
133
134 int main( int argc, char *argv[] )
135 {
136     int errs = 0;
137     int rank, size, root;
138     int minsize = 2, count; 
139     MPI_Comm      comm;
140     int *buf, *bufout;
141     MPI_Op op;
142     MPI_Datatype mattype;
143
144     MTest_Init( &argc, &argv );
145
146     MPI_Op_create( uop, 0, &op );
147     
148     while (MTestGetIntracommGeneral( &comm, minsize, 1 )) {
149         if (comm == MPI_COMM_NULL) continue;
150
151         MPI_Comm_size( comm, &size );
152         MPI_Comm_rank( comm, &rank );
153
154         matSize = size;  /* used by the user-defined operation */
155         /* Only one matrix for now */
156         count = 1;
157
158         /* A single matrix, the size of the communicator */
159         MPI_Type_contiguous( size*size, MPI_INT, &mattype );
160         MPI_Type_commit( &mattype );
161         
162         buf = (int *)malloc( count * size * size * sizeof(int) );
163         if (!buf) MPI_Abort( MPI_COMM_WORLD, 1 );
164         bufout = (int *)malloc( count * size * size * sizeof(int) );
165         if (!bufout) MPI_Abort( MPI_COMM_WORLD, 1 );
166
167         for (root = 0; root < size; root ++) {
168             initMat( comm, buf );
169             MPI_Reduce( buf, bufout, count, mattype, op, root, comm );
170             if (rank == root) {
171                 errs += isShiftLeft( comm, bufout );
172             }
173
174             /* Try the same test, but using MPI_IN_PLACE */
175             initMat( comm, bufout );
176             if (rank == root) {
177                 MPI_Reduce( MPI_IN_PLACE, bufout, count, mattype, op, root, comm );
178             }
179             else {
180                 MPI_Reduce( bufout, NULL, count, mattype, op, root, comm );
181             }
182             if (rank == root) {
183                 errs += isShiftLeft( comm, bufout );
184             }
185         }
186
187         free( buf );
188         free( bufout );
189         
190         MPI_Type_free( &mattype );
191
192         MTestFreeComm( &comm );
193     }
194
195     MPI_Op_free( &op );
196
197     MTest_Finalize( errs );
198     MPI_Finalize();
199     return 0;
200 }