1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
3 * (C) 2003 by Argonne National Laboratory.
4 * See COPYRIGHT in top-level directory.
13 static char MTEST_Descrip[] = "Test MPI_Allreduce with non-commutative user-defined operations";
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
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
25 c(i,j) is cin[j+i*matSize]
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 )
33 const int *cin = (const int *)cinPtr;
34 int *cout = (int *)coutPtr;
38 int matsize2 = matSize*matSize;
40 for (nmat = 0; nmat < *count; nmat++) {
41 for (j=0; j<matSize; j++) {
42 for (i=0; i<matSize; i++) {
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];
53 for (i=0; i<matSize; i++) {
54 offset1 = j+i*matSize;
55 assert(offset1 < max_offset);
56 cout[offset1] = tempcol[i];
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
70 static void initMat( MPI_Comm comm, int mat[] )
75 MPI_Comm_rank( comm, &rank );
76 MPI_Comm_size( comm, &size );
78 for (i=0; i<size*size; i++) {
79 assert(i < max_offset);
84 /* Create the permutation matrix that exchanges r with r+1 */
85 for (i=0; i<size; i++) {
87 offset = ((i+1)%size) + i * size;
88 assert(offset < max_offset);
91 else if (i == ((rank + 1)%size)) {
92 offset = ((i+size-1)%size) + i * size;
93 assert(offset < max_offset);
98 assert(offset < max_offset);
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) */
109 if ( ((j-i+size)%size) == 1 ) mat[offset] = 1;
116 /* Compare a matrix with the identity matrix */
117 static int isIdentity( MPI_Comm comm, int mat[] )
119 int i, j, size, rank, lerrs = 0;
122 MPI_Comm_rank( comm, &rank );
123 MPI_Comm_size( comm, &size );
125 for (i=0; i<size; i++) {
126 for (j=0; j<size; j++) {
129 assert(offset < max_offset);
130 if (mat[offset] != 1) {
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() );
140 assert(offset < max_offset);
141 if (mat[offset] != 0) {
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() );
154 int main( int argc, char *argv[] )
157 int minsize = 2, count;
161 MPI_Datatype mattype;
163 MTest_Init( &argc, &argv );
165 MPI_Op_create( uop, 0, &op );
167 while (MTestGetIntracommGeneral( &comm, minsize, 1 )) {
168 if (comm == MPI_COMM_NULL) {
171 MPI_Comm_size( comm, &size );
174 /* Only one matrix for now */
177 /* A single matrix, the size of the communicator */
178 MPI_Type_contiguous( size*size, MPI_INT, &mattype );
179 MPI_Type_commit( &mattype );
181 max_offset = count * size * size;
182 buf = (int *)malloc( max_offset * sizeof(int) );
184 MPI_Abort( MPI_COMM_WORLD, 1 );
187 bufout = (int *)malloc( max_offset * sizeof(int) );
189 MPI_Abort( MPI_COMM_WORLD, 1 );
193 initMat( comm, buf );
194 MPI_Allreduce( buf, bufout, count, mattype, op, comm );
195 errs += isIdentity( comm, bufout );
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 );
205 //MPI_Type_free( &mattype );
206 MTestFreeComm( &comm );
209 // MPI_Op_free( &op );
211 MTest_Finalize( errs );