Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Reduce the size of partial shared malloc tests.
[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)
110                     mat[offset] = 1;
111             }
112         }
113
114     }
115 }
116
117 /* Compare a matrix with the identity matrix */
118 static int isIdentity(MPI_Comm comm, int mat[])
119 {
120     int i, j, size, rank, lerrs = 0;
121     int offset;
122
123     MPI_Comm_rank(comm, &rank);
124     MPI_Comm_size(comm, &size);
125
126     for (i = 0; i < size; i++) {
127         for (j = 0; j < size; j++) {
128             if (i == j) {
129                 offset = j + i * size;
130                 assert(offset < max_offset);
131                 if (mat[offset] != 1) {
132                     lerrs++;
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());
136                     }
137                 }
138             }
139             else {
140                 offset = j + i * size;
141                 assert(offset < max_offset);
142                 if (mat[offset] != 0) {
143                     lerrs++;
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());
147                     }
148                 }
149             }
150         }
151     }
152     return lerrs;
153 }
154
155 int main(int argc, char *argv[])
156 {
157     int size;
158     int minsize = 2, count;
159     MPI_Comm comm;
160     int *buf, *bufout;
161     MPI_Op op;
162     MPI_Datatype mattype;
163
164     MTest_Init(&argc, &argv);
165
166     MPI_Op_create(uop, 0, &op);
167
168     while (MTestGetIntracommGeneral(&comm, minsize, 1)) {
169         if (comm == MPI_COMM_NULL) {
170             continue;
171         }
172         MPI_Comm_size(comm, &size);
173         matSize = size;
174
175         /* Only one matrix for now */
176         count = 1;
177
178         /* A single matrix, the size of the communicator */
179         MPI_Type_contiguous(size * size, MPI_INT, &mattype);
180         MPI_Type_commit(&mattype);
181
182         max_offset = count * size * size;
183         buf = (int *) malloc(max_offset * sizeof(int));
184         if (!buf) {
185             MPI_Abort(MPI_COMM_WORLD, 1);
186         }
187         bufout = (int *) malloc(max_offset * sizeof(int));
188         if (!bufout) {
189             MPI_Abort(MPI_COMM_WORLD, 1);
190         }
191
192         initMat(comm, buf);
193         MPI_Allreduce(buf, bufout, count, mattype, op, comm);
194         errs += isIdentity(comm, bufout);
195
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);
200
201         free(buf);
202         free(bufout);
203
204         MPI_Type_free(&mattype);
205         MTestFreeComm(&comm);
206     }
207
208     MPI_Op_free(&op);
209
210     MTest_Finalize(errs);
211     MPI_Finalize();
212     return 0;
213 }