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);
83 if (rank < size - 1) {
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);
97 offset = i + i * size;
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)
117 /* Compare a matrix with the identity matrix */
118 static int isIdentity(MPI_Comm comm, int mat[])
120 int i, j, size, rank, lerrs = 0;
123 MPI_Comm_rank(comm, &rank);
124 MPI_Comm_size(comm, &size);
126 for (i = 0; i < size; i++) {
127 for (j = 0; j < size; j++) {
129 offset = j + i * size;
130 assert(offset < max_offset);
131 if (mat[offset] != 1) {
133 if (errs + lerrs < 10) {
134 printf("[%d] mat[%d,%d] = %d, expected 1 for comm %s\n",
135 rank, i, j, mat[offset], MTestGetIntracommName());
140 offset = j + i * size;
141 assert(offset < max_offset);
142 if (mat[offset] != 0) {
144 if (errs + lerrs < 10) {
145 printf("[%d] mat[%d,%d] = %d, expected 0 for comm %s\n",
146 rank, i, j, mat[offset], MTestGetIntracommName());
155 int main(int argc, char *argv[])
158 int minsize = 2, count;
162 MPI_Datatype mattype;
164 MTest_Init(&argc, &argv);
166 MPI_Op_create(uop, 0, &op);
168 while (MTestGetIntracommGeneral(&comm, minsize, 1)) {
169 if (comm == MPI_COMM_NULL) {
172 MPI_Comm_size(comm, &size);
175 /* Only one matrix for now */
178 /* A single matrix, the size of the communicator */
179 MPI_Type_contiguous(size * size, MPI_INT, &mattype);
180 MPI_Type_commit(&mattype);
182 max_offset = count * size * size;
183 buf = (int *) malloc(max_offset * sizeof(int));
185 MPI_Abort(MPI_COMM_WORLD, 1);
187 bufout = (int *) malloc(max_offset * sizeof(int));
189 MPI_Abort(MPI_COMM_WORLD, 1);
193 MPI_Allreduce(buf, bufout, count, mattype, op, comm);
194 errs += isIdentity(comm, bufout);
196 /* Try the same test, but using MPI_IN_PLACE */
197 initMat(comm, bufout);
198 MPI_Allreduce(MPI_IN_PLACE, bufout, count, mattype, op, comm);
199 errs += isIdentity(comm, bufout);
204 MPI_Type_free(&mattype);
205 MTestFreeComm(&comm);
210 MTest_Finalize(errs);