Blame test/mpi/io/i_aggregation1.c

Packit 0848f5
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit 0848f5
/*
Packit 0848f5
 *  (C) 2014 by Argonne National Laboratory.
Packit 0848f5
 *      See COPYRIGHT in top-level directory.
Packit 0848f5
 */
Packit 0848f5
Packit 0848f5
/* Test case from John Bent (ROMIO req #835)
Packit 0848f5
 * Aggregation code was not handling certain access patterns when collective
Packit 0848f5
 * buffering forced */
Packit 0848f5
Packit 0848f5
/* Uses nonblocking collective I/O.*/
Packit 0848f5
Packit 0848f5
#include <unistd.h>
Packit 0848f5
#include <stdlib.h>
Packit 0848f5
#include <mpi.h>
Packit 0848f5
#include <stdio.h>
Packit 0848f5
#include <string.h>
Packit 0848f5
Packit 0848f5
#define NUM_OBJS 4
Packit 0848f5
#define OBJ_SIZE 1048576
Packit 0848f5
Packit 0848f5
extern char *optarg;
Packit 0848f5
extern int optind, opterr, optopt;
Packit 0848f5
Packit 0848f5
Packit 0848f5
char *prog = NULL;
Packit 0848f5
int debug = 0;
Packit 0848f5
Packit 0848f5
static void Usage(int line)
Packit 0848f5
{
Packit 0848f5
    int rank;
Packit 0848f5
    MPI_Comm_rank(MPI_COMM_WORLD, &rank;;
Packit 0848f5
    if (rank == 0) {
Packit 0848f5
        fprintf(stderr,
Packit 0848f5
                "Usage (line %d): %s [-d] [-h] -f filename\n"
Packit 0848f5
                "\t-d for debugging\n"
Packit 0848f5
                "\t-h to turn on the hints to force collective aggregation\n", line, prog);
Packit 0848f5
    }
Packit 0848f5
    exit(0);
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
static void fatal_error(int mpi_ret, MPI_Status * mpi_stat, const char *msg)
Packit 0848f5
{
Packit 0848f5
    fprintf(stderr, "Fatal error %s: %d\n", msg, mpi_ret);
Packit 0848f5
    MPI_Abort(MPI_COMM_WORLD, -1);
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
static void print_hints(int rank, MPI_File * mfh)
Packit 0848f5
{
Packit 0848f5
    MPI_Info info;
Packit 0848f5
    int nkeys;
Packit 0848f5
    int i, dummy_int;
Packit 0848f5
    char key[1024];
Packit 0848f5
    char value[1024];
Packit 0848f5
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
    if (rank == 0) {
Packit 0848f5
        MPI_File_get_info(*mfh, &info;;
Packit 0848f5
        MPI_Info_get_nkeys(info, &nkeys);
Packit 0848f5
Packit 0848f5
        printf("HINTS:\n");
Packit 0848f5
        for (i = 0; i < nkeys; i++) {
Packit 0848f5
            MPI_Info_get_nthkey(info, i, key);
Packit 0848f5
            printf("%35s -> ", key);
Packit 0848f5
            MPI_Info_get(info, key, 1024, value, &dummy_int);
Packit 0848f5
            printf("%s\n", value);
Packit 0848f5
        }
Packit 0848f5
        MPI_Info_free(&info;;
Packit 0848f5
    }
Packit 0848f5
    MPI_Barrier(MPI_COMM_WORLD);
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
static void fill_buffer(char *buffer, int bufsize, int rank, MPI_Offset offset)
Packit 0848f5
{
Packit 0848f5
    memset((void *) buffer, 0, bufsize);
Packit 0848f5
    snprintf(buffer, bufsize, "Hello from %d at %lld\n", rank, offset);
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
static MPI_Offset get_offset(int rank, int num_objs, int obj_size, int which_obj)
Packit 0848f5
{
Packit 0848f5
    MPI_Offset offset;
Packit 0848f5
    offset = (MPI_Offset) rank *num_objs * obj_size + which_obj * obj_size;
Packit 0848f5
    return offset;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
static void write_file(char *target, int rank, MPI_Info * info)
Packit 0848f5
{
Packit 0848f5
    MPI_File wfh;
Packit 0848f5
    MPI_Request *request;
Packit 0848f5
    MPI_Status *mpi_stat;
Packit 0848f5
    int mpi_ret;
Packit 0848f5
    int i;
Packit 0848f5
    char **buffer;
Packit 0848f5
Packit 0848f5
    request = (MPI_Request *) malloc(NUM_OBJS * sizeof(MPI_Request));
Packit 0848f5
    mpi_stat = (MPI_Status *) malloc(NUM_OBJS * sizeof(MPI_Status));
Packit 0848f5
    buffer = (char **) malloc(NUM_OBJS * sizeof(char *));
Packit 0848f5
Packit 0848f5
    if (debug)
Packit 0848f5
        printf("%d writing file %s\n", rank, target);
Packit 0848f5
Packit 0848f5
    if ((mpi_ret = MPI_File_open(MPI_COMM_WORLD, target,
Packit 0848f5
                                 MPI_MODE_WRONLY | MPI_MODE_CREATE, *info, &wfh))
Packit 0848f5
        != MPI_SUCCESS) {
Packit 0848f5
        fatal_error(mpi_ret, NULL, "open for write");
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* nonblocking collective write */
Packit 0848f5
    for (i = 0; i < NUM_OBJS; i++) {
Packit 0848f5
        MPI_Offset offset = get_offset(rank, NUM_OBJS, OBJ_SIZE, i);
Packit 0848f5
        buffer[i] = (char *) malloc(OBJ_SIZE);
Packit 0848f5
        fill_buffer(buffer[i], OBJ_SIZE, rank, offset);
Packit 0848f5
        if (debug)
Packit 0848f5
            printf("%s", buffer[i]);
Packit 0848f5
        if ((mpi_ret = MPI_File_iwrite_at_all(wfh, offset, buffer[i], OBJ_SIZE,
Packit 0848f5
                                              MPI_CHAR, &request[i]))
Packit 0848f5
            != MPI_SUCCESS) {
Packit 0848f5
            fatal_error(mpi_ret, NULL, "write");
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    if (debug)
Packit 0848f5
        print_hints(rank, &wfh;;
Packit 0848f5
Packit 0848f5
    MPI_Waitall(NUM_OBJS, request, mpi_stat);
Packit 0848f5
Packit 0848f5
    if ((mpi_ret = MPI_File_close(&wfh)) != MPI_SUCCESS) {
Packit 0848f5
        fatal_error(mpi_ret, NULL, "close for write");
Packit 0848f5
    }
Packit 0848f5
    if (debug)
Packit 0848f5
        printf("%d wrote file %s\n", rank, target);
Packit 0848f5
Packit 0848f5
    for (i = 0; i < NUM_OBJS; i++)
Packit 0848f5
        free(buffer[i]);
Packit 0848f5
    free(buffer);
Packit 0848f5
    free(mpi_stat);
Packit 0848f5
    free(request);
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
static int reduce_corruptions(int corrupt_blocks)
Packit 0848f5
{
Packit 0848f5
    int mpi_ret;
Packit 0848f5
    int sum;
Packit 0848f5
    if ((mpi_ret = MPI_Reduce(&corrupt_blocks, &sum, 1, MPI_INT, MPI_SUM, 0,
Packit 0848f5
                              MPI_COMM_WORLD)) != MPI_SUCCESS) {
Packit 0848f5
        fatal_error(mpi_ret, NULL, "MPI_Reduce");
Packit 0848f5
    }
Packit 0848f5
    return sum;
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
static void read_file(char *target, int rank, MPI_Info * info, int *corrupt_blocks)
Packit 0848f5
{
Packit 0848f5
    MPI_File rfh;
Packit 0848f5
    MPI_Offset *offset;
Packit 0848f5
    MPI_Request *request;
Packit 0848f5
    MPI_Status *mpi_stat;
Packit 0848f5
    int mpi_ret;
Packit 0848f5
    int i;
Packit 0848f5
    char **buffer;
Packit 0848f5
    char **verify_buf = NULL;
Packit 0848f5
Packit 0848f5
    offset = (MPI_Offset *) malloc(NUM_OBJS * sizeof(MPI_Offset));
Packit 0848f5
    request = (MPI_Request *) malloc(NUM_OBJS * sizeof(MPI_Request));
Packit 0848f5
    mpi_stat = (MPI_Status *) malloc(NUM_OBJS * sizeof(MPI_Status));
Packit 0848f5
    buffer = (char **) malloc(NUM_OBJS * sizeof(char *));
Packit 0848f5
    verify_buf = (char **) malloc(NUM_OBJS * sizeof(char *));
Packit 0848f5
Packit 0848f5
    if (debug)
Packit 0848f5
        printf("%d reading file %s\n", rank, target);
Packit 0848f5
Packit 0848f5
    if ((mpi_ret = MPI_File_open(MPI_COMM_WORLD, target, MPI_MODE_RDONLY,
Packit 0848f5
                                 *info, &rfh)) != MPI_SUCCESS) {
Packit 0848f5
        fatal_error(mpi_ret, NULL, "open for read");
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    /* nonblocking collective read */
Packit 0848f5
    for (i = 0; i < NUM_OBJS; i++) {
Packit 0848f5
        offset[i] = get_offset(rank, NUM_OBJS, OBJ_SIZE, i);
Packit 0848f5
        buffer[i] = (char *) malloc(OBJ_SIZE);
Packit 0848f5
        verify_buf[i] = (char *) malloc(OBJ_SIZE);
Packit 0848f5
        fill_buffer(verify_buf[i], OBJ_SIZE, rank, offset[i]);
Packit 0848f5
        if (debug)
Packit 0848f5
            printf("Expecting %s", verify_buf[i]);
Packit 0848f5
        if ((mpi_ret = MPI_File_iread_at_all(rfh, offset[i], buffer[i],
Packit 0848f5
                                             OBJ_SIZE, MPI_CHAR, &request[i]))
Packit 0848f5
            != MPI_SUCCESS) {
Packit 0848f5
            fatal_error(mpi_ret, NULL, "read");
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    MPI_Waitall(NUM_OBJS, request, mpi_stat);
Packit 0848f5
Packit 0848f5
    /* verification */
Packit 0848f5
    for (i = 0; i < NUM_OBJS; i++) {
Packit 0848f5
        if (memcmp(verify_buf[i], buffer[i], OBJ_SIZE) != 0) {
Packit 0848f5
            (*corrupt_blocks)++;
Packit 0848f5
            printf("Corruption at %lld\n", offset[i]);
Packit 0848f5
            if (debug) {
Packit 0848f5
                printf("\tExpecting %s\n" "\tRecieved  %s\n", verify_buf[i], buffer[i]);
Packit 0848f5
            }
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    if ((mpi_ret = MPI_File_close(&rfh)) != MPI_SUCCESS) {
Packit 0848f5
        fatal_error(mpi_ret, NULL, "close for read");
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    for (i = 0; i < NUM_OBJS; i++) {
Packit 0848f5
        free(verify_buf[i]);
Packit 0848f5
        free(buffer[i]);
Packit 0848f5
    }
Packit 0848f5
    free(verify_buf);
Packit 0848f5
    free(buffer);
Packit 0848f5
    free(mpi_stat);
Packit 0848f5
    free(request);
Packit 0848f5
    free(offset);
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
static void set_hints(MPI_Info * info)
Packit 0848f5
{
Packit 0848f5
    MPI_Info_set(*info, "romio_cb_write", "enable");
Packit 0848f5
    MPI_Info_set(*info, "romio_no_indep_rw", "1");
Packit 0848f5
    MPI_Info_set(*info, "cb_nodes", "1");
Packit 0848f5
    MPI_Info_set(*info, "cb_buffer_size", "4194304");
Packit 0848f5
}
Packit 0848f5
Packit 0848f5
/*
Packit 0848f5
void
Packit 0848f5
set_hints(MPI_Info *info, char *hints) {
Packit 0848f5
    char *delimiter = " ";
Packit 0848f5
    char *hints_cp  = strdup(hints);
Packit 0848f5
    char *key = strtok(hints_cp, delimiter);
Packit 0848f5
    char *val;
Packit 0848f5
    while (key) {
Packit 0848f5
        val = strtok(NULL, delimiter);
Packit 0848f5
        if (debug) printf("HINT: %s = %s\n", key, val);
Packit 0848f5
        if (! val) {
Packit 0848f5
            Usage(__LINE__);
Packit 0848f5
        }
Packit 0848f5
        MPI_Info_set(*info, key, val);
Packit 0848f5
        key = strtok(NULL, delimiter);
Packit 0848f5
    }
Packit 0848f5
    free(hints_cp);
Packit 0848f5
}
Packit 0848f5
*/
Packit 0848f5
Packit 0848f5
int main(int argc, char *argv[])
Packit 0848f5
{
Packit 0848f5
    int nproc = 1, rank = 0;
Packit 0848f5
    char *target = NULL;
Packit 0848f5
    int c;
Packit 0848f5
    MPI_Info info;
Packit 0848f5
    int mpi_ret;
Packit 0848f5
    int corrupt_blocks = 0;
Packit 0848f5
Packit 0848f5
    MPI_Init(&argc, &argv);
Packit 0848f5
    MPI_Comm_size(MPI_COMM_WORLD, &nproc);
Packit 0848f5
    MPI_Comm_rank(MPI_COMM_WORLD, &rank;;
Packit 0848f5
Packit 0848f5
    if ((mpi_ret = MPI_Info_create(&info)) != MPI_SUCCESS) {
Packit 0848f5
        if (rank == 0)
Packit 0848f5
            fatal_error(mpi_ret, NULL, "MPI_info_create.\n");
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    prog = strdup(argv[0]);
Packit 0848f5
Packit 0848f5
    if (argc > 1) {
Packit 0848f5
        while ((c = getopt(argc, argv, "df:h")) != EOF) {
Packit 0848f5
            switch (c) {
Packit 0848f5
            case 'd':
Packit 0848f5
                debug = 1;
Packit 0848f5
                break;
Packit 0848f5
            case 'f':
Packit 0848f5
                target = strdup(optarg);
Packit 0848f5
                break;
Packit 0848f5
            case 'h':
Packit 0848f5
                set_hints(&info;;
Packit 0848f5
                break;
Packit 0848f5
            default:
Packit 0848f5
                Usage(__LINE__);
Packit 0848f5
            }
Packit 0848f5
        }
Packit 0848f5
        if (!target) {
Packit 0848f5
            Usage(__LINE__);
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
    else {
Packit 0848f5
        target = "testfile";
Packit 0848f5
        set_hints(&info;;
Packit 0848f5
    }
Packit 0848f5
Packit 0848f5
    write_file(target, rank, &info;;
Packit 0848f5
    read_file(target, rank, &info, &corrupt_blocks);
Packit 0848f5
Packit 0848f5
    corrupt_blocks = reduce_corruptions(corrupt_blocks);
Packit 0848f5
    if (rank == 0) {
Packit 0848f5
        if (corrupt_blocks == 0) {
Packit 0848f5
            fprintf(stdout, " No Errors\n");
Packit 0848f5
        }
Packit 0848f5
        else {
Packit 0848f5
            fprintf(stdout, "%d/%d blocks corrupt\n", corrupt_blocks, nproc * NUM_OBJS);
Packit 0848f5
        }
Packit 0848f5
    }
Packit 0848f5
    MPI_Info_free(&info;;
Packit 0848f5
Packit 0848f5
    MPI_Finalize();
Packit 0848f5
    free(prog);
Packit 0848f5
    exit(0);
Packit 0848f5
}