Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
add new coll tests
[simgrid.git] / teshsuite / smpi / mpich3-test / coll / allred_derived.c
diff --git a/teshsuite/smpi/mpich3-test/coll/allred_derived.c b/teshsuite/smpi/mpich3-test/coll/allred_derived.c
new file mode 100644 (file)
index 0000000..1b40edd
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) by Argonne National Laboratory
+ *     See COPYRIGHT in top-level directory
+ */
+
+#include "mpi.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "mpitest.h"
+#include <assert.h>
+
+/*
+static char MTEST_Descrip[] = "Test MPI_Allreduce with commutative user-defined operations";
+*/
+
+#define MAX_BLOCKLEN 10000
+#define IS_COMMUTATIVE 1
+
+/* We make the error count global so that we can easily control the output
+   of error information (in particular, limiting it after the first 10
+   errors */
+int errs = 0;
+
+/* parameter for a vector type of MPI_INT */
+int g_blocklen = 1;
+int g_stride = 1;
+
+void uop(void *, void *, int *, MPI_Datatype *);
+void uop(void *cinPtr, void *coutPtr, int *count, MPI_Datatype * dtype)
+{
+    const int *cin = (const int *) cinPtr;
+    int *cout = (int *) coutPtr;
+
+    int k = 0;
+    for (int i = 0; i < *count; i++) {
+        for (int j = 0; j < g_blocklen; j++) {
+            cout[k] += cin[k];
+            k += g_stride;
+        }
+    }
+}
+
+static void init_buf(void *buf, int count, int rank)
+{
+    int *p = buf;
+
+    int k = 0;
+    for (int i = 0; i < count; i++) {
+        for (int j = 0; j < g_blocklen; j++) {
+            p[k] = rank + i + j;
+            k += g_stride;
+        }
+    }
+}
+
+static int check_result(void *buf, int count, int size)
+{
+    int lerrs = 0;
+    int *p = buf;
+
+    int k = 0;
+    for (int i = 0; i < count; i++) {
+        for (int j = 0; j < g_blocklen; j++) {
+            int exp = size * (size - 1) / 2 + (i + j) * size;
+            if (p[k] != exp) {
+                lerrs++;
+                if (errs + lerrs < 10) {
+                    printf("[%d - %d] expected %d, got %d, %s\n",
+                           i, j, exp, p[k], MTestGetIntracommName());
+                }
+            }
+            k += g_stride;
+        }
+    }
+    return lerrs;
+}
+
+int main(int argc, char *argv[])
+{
+    MPI_Comm comm;
+    void *buf, *bufout;
+    MPI_Op op;
+    MPI_Datatype datatype;
+
+    MTest_Init(&argc, &argv);
+
+    MPI_Op_create(uop, IS_COMMUTATIVE, &op);
+
+    while (MTestGetIntracommGeneral(&comm, 2, 1)) {
+        if (comm == MPI_COMM_NULL) {
+            continue;
+        }
+
+        int rank, size;
+        MPI_Comm_rank(comm, &rank);
+        MPI_Comm_size(comm, &size);
+
+        int count = 10;
+        for (int n = 1; n < MAX_BLOCKLEN; n *= 2) {
+            g_blocklen = n;
+            int extent = g_blocklen * g_stride * sizeof(int);
+            MPI_Type_vector(g_blocklen, 1, g_stride, MPI_INT, &datatype);
+            MPI_Type_commit(&datatype);
+
+            buf = (int *) malloc(extent * count);
+            if (!buf) {
+                MPI_Abort(MPI_COMM_WORLD, 1);
+            }
+            bufout = (int *) malloc(extent * count);
+            if (!bufout) {
+                MPI_Abort(MPI_COMM_WORLD, 1);
+            }
+
+            init_buf(buf, count, rank);
+            MPI_Allreduce(buf, bufout, count, datatype, op, comm);
+            errs += check_result(bufout, count, size);
+
+            /* do it again using MPI_IN_PLACE */
+            init_buf(bufout, count, rank);
+            MPI_Allreduce(MPI_IN_PLACE, bufout, count, datatype, op, comm);
+            errs += check_result(bufout, count, size);
+
+            free(buf);
+            free(bufout);
+            MPI_Type_free(&datatype);
+        }
+
+        MTestFreeComm(&comm);
+    }
+
+    MPI_Op_free(&op);
+
+    MTest_Finalize(errs);
+    return MTestReturnValue(errs);
+}