1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
4 * (C) 2003 by Argonne National Laboratory.
5 * See COPYRIGHT in top-level directory.
13 static char MTEST_Descrip[] = "Test MPI_Reduce with non-commutative user-define operations";
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)
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
27 c(i,j) is cin[j+i*matSize]
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 )
34 const int *cin = (const int *)cinPtr;
35 int *cout = (int *)coutPtr;
39 for (nmat = 0; nmat < *count; nmat++) {
40 for (j=0; j<matSize; j++) {
41 for (i=0; i<matSize; i++) {
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];
48 for (i=0; i<matSize; i++) {
49 cout[j+i*matSize] = tempCol[i];
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}
60 static void initMat( MPI_Comm comm, int mat[] )
64 MPI_Comm_rank( comm, &rank );
65 MPI_Comm_size( comm, &size );
67 for (i=0; i<size*size; i++) mat[i] = 0;
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;
83 /* Compare a matrix with the identity matrix */
84 static int isIdentity( MPI_Comm comm, int mat[] )
86 int i, j, size, rank, errs = 0;
88 MPI_Comm_rank( comm, &rank );
89 MPI_Comm_size( comm, &size );
91 for (i=0; i<size; i++) {
92 for (j=0; j<size; j++) {
94 if (mat[j+i*size] != 1) {
99 if (mat[j+i*size] != 0) {
109 /* Compare a matrix with the identity matrix */
110 static int isShiftLeft( MPI_Comm comm, int mat[] )
112 int i, j, size, rank, errs = 0;
114 MPI_Comm_rank( comm, &rank );
115 MPI_Comm_size( comm, &size );
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) {
125 if (mat[j+i*size] != 0) {
134 int main( int argc, char *argv[] )
137 int rank, size, root;
138 int minsize = 2, count;
142 MPI_Datatype mattype;
144 MTest_Init( &argc, &argv );
146 MPI_Op_create( uop, 0, &op );
148 while (MTestGetIntracommGeneral( &comm, minsize, 1 )) {
149 if (comm == MPI_COMM_NULL) continue;
151 MPI_Comm_size( comm, &size );
152 MPI_Comm_rank( comm, &rank );
154 matSize = size; /* used by the user-defined operation */
155 /* Only one matrix for now */
158 /* A single matrix, the size of the communicator */
159 MPI_Type_contiguous( size*size, MPI_INT, &mattype );
160 MPI_Type_commit( &mattype );
162 buf = (int *)malloc( count * size * size * sizeof(int) );
164 MPI_Abort( MPI_COMM_WORLD, 1 );
167 bufout = (int *)malloc( count * size * size * sizeof(int) );
169 MPI_Abort( MPI_COMM_WORLD, 1 );
173 for (root = 0; root < size; root ++) {
174 initMat( comm, buf );
175 MPI_Reduce( buf, bufout, count, mattype, op, root, comm );
177 errs += isShiftLeft( comm, bufout );
180 /* Try the same test, but using MPI_IN_PLACE */
181 initMat( comm, bufout );
183 MPI_Reduce( MPI_IN_PLACE, bufout, count, mattype, op, root, comm );
186 MPI_Reduce( bufout, NULL, count, mattype, op, root, comm );
189 errs += isShiftLeft( comm, bufout );
192 #if MTEST_HAVE_MIN_MPI_VERSION(2,2)
193 /* Try one more time without IN_PLACE to make sure we check
194 * aliasing correctly */
196 MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
197 if (MPI_SUCCESS == MPI_Reduce( bufout, bufout, count, mattype, op, root, comm ))
206 MPI_Type_free( &mattype );
208 MTestFreeComm( &comm );
213 MTest_Finalize( errs );