Blame test/mpi/coll/allred4.c

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 *  (C) 2004 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 using matrix rotations";
Packit Service c5cf8c
*/
Packit Service c5cf8c
Packit Service c5cf8c
/* This example is similar to allred3.c, but uses only 3x3 matrics with
Packit Service c5cf8c
   integer-valued entries.  This is an associative but not commutative
Packit Service c5cf8c
   operation.
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*3]
Packit Service c5cf8c
Packit Service c5cf8c
   Three different matrices are used:
Packit Service c5cf8c
   I = identity matrix
Packit Service c5cf8c
   A = (1 0 0    B = (0 1 0
Packit Service c5cf8c
        0 0 1         1 0 0
Packit Service c5cf8c
        0 1 0)        0 0 1)
Packit Service c5cf8c
Packit Service c5cf8c
   The product
Packit Service c5cf8c
Packit Service c5cf8c
         I^k A I^(p-2-k-j) B I^j
Packit Service c5cf8c
Packit Service c5cf8c
   is
Packit Service c5cf8c
Packit Service c5cf8c
   (0 1 0
Packit Service c5cf8c
     0 0 1
Packit Service c5cf8c
     1 0 0)
Packit Service c5cf8c
Packit Service c5cf8c
   for all values of k, p, and j.
Packit Service c5cf8c
 */
Packit Service c5cf8c
Packit Service c5cf8c
void matmult(void *cinPtr, void *coutPtr, int *count, MPI_Datatype * dtype);
Packit Service c5cf8c
Packit Service c5cf8c
void matmult(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[3];
Packit Service c5cf8c
    int offset1, offset2;
Packit Service c5cf8c
Packit Service c5cf8c
    for (nmat = 0; nmat < *count; nmat++) {
Packit Service c5cf8c
        for (j = 0; j < 3; j++) {
Packit Service c5cf8c
            for (i = 0; i < 3; i++) {
Packit Service c5cf8c
                tempcol[i] = 0;
Packit Service c5cf8c
                for (k = 0; k < 3; k++) {
Packit Service c5cf8c
                    /* col[i] += cin(i,k) * cout(k,j) */
Packit Service c5cf8c
                    offset1 = k + i * 3;
Packit Service c5cf8c
                    offset2 = j + k * 3;
Packit Service c5cf8c
                    tempcol[i] += cin[offset1] * cout[offset2];
Packit Service c5cf8c
                }
Packit Service c5cf8c
            }
Packit Service c5cf8c
            for (i = 0; i < 3; i++) {
Packit Service c5cf8c
                offset1 = j + i * 3;
Packit Service c5cf8c
                cout[offset1] = tempcol[i];
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
        /* Advance to the next matrix */
Packit Service c5cf8c
        cin += 9;
Packit Service c5cf8c
        cout += 9;
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* Initialize the integer matrix as one of the
Packit Service c5cf8c
   above matrix entries, as a function of count.
Packit Service c5cf8c
   We guarantee that both the A and B matrices are included.
Packit Service c5cf8c
*/
Packit Service c5cf8c
static void initMat(int rank, int size, int nmat, int mat[])
Packit Service c5cf8c
{
Packit Service c5cf8c
    int i, kind;
Packit Service c5cf8c
Packit Service c5cf8c
    /* Zero the matrix */
Packit Service c5cf8c
    for (i = 0; i < 9; i++) {
Packit Service c5cf8c
        mat[i] = 0;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* Decide which matrix to create (I, A, or B) */
Packit Service c5cf8c
    if (size == 2) {
Packit Service c5cf8c
        /* rank 0 is A, 1 is B */
Packit Service c5cf8c
        kind = 1 + rank;
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        int tmpA, tmpB;
Packit Service c5cf8c
        /* Most ranks are identity matrices */
Packit Service c5cf8c
        kind = 0;
Packit Service c5cf8c
        /* Make sure exactly one rank gets the A matrix
Packit Service c5cf8c
         * and one the B matrix */
Packit Service c5cf8c
        tmpA = size / 4;
Packit Service c5cf8c
        tmpB = (3 * size) / 4;
Packit Service c5cf8c
Packit Service c5cf8c
        if (rank == tmpA)
Packit Service c5cf8c
            kind = 1;
Packit Service c5cf8c
        if (rank == tmpB)
Packit Service c5cf8c
            kind = 2;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    switch (kind) {
Packit Service c5cf8c
        case 0:        /* Identity */
Packit Service c5cf8c
            mat[0] = 1;
Packit Service c5cf8c
            mat[4] = 1;
Packit Service c5cf8c
            mat[8] = 1;
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        case 1:        /* A */
Packit Service c5cf8c
            mat[0] = 1;
Packit Service c5cf8c
            mat[5] = 1;
Packit Service c5cf8c
            mat[7] = 1;
Packit Service c5cf8c
            break;
Packit Service c5cf8c
        case 2:        /* B */
Packit Service c5cf8c
            mat[1] = 1;
Packit Service c5cf8c
            mat[3] = 1;
Packit Service c5cf8c
            mat[8] = 1;
Packit Service c5cf8c
            break;
Packit Service c5cf8c
    }
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
/* Compare a matrix with the known result */
Packit Service c5cf8c
static int checkResult(int nmat, int mat[], const char *msg)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int n, k, errs = 0, wrank;
Packit Service c5cf8c
    static int solution[9] = { 0, 1, 0,
Packit Service c5cf8c
        0, 0, 1,
Packit Service c5cf8c
        1, 0, 0
Packit Service c5cf8c
    };
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
Packit Service c5cf8c
Packit Service c5cf8c
    for (n = 0; n < nmat; n++) {
Packit Service c5cf8c
        for (k = 0; k < 9; k++) {
Packit Service c5cf8c
            if (mat[k] != solution[k]) {
Packit Service c5cf8c
                errs++;
Packit Service c5cf8c
                if (errs == 1) {
Packit Service c5cf8c
                    printf("Errors for communicators %s\n", MTestGetIntracommName());
Packit Service c5cf8c
                    fflush(stdout);
Packit Service c5cf8c
                }
Packit Service c5cf8c
                if (errs < 10) {
Packit Service c5cf8c
                    printf("[%d]matrix #%d(%s): Expected mat[%d,%d] = %d, got %d\n",
Packit Service c5cf8c
                           wrank, n, msg, k / 3, k % 3, solution[k], mat[k]);
Packit Service c5cf8c
                    fflush(stdout);
Packit Service c5cf8c
                }
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
        /* Advance to the next matrix */
Packit Service c5cf8c
        mat += 9;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    return errs;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int main(int argc, char *argv[])
Packit Service c5cf8c
{
Packit Service c5cf8c
    int errs = 0;
Packit Service c5cf8c
    int size, rank;
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
    int i;
Packit Service c5cf8c
Packit Service c5cf8c
    MTest_Init(&argc, &argv);
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Op_create(matmult, 0, &op);
Packit Service c5cf8c
Packit Service c5cf8c
    /* A single rotation matrix (3x3, stored as 9 consequetive elements) */
Packit Service c5cf8c
    MPI_Type_contiguous(9, MPI_INT, &mattype);
Packit Service c5cf8c
    MPI_Type_commit(&mattype);
Packit Service c5cf8c
Packit Service c5cf8c
    /* Sanity check: test that our routines work properly */
Packit Service c5cf8c
    {
Packit Service c5cf8c
        int one = 1;
Packit Service c5cf8c
        buf = (int *) malloc(4 * 9 * sizeof(int));
Packit Service c5cf8c
        initMat(0, 4, 0, &buf[0]);
Packit Service c5cf8c
        initMat(1, 4, 0, &buf[9]);
Packit Service c5cf8c
        initMat(2, 4, 0, &buf[18]);
Packit Service c5cf8c
        initMat(3, 4, 0, &buf[27]);
Packit Service c5cf8c
        matmult(&buf[0], &buf[9], &one, &mattype);
Packit Service c5cf8c
        matmult(&buf[9], &buf[18], &one, &mattype);
Packit Service c5cf8c
        matmult(&buf[18], &buf[27], &one, &mattype);
Packit Service c5cf8c
        checkResult(1, &buf[27], "Sanity Check");
Packit Service c5cf8c
        free(buf);
Packit Service c5cf8c
    }
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
        MPI_Comm_rank(comm, &rank;;
Packit Service c5cf8c
Packit Service c5cf8c
        for (count = 1; count < size; count++) {
Packit Service c5cf8c
Packit Service c5cf8c
            /* Allocate the matrices */
Packit Service c5cf8c
            buf = (int *) malloc(count * 9 * sizeof(int));
Packit Service c5cf8c
            if (!buf) {
Packit Service c5cf8c
                MPI_Abort(MPI_COMM_WORLD, 1);
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            bufout = (int *) malloc(count * 9 * 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
            for (i = 0; i < count; i++) {
Packit Service c5cf8c
                initMat(rank, size, i, &buf[i * 9]);
Packit Service c5cf8c
            }
Packit Service c5cf8c
Packit Service c5cf8c
            MPI_Allreduce(buf, bufout, count, mattype, op, comm);
Packit Service c5cf8c
            errs += checkResult(count, bufout, "");
Packit Service c5cf8c
Packit Service c5cf8c
            /* Try the same test, but using MPI_IN_PLACE */
Packit Service c5cf8c
            for (i = 0; i < count; i++) {
Packit Service c5cf8c
                initMat(rank, size, i, &bufout[i * 9]);
Packit Service c5cf8c
            }
Packit Service c5cf8c
            MPI_Allreduce(MPI_IN_PLACE, bufout, count, mattype, op, comm);
Packit Service c5cf8c
            errs += checkResult(count, bufout, "IN_PLACE");
Packit Service c5cf8c
Packit Service c5cf8c
            free(buf);
Packit Service c5cf8c
            free(bufout);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        MTestFreeComm(&comm);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Op_free(&op);
Packit Service c5cf8c
    MPI_Type_free(&mattype);
Packit Service c5cf8c
Packit Service c5cf8c
    MTest_Finalize(errs);
Packit Service c5cf8c
    return MTestReturnValue(errs);
Packit Service c5cf8c
}