1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 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);
}
|