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 and arbitrary root";
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)
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
28 c(i,j) is cin[j+i*matSize]
31 static int matSize = 0; /* Must be < MAXCOL */
33 void uop( void *cinPtr, void *coutPtr, int *count, MPI_Datatype *dtype );
34 void uop( void *cinPtr, void *coutPtr, int *count, MPI_Datatype *dtype )
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++) {
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];
53 for (i=0; i<matSize; i++) {
54 cout[j+i*matSize] = tempCol[i];
57 cinPtr = (int *)cinPtr + matSize*matSize;
58 coutPtr = (int *)coutPtr + matSize*matSize;
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)
71 static void initMat( MPI_Comm comm, int mat[] )
75 MPI_Comm_rank( comm, &rank );
76 MPI_Comm_size( comm, &size );
78 /* Remember the matrix size */
81 for (i=0; i<matSize*matSize; i++) mat[i] = 0;
83 for (i=0; i<matSize; i++) {
85 mat[((i+1)%matSize) + i * matSize] = 1;
86 else if (i == ((rank + 1)%matSize))
87 mat[((i+matSize-1)%matSize) + i * matSize] = 1;
93 /* Compare a matrix with the identity matrix */
95 static int isIdentity( MPI_Comm comm, int mat[] )
97 int i, j, size, rank, errs = 0;
99 MPI_Comm_rank( comm, &rank );
100 MPI_Comm_size( comm, &size );
102 for (i=0; i<size; i++) {
103 for (j=0; j<size; j++) {
105 if (mat[j+i*size] != 1) {
106 printf( "mat(%d,%d) = %d, should = 1\n",
107 i, j, mat[j+i*size] );
112 if (mat[j+i*size] != 0) {
113 printf( "mat(%d,%d) = %d, should = 0\n",
114 i, j, mat[j+i*size] );
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[] )
128 int i, j, size, rank, errs = 0;
130 MPI_Comm_rank( comm, &rank );
131 MPI_Comm_size( comm, &size );
133 /* Check the first two last rows */
135 for (j=0; j<size; j++) {
138 printf( "mat(%d,%d) = %d, should = 1\n",
145 printf( "mat(%d,%d) = %d, should = 0\n",
152 for (j=0; j<size; j++) {
154 if (mat[j+i*size] != 1) {
155 printf( "mat(%d,%d) = %d, should = 1\n",
156 i, j, mat[j+i*size] );
161 if (mat[j+i*size] != 0) {
162 printf( "mat(%d,%d) = %d, should = 0\n",
163 i, j, mat[j+i*size] );
168 /* The remaint rows are shifted down by one */
169 for (i=2; i<size; i++) {
170 for (j=0; j<size; j++) {
172 if (mat[j+i*size] != 1) {
173 printf( "mat(%d,%d) = %d, should = 1\n",
174 i, j, mat[j+i*size] );
179 if (mat[j+i*size] != 0) {
180 printf( "mat(%d,%d) = %d, should = 0\n",
181 i, j, mat[j+i*size] );
190 int main( int argc, char *argv[] )
193 int rank, size, root;
194 int minsize = 2, count;
198 MPI_Datatype mattype;
200 MTest_Init( &argc, &argv );
202 MPI_Op_create( uop, 0, &op );
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 );
210 /* Skip because there are too many processes */
211 MTestFreeComm( &comm );
215 /* Only one matrix for now */
218 /* A single matrix, the size of the communicator */
219 MPI_Type_contiguous( size*size, MPI_INT, &mattype );
220 MPI_Type_commit( &mattype );
222 buf = (int *)malloc( count * size * size * sizeof(int) );
224 MPI_Abort( MPI_COMM_WORLD, 1 );
227 bufout = (int *)malloc( count * size * size * sizeof(int) );
229 MPI_Abort( MPI_COMM_WORLD, 1 );
233 for (root = 0; root < size; root ++) {
234 initMat( comm, buf );
235 MPI_Reduce( buf, bufout, count, mattype, op, root, comm );
237 errs += isPermutedIdentity( comm, bufout );
240 /* Try the same test, but using MPI_IN_PLACE */
241 initMat( comm, bufout );
243 MPI_Reduce( MPI_IN_PLACE, bufout, count, mattype, op, root, comm );
246 MPI_Reduce( bufout, NULL, count, mattype, op, root, comm );
249 errs += isPermutedIdentity( comm, bufout );
252 MPI_Type_free( &mattype );
257 MTestFreeComm( &comm );
262 MTest_Finalize( errs );