|
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 |
}
|