Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
61f1a7c7b3deac5a91b1aba7f9408ff407519933
[simgrid.git] / teshsuite / smpi / mpich3-test / coll / allred3.c
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  *  (C) 2003 by Argonne National Laboratory.
4  *      See COPYRIGHT in top-level directory.
5  */
6 #include "mpi.h"
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include "mpitest.h"
10 #include <assert.h>
11
12 /*
13 static char MTEST_Descrip[] = "Test MPI_Allreduce with non-commutative user-defined operations";
14 */
15
16 /* We make the error count global so that we can easily control the output
17    of error information (in particular, limiting it after the first 10 
18    errors */
19 int errs = 0;
20
21 /* This implements a simple matrix-matrix multiply.  This is an associative
22    but not commutative operation.  The matrix size is set in matSize;
23    the number of matrices is the count argument. The matrix is stored
24    in C order, so that
25      c(i,j) is cin[j+i*matSize]
26  */
27 #define MAXCOL 256
28 static int matSize = 0;  /* Must be < MAXCOL */
29 static int max_offset = 0;
30 void uop( void *, void *, int *, MPI_Datatype * );
31 void uop( void *cinPtr, void *coutPtr, int *count, MPI_Datatype *dtype )
32 {
33     const int *cin = (const int *)cinPtr;
34     int *cout = (int *)coutPtr;
35     int i, j, k, nmat;
36     int tempcol[MAXCOL];
37     int offset1, offset2;
38     int matsize2 = matSize*matSize;
39
40     for (nmat = 0; nmat < *count; nmat++) {
41         for (j=0; j<matSize; j++) {
42             for (i=0; i<matSize; i++) {
43                 tempcol[i] = 0;
44                 for (k=0; k<matSize; k++) {
45                     /* col[i] += cin(i,k) * cout(k,j) */
46                     offset1    = k+i*matSize;
47                     offset2    = j+k*matSize;
48                     assert(offset1 < max_offset);
49                     assert(offset2 < max_offset);
50                     tempcol[i] += cin[offset1] * cout[offset2];
51                 }
52             }
53             for (i=0; i<matSize; i++) {
54                 offset1       = j+i*matSize;
55                 assert(offset1 < max_offset);
56                 cout[offset1] = tempcol[i];
57             }
58         }
59         cin  += matsize2;
60         cout += matsize2;
61     }
62 }
63
64 /* Initialize the integer matrix as a permutation of rank with rank+1.
65    If we call this matrix P_r, we know that product of P_0 P_1 ... P_{size-2}
66    is the the matrix representing the permutation that shifts left by one.
67    As the final matrix (in the size-1 position), we use the matrix that
68    shifts RIGHT by one
69 */   
70 static void initMat( MPI_Comm comm, int mat[] )
71 {
72     int i, j, size, rank;
73     int offset;
74     
75     MPI_Comm_rank( comm, &rank );
76     MPI_Comm_size( comm, &size );
77
78     for (i=0; i<size*size; i++) {
79         assert(i < max_offset);
80         mat[i] = 0;
81     }
82
83     if (rank < size-1) {
84         /* Create the permutation matrix that exchanges r with r+1 */
85         for (i=0; i<size; i++) {
86             if (i == rank) {
87                 offset = ((i+1)%size) + i * size;
88                 assert(offset < max_offset);
89                 mat[offset] = 1;
90             }
91             else if (i == ((rank + 1)%size)) {
92                 offset = ((i+size-1)%size) + i * size;
93                 assert(offset < max_offset);
94                 mat[offset] = 1;
95             }
96             else {
97                 offset = i+i*size;
98                 assert(offset < max_offset);
99                 mat[offset] = 1;
100             }
101         }
102     }
103     else {
104         /* Create the permutation matrix that shifts right by one */
105         for (i=0; i<size; i++) {
106             for (j=0; j<size; j++) {
107                 offset = j + i * size;  /* location of c(i,j) */
108                 mat[offset] = 0;
109                 if ( ((j-i+size)%size) == 1 ) mat[offset] = 1;
110             }
111         }
112         
113     }
114 }
115
116 /* Compare a matrix with the identity matrix */
117 static int isIdentity( MPI_Comm comm, int mat[] )
118 {
119     int i, j, size, rank, lerrs = 0;
120     int offset;
121     
122     MPI_Comm_rank( comm, &rank );
123     MPI_Comm_size( comm, &size );
124
125     for (i=0; i<size; i++) {
126         for (j=0; j<size; j++) {
127             if (i == j) {
128                 offset = j+i*size;
129                 assert(offset < max_offset);
130                 if (mat[offset] != 1) {
131                     lerrs++;
132                     if (errs + lerrs< 10) {
133                         printf( "[%d] mat[%d,%d] = %d, expected 1 for comm %s\n", 
134                                 rank, i,j, mat[offset], MTestGetIntracommName() );
135                     }
136                 }
137             }
138             else {
139                 offset = j+i*size;
140                 assert(offset < max_offset);
141                 if (mat[offset] != 0) {
142                     lerrs++;
143                     if (errs + lerrs< 10) {
144                         printf( "[%d] mat[%d,%d] = %d, expected 0 for comm %s\n", 
145                                 rank, i,j, mat[offset], MTestGetIntracommName() );
146                     }
147                 }
148             }
149         }
150     }
151     return lerrs;
152 }
153
154 int main( int argc, char *argv[] )
155 {
156     int size;
157     int minsize = 2, count; 
158     MPI_Comm      comm;
159     int *buf, *bufout;
160     MPI_Op op;
161     MPI_Datatype mattype;
162
163     MTest_Init( &argc, &argv );
164
165     MPI_Op_create( uop, 0, &op );
166     
167     while (MTestGetIntracommGeneral( &comm, minsize, 1 )) {
168         if (comm == MPI_COMM_NULL) {
169             continue;
170         }
171         MPI_Comm_size( comm, &size );
172         matSize = size;
173
174         /* Only one matrix for now */
175         count = 1;
176
177         /* A single matrix, the size of the communicator */
178         MPI_Type_contiguous( size*size, MPI_INT, &mattype );
179         MPI_Type_commit( &mattype );
180
181         max_offset = count * size * size;
182         buf = (int *)malloc( max_offset * sizeof(int) );
183         if (!buf) {
184             MPI_Abort( MPI_COMM_WORLD, 1 );
185             exit(1);
186         }
187         bufout = (int *)malloc( max_offset * sizeof(int) );
188         if (!bufout) {
189             MPI_Abort( MPI_COMM_WORLD, 1 );
190             exit(1);
191         }
192
193         initMat( comm, buf );
194         MPI_Allreduce( buf, bufout, count, mattype, op, comm );
195         errs += isIdentity( comm, bufout );
196
197         /* Try the same test, but using MPI_IN_PLACE */
198         initMat( comm, bufout );
199         MPI_Allreduce( MPI_IN_PLACE, bufout, count, mattype, op, comm );
200         errs += isIdentity( comm, bufout );
201
202         free( buf );
203         free( bufout );
204
205         MPI_Type_free( &mattype );
206         MTestFreeComm( &comm );
207     }
208
209     MPI_Op_free( &op );
210
211     MTest_Finalize( errs );
212     MPI_Finalize();
213     return 0;
214 }