Blame test/mpi/rma/lockcontention2.c

Packit 0848f5
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit 0848f5
/*
Packit 0848f5
 *  (C) 2010 by Argonne National Laboratory.
Packit 0848f5
 *      See COPYRIGHT in top-level directory.
Packit 0848f5
 */
Packit 0848f5
#include "mpi.h"
Packit 0848f5
#include "stdio.h"
Packit 0848f5
#include "stdlib.h"
Packit 0848f5
#include "mpitest.h"
Packit 0848f5
Packit 0848f5
/*
Packit 0848f5
 * Tests for lock contention, including special cases within the MPICH code
Packit 0848f5
 * (any MPI implementation should pass these tests; in the MPICH case, our
Packit 0848f5
 * coverage analysis showed that the lockcontention.c test was not covering
Packit 0848f5
 * all cases, and in fact, this test revealed a bug in the code).
Packit 0848f5
 *
Packit 0848f5
 * In all of these tests, each process writes (or accesses) the values
Packit 0848f5
 * rank + i*size_of_world for NELM times.
Packit 0848f5
 *
Packit 0848f5
 * This test strives to avoid operations not strictly permitted by MPI RMA,
Packit 0848f5
 * for example, it doesn't target the same locations with multiple put/get
Packit 0848f5
 * calls in the same access epoch.
Packit 0848f5
 */
Packit 0848f5
Packit 0848f5
#define NELM 200
Packit 0848f5
#define NBLOCK 10
Packit 0848f5
#define MAX_ERRS_REPORT 10
Packit 0848f5
Packit 0848f5
/*
Packit 0848f5
 *  Each process writes data into the rmabuf on the process with target rank
Packit 0848f5
 *  trank.  The final result in rmabuf are the consecutive integers starting
Packit 0848f5
 *  from 0.  Each process, however, does not write a consecutive block.
Packit 0848f5
 *  Instead, they write these locations:
Packit 0848f5
 *
Packit 0848f5
 *  for i=0,...,NELM-1
Packit 0848f5
 *     for j=0,...,NBLOCK-1
Packit 0848f5
 *         j + NBLOCK * (rank + i * wsize)
Packit 0848f5
 *
Packit 0848f5
 * The value written is the location.
Packit 0848f5
 *
Packit 0848f5
 * In many cases, multiple RMA operations are needed.  Where these must not
Packit 0848f5
 * overlap, the above pattern is replicated at NBLOCK*NELM*wsize.
Packit 0848f5
 * (NBLOCK is either 1 or NBLOCK in the code below, depending on use)
Packit 0848f5
 */
Packit 0848f5
Packit 0848f5
static int toterrs = 0;
Packit 0848f5
Packit 0848f5
int testValues(int, int, int, int *, const char *);
Packit 0848f5
Packit 0848f5
int main(int argc, char *argv[])
Packit 0848f5
{
Packit 0848f5
    int rank, wsize, i, j, cnt;
Packit 0848f5
    int *rmabuf, *localbuf, *localbuf2, *vals;
Packit 0848f5
    MPI_Win win;
Packit 0848f5
    int trank = 0;
Packit 0848f5
    int windowsize;
Packit 0848f5
Packit 0848f5
    MTest_Init(&argc, &argv);
Packit 0848f5
    MPI_Comm_size(MPI_COMM_WORLD, &wsize);
Packit 0848f5
    MPI_Comm_rank(MPI_COMM_WORLD, &rank;;
Packit 0848f5
Packit 0848f5
    if (wsize < 2) {
Packit 0848f5
        fprintf(stderr, "Run this program with at least 2 processes\n");
Packit 0848f5
        MPI_Abort(MPI_COMM_WORLD, 1);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    windowsize = (2 * NBLOCK + 2) * NELM * wsize;
Packit 0848f5
    rmabuf = (int *) malloc(windowsize * sizeof(int));
Packit 0848f5
    localbuf = (int *) malloc(NELM * sizeof(int));
Packit 0848f5
    localbuf2 = (int *) malloc(NELM * NBLOCK * sizeof(int));
Packit 0848f5
    vals = (int *) malloc(NELM * sizeof(int));
Packit 0848f5
Packit 0848f5
    /*
Packit 0848f5
     * Initialize the buffers
Packit 0848f5
     */
Packit 0848f5
    for (i = 0; i < NELM; i++) {
Packit 0848f5
        localbuf[i] = rank + i * wsize;
Packit 0848f5
    }
Packit 0848f5
    cnt = 0;
Packit 0848f5
    for (i = 0; i < NELM; i++) {
Packit 0848f5
        for (j = 0; j < NBLOCK; j++) {
Packit 0848f5
            localbuf2[cnt++] = j + NBLOCK * (rank + i * wsize);
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
    for (i = 0; i < windowsize; i++) {
Packit 0848f5
        rmabuf[i] = -1;
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* Create the window */
Packit 0848f5
    MPI_Win_create(rmabuf, windowsize * sizeof(int), sizeof(int), MPI_INFO_NULL,
Packit 0848f5
                   MPI_COMM_WORLD, &win);
Packit 0848f5
Packit 0848f5
    /* Multiple puts, with contention at trank */
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
    for (i = 0; i < NELM; i++) {
Packit 0848f5
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
Packit 0848f5
        MPI_Put(&localbuf[i], 1, MPI_INT, trank, rank + i * wsize, 1, MPI_INT, win);
Packit 0848f5
        MPI_Put(&localbuf[i], 1, MPI_INT, trank, rank + (i + NELM) * wsize, 1, MPI_INT, win);
Packit 0848f5
        MPI_Win_unlock(trank, win);
Packit 0848f5
    }
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
    if (rank == trank) {
Packit 0848f5
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
Packit 0848f5
        toterrs += testValues(1, NELM, wsize, rmabuf, "Multiple puts (1)");
Packit 0848f5
        toterrs += testValues(1, NELM, wsize, rmabuf + wsize * NELM, "Multiple puts (2)");
Packit 0848f5
        MPI_Win_unlock(trank, win);
Packit 0848f5
    }
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
    /* Reinit the rmabuf */
Packit 0848f5
    for (i = 0; i < windowsize; i++) {
Packit 0848f5
        rmabuf[i] = -1;
Packit 0848f5
    }
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
Packit 0848f5
    /* Single put with contention */
Packit 0848f5
    trank = 0;
Packit 0848f5
    for (i = 0; i < NELM; i++) {
Packit 0848f5
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
Packit 0848f5
        MPI_Put(&localbuf[i], 1, MPI_INT, trank, rank + i * wsize, 1, MPI_INT, win);
Packit 0848f5
        MPI_Win_unlock(trank, win);
Packit 0848f5
    }
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
    if (rank == trank) {
Packit 0848f5
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
Packit 0848f5
        toterrs += testValues(1, NELM, wsize, rmabuf, "Single put");
Packit 0848f5
        MPI_Win_unlock(trank, win);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* Reinit the rmabuf */
Packit 0848f5
    for (i = 0; i < windowsize; i++) {
Packit 0848f5
        rmabuf[i] = -1;
Packit 0848f5
    }
Packit 0848f5
    /* Longer puts with contention at trank */
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
    for (i = 0; i < NELM; i++) {
Packit 0848f5
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
Packit 0848f5
        if (rank != trank) {
Packit 0848f5
            MPI_Put(&localbuf2[i * NBLOCK], NBLOCK, MPI_INT, trank,
Packit 0848f5
                    NELM * wsize + NBLOCK * (rank + i * wsize), NBLOCK, MPI_INT, win);
Packit 0848f5
            MPI_Put(&localbuf2[i * NBLOCK], NBLOCK, MPI_INT, trank,
Packit 0848f5
                    NELM * wsize + NBLOCK * (rank + (i + NELM) * wsize), NBLOCK, MPI_INT, win);
Packit 0848f5
        }
Packit 0848f5
        MPI_Put(&localbuf[i], 1, MPI_INT, trank, rank + i * wsize, 1, MPI_INT, win);
Packit 0848f5
        MPI_Win_unlock(trank, win);
Packit 0848f5
    }
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
    if (rank == trank) {
Packit 0848f5
        /* For simplicity in testing, set the values that rank==trank
Packit 0848f5
         * would have set. */
Packit 0848f5
        for (i = 0; i < NELM; i++) {
Packit 0848f5
            for (j = 0; j < NBLOCK; j++) {
Packit 0848f5
                rmabuf[NELM * wsize + NBLOCK * (trank + i * wsize) + j] =
Packit 0848f5
                    j + NBLOCK * (trank + i * wsize);
Packit 0848f5
                rmabuf[NELM * wsize + NBLOCK * (trank + (i + NELM) * wsize) + j] =
Packit 0848f5
                    j + NBLOCK * (trank + i * wsize);
Packit 0848f5
            }
Packit 0848f5
        }
Packit 0848f5
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
Packit 0848f5
        toterrs += testValues(1, NELM, wsize, rmabuf, "Long puts (1)");
Packit 0848f5
        toterrs += testValues(NBLOCK, NELM, wsize, rmabuf + NELM * wsize, "Long puts(2)");
Packit 0848f5
        toterrs += testValues(NBLOCK, NELM, wsize,
Packit 0848f5
                              rmabuf + NELM * wsize * (1 + NBLOCK), "Long puts(3)");
Packit 0848f5
        MPI_Win_unlock(trank, win);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* Reinit the rmabuf */
Packit 0848f5
    for (i = 0; i < windowsize; i++) {
Packit 0848f5
        rmabuf[i] = -1;
Packit 0848f5
    }
Packit 0848f5
    for (i = 0; i < NELM; i++)
Packit 0848f5
        vals[i] = -2;
Packit 0848f5
Packit 0848f5
    /* Put mixed with Get */
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
    for (i = 0; i < NELM; i++) {
Packit 0848f5
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
Packit 0848f5
        if (rank != trank) {
Packit 0848f5
            MPI_Put(&localbuf2[i], NBLOCK, MPI_INT, trank,
Packit 0848f5
                    NELM * wsize + NBLOCK * (rank + i * wsize), NBLOCK, MPI_INT, win);
Packit 0848f5
            MPI_Put(&localbuf[i], 1, MPI_INT, trank, rank + i * wsize, 1, MPI_INT, win);
Packit 0848f5
        }
Packit 0848f5
        else {
Packit 0848f5
            MPI_Get(&vals[i], 1, MPI_INT, trank, i, 1, MPI_INT, win);
Packit 0848f5
        }
Packit 0848f5
        MPI_Win_unlock(trank, win);
Packit 0848f5
    }
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
    if (rank == trank) {
Packit 0848f5
        /* Just test the Get */
Packit 0848f5
        for (i = 0; i < wsize; i++) {
Packit 0848f5
            if (i == trank) {
Packit 0848f5
                if (vals[i] != -1) {
Packit 0848f5
                    toterrs++;
Packit 0848f5
                    if (toterrs < MAX_ERRS_REPORT) {
Packit 0848f5
                        printf("put/get: vals[%d] = %d, expected -1\n", i, vals[i]);
Packit 0848f5
                    }
Packit 0848f5
                }
Packit 0848f5
            }
Packit 0848f5
            else if (vals[i] != i && vals[i] != -1) {
Packit 0848f5
                toterrs++;
Packit 0848f5
                if (toterrs < MAX_ERRS_REPORT) {
Packit 0848f5
                    printf("put/get: vals[%d] = %d, expected -1 or %d\n", i, vals[i], i);
Packit 0848f5
                }
Packit 0848f5
            }
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* Contention only with get */
Packit 0848f5
    for (i = 0; i < windowsize; i++) {
Packit 0848f5
        rmabuf[i] = -i;
Packit 0848f5
    }
Packit 0848f5
    for (i = 0; i < NELM; i++)
Packit 0848f5
        vals[i] = -2;
Packit 0848f5
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
    for (i = 0; i < NELM; i++) {
Packit 0848f5
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
Packit 0848f5
        MPI_Get(&vals[i], 1, MPI_INT, trank, i, 1, MPI_INT, win);
Packit 0848f5
        MPI_Win_unlock(trank, win);
Packit 0848f5
    }
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
    if (rank == trank) {
Packit 0848f5
        for (i = 0; i < NELM; i++) {
Packit 0848f5
            if (vals[i] != -i) {
Packit 0848f5
                toterrs++;
Packit 0848f5
                if (toterrs < MAX_ERRS_REPORT) {
Packit 0848f5
                    printf("single get: vals[%d] = %d, expected %d\n", i, vals[i], -i);
Packit 0848f5
                }
Packit 0848f5
            }
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* Contention with accumulate */
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
    for (i = 0; i < NELM * wsize; i++) {
Packit 0848f5
        rmabuf[i] = 0;
Packit 0848f5
    }
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
    for (i = 0; i < NELM; i++) {
Packit 0848f5
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
Packit 0848f5
        MPI_Accumulate(&localbuf[i], 1, MPI_INT, trank, rank + i * wsize, 1, MPI_INT, MPI_SUM, win);
Packit 0848f5
        MPI_Accumulate(&localbuf[i], 1, MPI_INT, trank, rank + i * wsize, 1, MPI_INT, MPI_SUM, win);
Packit 0848f5
        MPI_Win_unlock(trank, win);
Packit 0848f5
    }
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
    if (rank == trank) {
Packit 0848f5
        MPI_Win_lock(MPI_LOCK_EXCLUSIVE, trank, 0, win);
Packit 0848f5
        for (i = 0; i < NELM * wsize; i++) {
Packit 0848f5
            if (rmabuf[i] != 2 * i) {
Packit 0848f5
                toterrs++;
Packit 0848f5
                if (toterrs < MAX_ERRS_REPORT) {
Packit 0848f5
                    printf("2 accumulate: rmabuf[%d] = %d, expected %d\n", i, rmabuf[i], 2 * i);
Packit 0848f5
                }
Packit 0848f5
            }
Packit 0848f5
        }
Packit 0848f5
        MPI_Win_unlock(trank, win);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    MPI_Win_free(&win);
Packit 0848f5
Packit 0848f5
    free(rmabuf);
Packit 0848f5
    free(localbuf);
Packit 0848f5
    free(localbuf2);
Packit 0848f5
    free(vals);
Packit 0848f5
Packit 0848f5
    MTest_Finalize(toterrs);
Packit 0848f5
    MPI_Finalize();
Packit 0848f5
    return 0;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
/* Test the values in the rmabuf against the expected values.  Return the
Packit 0848f5
   number of errors */
Packit 0848f5
int testValues(int nb, int nelm, int wsize, int *rmabuf, const char *msg)
Packit 0848f5
{
Packit 0848f5
    int i, errs = 0;
Packit 0848f5
Packit 0848f5
    for (i = 0; i < nb * nelm * wsize; i++) {
Packit 0848f5
        if (rmabuf[i] != i) {
Packit 0848f5
            if (toterrs + errs < MAX_ERRS_REPORT) {
Packit 0848f5
                printf("%s:rmabuf[%d] = %d expected %d\n", msg, i, rmabuf[i], i);
Packit 0848f5
            }
Packit 0848f5
            errs++;
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    return errs;
Packit 0848f5
}