Blame test/mpi/coll/allred3.c

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 *  (C) 2003 by Argonne National Laboratory.
Packit Service c5cf8c
 *      See COPYRIGHT in top-level directory.
Packit Service c5cf8c
 */
Packit Service c5cf8c
#include "mpi.h"
Packit Service c5cf8c
#include <stdio.h>
Packit Service c5cf8c
#include <stdlib.h>
Packit Service c5cf8c
#include "mpitest.h"
Packit Service c5cf8c
#include <assert.h>
Packit Service c5cf8c
Packit Service c5cf8c
/*
Packit Service c5cf8c
static char MTEST_Descrip[] = "Test MPI_Allreduce with non-commutative user-defined operations";
Packit Service c5cf8c
*/
Packit Service c5cf8c
Packit Service c5cf8c
/* We make the error count global so that we can easily control the output
Packit Service c5cf8c
   of error information (in particular, limiting it after the first 10
Packit Service c5cf8c
   errors */
Packit Service c5cf8c
int errs = 0;
Packit Service c5cf8c
Packit Service c5cf8c
/* This implements a simple matrix-matrix multiply.  This is an associative
Packit Service c5cf8c
   but not commutative operation.  The matrix size is set in matSize;
Packit Service c5cf8c
   the number of matrices is the count argument. The matrix is stored
Packit Service c5cf8c
   in C order, so that
Packit Service c5cf8c
     c(i,j) is cin[j+i*matSize]
Packit Service c5cf8c
 */
Packit Service c5cf8c
#define MAXCOL 256
Packit Service c5cf8c
static int matSize = 0;         /* Must be < MAXCOL */
Packit Service c5cf8c
static int max_offset = 0;
Packit Service c5cf8c
void uop(void *, void *, int *, MPI_Datatype *);
Packit Service c5cf8c
void uop(void *cinPtr, void *coutPtr, int *count, MPI_Datatype * dtype)
Packit Service c5cf8c
{
Packit Service c5cf8c
    const int *cin = (const int *) cinPtr;
Packit Service c5cf8c
    int *cout = (int *) coutPtr;
Packit Service c5cf8c
    int i, j, k, nmat;
Packit Service c5cf8c
    int tempcol[MAXCOL];
Packit Service c5cf8c
    int offset1, offset2;
Packit Service c5cf8c
    int matsize2 = matSize * matSize;
Packit Service c5cf8c
Packit Service c5cf8c
    for (nmat = 0; nmat < *count; nmat++) {
Packit Service c5cf8c
        for (j = 0; j < matSize; j++) {
Packit Service c5cf8c
            for (i = 0; i < matSize; i++) {
Packit Service c5cf8c
                tempcol[i] = 0;
Packit Service c5cf8c
                for (k = 0; k < matSize; k++) {
Packit Service c5cf8c
                    /* col[i] += cin(i,k) * cout(k,j) */
Packit Service c5cf8c
                    offset1 = k + i * matSize;
Packit Service c5cf8c
                    offset2 = j + k * matSize;
Packit Service c5cf8c
                    assert(offset1 < max_offset);
Packit Service c5cf8c
                    assert(offset2 < max_offset);
Packit Service c5cf8c
                    tempcol[i] += cin[offset1] * cout[offset2];
Packit Service c5cf8c
                }
Packit Service c5cf8c
            }
Packit Service c5cf8c
            for (i = 0; i < matSize; i++) {
Packit Service c5cf8c
                offset1 = j + i * matSize;
Packit Service c5cf8c
                assert(offset1 < max_offset);
Packit Service c5cf8c
                cout[offset1] = tempcol[i];
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
        cin += matsize2;
Packit Service c5cf8c
        cout += matsize2;
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* Initialize the integer matrix as a permutation of rank with rank+1.
Packit Service c5cf8c
   If we call this matrix P_r, we know that product of P_0 P_1 ... P_{size-2}
Packit Service c5cf8c
   is the the matrix representing the permutation that shifts left by one.
Packit Service c5cf8c
   As the final matrix (in the size-1 position), we use the matrix that
Packit Service c5cf8c
   shifts RIGHT by one
Packit Service c5cf8c
*/
Packit Service c5cf8c
static void initMat(MPI_Comm comm, int mat[])
Packit Service c5cf8c
{
Packit Service c5cf8c
    int i, j, size, rank;
Packit Service c5cf8c
    int offset;
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Comm_rank(comm, &rank;;
Packit Service c5cf8c
    MPI_Comm_size(comm, &size);
Packit Service c5cf8c
Packit Service c5cf8c
    for (i = 0; i < size * size; i++) {
Packit Service c5cf8c
        assert(i < max_offset);
Packit Service c5cf8c
        mat[i] = 0;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if (rank < size - 1) {
Packit Service c5cf8c
        /* Create the permutation matrix that exchanges r with r+1 */
Packit Service c5cf8c
        for (i = 0; i < size; i++) {
Packit Service c5cf8c
            if (i == rank) {
Packit Service c5cf8c
                offset = ((i + 1) % size) + i * size;
Packit Service c5cf8c
                assert(offset < max_offset);
Packit Service c5cf8c
                mat[offset] = 1;
Packit Service c5cf8c
            } else if (i == ((rank + 1) % size)) {
Packit Service c5cf8c
                offset = ((i + size - 1) % size) + i * size;
Packit Service c5cf8c
                assert(offset < max_offset);
Packit Service c5cf8c
                mat[offset] = 1;
Packit Service c5cf8c
            } else {
Packit Service c5cf8c
                offset = i + i * size;
Packit Service c5cf8c
                assert(offset < max_offset);
Packit Service c5cf8c
                mat[offset] = 1;
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        /* Create the permutation matrix that shifts right by one */
Packit Service c5cf8c
        for (i = 0; i < size; i++) {
Packit Service c5cf8c
            for (j = 0; j < size; j++) {
Packit Service c5cf8c
                offset = j + i * size;  /* location of c(i,j) */
Packit Service c5cf8c
                mat[offset] = 0;
Packit Service c5cf8c
                if (((j - i + size) % size) == 1)
Packit Service c5cf8c
                    mat[offset] = 1;
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* Compare a matrix with the identity matrix */
Packit Service c5cf8c
static int isIdentity(MPI_Comm comm, int mat[])
Packit Service c5cf8c
{
Packit Service c5cf8c
    int i, j, size, rank, lerrs = 0;
Packit Service c5cf8c
    int offset;
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Comm_rank(comm, &rank;;
Packit Service c5cf8c
    MPI_Comm_size(comm, &size);
Packit Service c5cf8c
Packit Service c5cf8c
    for (i = 0; i < size; i++) {
Packit Service c5cf8c
        for (j = 0; j < size; j++) {
Packit Service c5cf8c
            if (i == j) {
Packit Service c5cf8c
                offset = j + i * size;
Packit Service c5cf8c
                assert(offset < max_offset);
Packit Service c5cf8c
                if (mat[offset] != 1) {
Packit Service c5cf8c
                    lerrs++;
Packit Service c5cf8c
                    if (errs + lerrs < 10) {
Packit Service c5cf8c
                        printf("[%d] mat[%d,%d] = %d, expected 1 for comm %s\n",
Packit Service c5cf8c
                               rank, i, j, mat[offset], MTestGetIntracommName());
Packit Service c5cf8c
                    }
Packit Service c5cf8c
                }
Packit Service c5cf8c
            } else {
Packit Service c5cf8c
                offset = j + i * size;
Packit Service c5cf8c
                assert(offset < max_offset);
Packit Service c5cf8c
                if (mat[offset] != 0) {
Packit Service c5cf8c
                    lerrs++;
Packit Service c5cf8c
                    if (errs + lerrs < 10) {
Packit Service c5cf8c
                        printf("[%d] mat[%d,%d] = %d, expected 0 for comm %s\n",
Packit Service c5cf8c
                               rank, i, j, mat[offset], MTestGetIntracommName());
Packit Service c5cf8c
                    }
Packit Service c5cf8c
                }
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
    return lerrs;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int main(int argc, char *argv[])
Packit Service c5cf8c
{
Packit Service c5cf8c
    int size;
Packit Service c5cf8c
    int minsize = 2, count;
Packit Service c5cf8c
    MPI_Comm comm;
Packit Service c5cf8c
    int *buf, *bufout;
Packit Service c5cf8c
    MPI_Op op;
Packit Service c5cf8c
    MPI_Datatype mattype;
Packit Service c5cf8c
Packit Service c5cf8c
    MTest_Init(&argc, &argv);
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Op_create(uop, 0, &op);
Packit Service c5cf8c
Packit Service c5cf8c
    while (MTestGetIntracommGeneral(&comm, minsize, 1)) {
Packit Service c5cf8c
        if (comm == MPI_COMM_NULL) {
Packit Service c5cf8c
            continue;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        MPI_Comm_size(comm, &size);
Packit Service c5cf8c
        matSize = size;
Packit Service c5cf8c
Packit Service c5cf8c
        /* Only one matrix for now */
Packit Service c5cf8c
        count = 1;
Packit Service c5cf8c
Packit Service c5cf8c
        /* A single matrix, the size of the communicator */
Packit Service c5cf8c
        MPI_Type_contiguous(size * size, MPI_INT, &mattype);
Packit Service c5cf8c
        MPI_Type_commit(&mattype);
Packit Service c5cf8c
Packit Service c5cf8c
        max_offset = count * size * size;
Packit Service c5cf8c
        buf = (int *) malloc(max_offset * sizeof(int));
Packit Service c5cf8c
        if (!buf) {
Packit Service c5cf8c
            MPI_Abort(MPI_COMM_WORLD, 1);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        bufout = (int *) malloc(max_offset * sizeof(int));
Packit Service c5cf8c
        if (!bufout) {
Packit Service c5cf8c
            MPI_Abort(MPI_COMM_WORLD, 1);
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        initMat(comm, buf);
Packit Service c5cf8c
        MPI_Allreduce(buf, bufout, count, mattype, op, comm);
Packit Service c5cf8c
        errs += isIdentity(comm, bufout);
Packit Service c5cf8c
Packit Service c5cf8c
        /* Try the same test, but using MPI_IN_PLACE */
Packit Service c5cf8c
        initMat(comm, bufout);
Packit Service c5cf8c
        MPI_Allreduce(MPI_IN_PLACE, bufout, count, mattype, op, comm);
Packit Service c5cf8c
        errs += isIdentity(comm, bufout);
Packit Service c5cf8c
Packit Service c5cf8c
        free(buf);
Packit Service c5cf8c
        free(bufout);
Packit Service c5cf8c
Packit Service c5cf8c
        MPI_Type_free(&mattype);
Packit Service c5cf8c
        MTestFreeComm(&comm);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Op_free(&op);
Packit Service c5cf8c
Packit Service c5cf8c
    MTest_Finalize(errs);
Packit Service c5cf8c
    return MTestReturnValue(errs);
Packit Service c5cf8c
}