Blame test/mpi/rma/adlb_mimic1.c

Packit 0848f5
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit 0848f5
/*
Packit 0848f5
 *
Packit 0848f5
 *  (C) 2003 by Argonne National Laboratory.
Packit 0848f5
 *      See COPYRIGHT in top-level directory.
Packit 0848f5
 */
Packit 0848f5
Packit 0848f5
#include <stdio.h>
Packit 0848f5
#include <stdlib.h>
Packit 0848f5
#include <string.h>
Packit 0848f5
#include "mpi.h"
Packit 0848f5
#include "mpitest.h"
Packit 0848f5
Packit 0848f5
#define NUM_TIMES 500
Packit 0848f5
#define MAX_BUF_SIZE (400 * 1024 * 1024)        /* 400 MB */
Packit 0848f5
#define PUT_SIZE (1024 * 1024)  /* 1MB */
Packit 0848f5
Packit 0848f5
/*
Packit 0848f5
static char MTEST_Descrip[] = "ADLB mimic test";
Packit 0848f5
*/
Packit 0848f5
Packit 0848f5
/*
Packit 0848f5
 * ALGORITHM:
Packit 0848f5
 *    This test uses one server process (S), one target process (T)
Packit 0848f5
 *    and a bunch of origin processes (O). 'O' PUTs (LOCK/PUT/UNLOCK)
Packit 0848f5
 *    data to a distinct part of the window, and sends a message to
Packit 0848f5
 *    'S' once the UNLOCK has completed. The server forwards this
Packit 0848f5
 *    message to 'T'. 'T' GETS the data from this buffer after it
Packit 0848f5
 *    receives the message from 'S', to see if it contains the correct
Packit 0848f5
 *    contents.
Packit 0848f5
 *
Packit 0848f5
 *                          -------
Packit 0848f5
 *                          |  S  |
Packit 0848f5
 *                          -------
Packit 0848f5
 *                         ^       \
Packit 0848f5
 *                step 2  /         \ step 3
Packit 0848f5
 *                 SEND  /           \ SEND
Packit 0848f5
 *                      /             v
Packit 0848f5
 *                  -------  step 1   -------
Packit 0848f5
 *                  |     | --------> |     |
Packit 0848f5
 *                  |     |   PUT     |     |
Packit 0848f5
 *                  |  O  |           |  T  |
Packit 0848f5
 *                  |     |  step 4   |     |
Packit 0848f5
 *                  |     | <-------- |     |
Packit 0848f5
 *                  -------   SEND    -------
Packit 0848f5
 *
Packit 0848f5
 */
Packit 0848f5
Packit 0848f5
int main(int argc, char **argv)
Packit 0848f5
{
Packit 0848f5
    int comm_size, comm_rank, i, by_rank, errs = 0;
Packit 0848f5
    int rc;
Packit 0848f5
    char *rma_win_addr, *local_buf;
Packit 0848f5
    char check;
Packit 0848f5
    MPI_Win win;
Packit 0848f5
    MPI_Status status;
Packit 0848f5
    int max_buf_size = 0, put_size = PUT_SIZE;
Packit 0848f5
Packit 0848f5
    MTest_Init(&argc, &argv);
Packit 0848f5
    MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
Packit 0848f5
    MPI_Comm_rank(MPI_COMM_WORLD, &comm_rank);
Packit 0848f5
Packit 0848f5
    if (comm_size <= 2) {
Packit 0848f5
        fprintf(stderr, "This test requires at least 3 processes\n");
Packit 0848f5
        MPI_Abort(MPI_COMM_WORLD, 1);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    max_buf_size = comm_size * put_size;
Packit 0848f5
    if (max_buf_size > MAX_BUF_SIZE) {
Packit 0848f5
        fprintf(stderr, "Too many processes in COMM_WORLD (max is %d)\n", MAX_BUF_SIZE / put_size);
Packit 0848f5
        MPI_Abort(MPI_COMM_WORLD, 1);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* If alloc mem returns an error (because too much memory is requested */
Packit 0848f5
    MPI_Errhandler_set(MPI_COMM_WORLD, MPI_ERRORS_RETURN);
Packit 0848f5
Packit 0848f5
    rc = MPI_Alloc_mem(max_buf_size, MPI_INFO_NULL, (void *) &rma_win_addr);
Packit 0848f5
    if (rc) {
Packit 0848f5
        MTestPrintErrorMsg("Unable to MPI_Alloc_mem space (not an error)", rc);
Packit 0848f5
        MPI_Abort(MPI_COMM_WORLD, 0);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    memset(rma_win_addr, 0, max_buf_size);
Packit 0848f5
    MPI_Win_create((void *) rma_win_addr, max_buf_size, 1, MPI_INFO_NULL, MPI_COMM_WORLD, &win);
Packit 0848f5
Packit 0848f5
    /* Note that it is not necessary to use MPI_Alloc_mem for the memory that
Packit 0848f5
     * is not part of the MPI_Win.  */
Packit 0848f5
    rc = MPI_Alloc_mem(put_size, MPI_INFO_NULL, (void *) &local_buf);
Packit 0848f5
    if (rc) {
Packit 0848f5
        MTestPrintErrorMsg("Unable to MPI_Alloc_mem space (not an error)", rc);
Packit 0848f5
        MPI_Abort(MPI_COMM_WORLD, 0);
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    for (i = 0; i < put_size; i++)
Packit 0848f5
        local_buf[i] = 1;
Packit 0848f5
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
Packit 0848f5
    if (comm_rank == 0) {       /* target */
Packit 0848f5
        for (i = 0; i < (NUM_TIMES * (comm_size - 2)); i++) {
Packit 0848f5
            /* Wait for a message from the server to notify me that
Packit 0848f5
             * someone put some data in my window */
Packit 0848f5
            MPI_Recv(&by_rank, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &status);
Packit 0848f5
Packit 0848f5
            /* Got a message from the server that 'by_rank' put some
Packit 0848f5
             * data in my local window. Check the last byte to make
Packit 0848f5
             * sure we got it correctly. */
Packit 0848f5
            MPI_Win_lock(MPI_LOCK_SHARED, 0, 0, win);
Packit 0848f5
            MPI_Get((void *) &check, 1, MPI_CHAR, 0,
Packit 0848f5
                    ((by_rank + 1) * put_size) - 1, 1, MPI_CHAR, win);
Packit 0848f5
            MPI_Win_unlock(0, win);
Packit 0848f5
Packit 0848f5
            /* If this is not the value I expect, count it as an error */
Packit 0848f5
            if (check != 1)
Packit 0848f5
                errs++;
Packit 0848f5
Packit 0848f5
            /* Reset the buffer to zero for the next round */
Packit 0848f5
            memset((void *) (rma_win_addr + (by_rank * put_size)), 0, put_size);
Packit 0848f5
Packit 0848f5
            /* Tell the origin that I am ready for the next round */
Packit 0848f5
            MPI_Send(NULL, 0, MPI_INT, by_rank, 0, MPI_COMM_WORLD);
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    else if (comm_rank == 1) {  /* server */
Packit 0848f5
        for (i = 0; i < (NUM_TIMES * (comm_size - 2)); i++) {
Packit 0848f5
            /* Wait for a message from any of the origin processes
Packit 0848f5
             * informing me that it has put data to the target
Packit 0848f5
             * process */
Packit 0848f5
            MPI_Recv(NULL, 0, MPI_INT, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
Packit 0848f5
            by_rank = status.MPI_SOURCE;
Packit 0848f5
Packit 0848f5
            /* Tell the target process that it should be seeing some
Packit 0848f5
             * data in its local buffer */
Packit 0848f5
            MPI_Send(&by_rank, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    else {      /* origin */
Packit 0848f5
        for (i = 0; i < NUM_TIMES; i++) {
Packit 0848f5
            /* Put some data in the target window */
Packit 0848f5
            MPI_Win_lock(MPI_LOCK_SHARED, 0, 0, win);
Packit 0848f5
            MPI_Put(local_buf, put_size, MPI_CHAR, 0, comm_rank * put_size,
Packit 0848f5
                    put_size, MPI_CHAR, win);
Packit 0848f5
            MPI_Win_unlock(0, win);
Packit 0848f5
Packit 0848f5
            /* Tell the server that the put has completed */
Packit 0848f5
            MPI_Send(NULL, 0, MPI_INT, 1, 0, MPI_COMM_WORLD);
Packit 0848f5
Packit 0848f5
            /* Wait for a message from the target that it is ready for
Packit 0848f5
             * the next round */
Packit 0848f5
            MPI_Recv(NULL, 0, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    MPI_Win_free(&win);
Packit 0848f5
Packit 0848f5
    MPI_Free_mem(rma_win_addr);
Packit 0848f5
    MPI_Free_mem(local_buf);
Packit 0848f5
Packit 0848f5
    MTest_Finalize(errs);
Packit 0848f5
    MPI_Finalize();
Packit 0848f5
Packit 0848f5
    return 0;
Packit 0848f5
}