Blame src/mpi/romio/test/noncontig_coll2.c

Packit Service c5cf8c
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
Packit Service c5cf8c
/*
Packit Service c5cf8c
 *  (C) 2001 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 <string.h>
Packit Service c5cf8c
#include <stdlib.h>
Packit Service c5cf8c
Packit Service c5cf8c
/* tests noncontiguous reads/writes using collective I/O */
Packit Service c5cf8c
Packit Service c5cf8c
/* this test is almost exactly like noncontig_coll.c with the following changes:
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * . generalized file writing/reading to handle arbitrary number of processors
Packit Service c5cf8c
 * . provides the "cb_config_list" hint with several permutations of the
Packit Service c5cf8c
 *   avaliable processors.
Packit Service c5cf8c
 *   [ makes use of code copied from ROMIO's ADIO code to collect the names of
Packit Service c5cf8c
 *   the processors ]
Packit Service c5cf8c
 */
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
#define MPI_CHECK(fn) { int _errcode; _errcode = (fn); if (_errcode != MPI_SUCCESS) handle_error(_errcode, #fn); }
Packit Service c5cf8c
Packit Service c5cf8c
/* we are going to muck with this later to make it evenly divisible by however many compute nodes we have */
Packit Service c5cf8c
#define STARTING_SIZE 5000
Packit Service c5cf8c
Packit Service c5cf8c
int test_file(char *filename, int mynod, int nprocs, char *cb_hosts, const char *msg, int verbose);
Packit Service c5cf8c
Packit Service c5cf8c
#define ADIOI_Free free
Packit Service c5cf8c
#define ADIOI_Malloc malloc
Packit Service c5cf8c
#define FPRINTF fprintf
Packit Service c5cf8c
/* I have no idea what the "D" stands for; it's how things are done in adio.h
Packit Service c5cf8c
 */
Packit Service c5cf8c
struct ADIO_cb_name_arrayD {
Packit Service c5cf8c
    int refct;
Packit Service c5cf8c
    int namect;
Packit Service c5cf8c
    char **names;
Packit Service c5cf8c
};
Packit Service c5cf8c
typedef struct ADIO_cb_name_arrayD *ADIO_cb_name_array;
Packit Service c5cf8c
Packit Service c5cf8c
void handle_error(int errcode, const char *str);
Packit Service c5cf8c
int cb_gather_name_array(MPI_Comm comm, ADIO_cb_name_array * arrayp);
Packit Service c5cf8c
void default_str(int mynod, int len, ADIO_cb_name_array array, char *dest);
Packit Service c5cf8c
void reverse_str(int mynod, int len, ADIO_cb_name_array array, char *dest);
Packit Service c5cf8c
void reverse_alternating_str(int mynod, int len, ADIO_cb_name_array array, char *dest);
Packit Service c5cf8c
void simple_shuffle_str(int mynod, int len, ADIO_cb_name_array array, char *dest);
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
void handle_error(int errcode, const char *str)
Packit Service c5cf8c
{
Packit Service c5cf8c
    char msg[MPI_MAX_ERROR_STRING];
Packit Service c5cf8c
    int resultlen;
Packit Service c5cf8c
    MPI_Error_string(errcode, msg, &resultlen);
Packit Service c5cf8c
    fprintf(stderr, "%s: %s\n", str, msg);
Packit Service c5cf8c
    MPI_Abort(MPI_COMM_WORLD, 1);
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
/* cb_gather_name_array() - gather a list of processor names from all processes
Packit Service c5cf8c
 *                          in a communicator and store them on rank 0.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * This is a collective call on the communicator(s) passed in.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Obtains a rank-ordered list of processor names from the processes in
Packit Service c5cf8c
 * "dupcomm".
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * Returns 0 on success, -1 on failure.
Packit Service c5cf8c
 *
Packit Service c5cf8c
 * NOTE: Needs some work to cleanly handle out of memory cases!
Packit Service c5cf8c
 */
Packit Service c5cf8c
int cb_gather_name_array(MPI_Comm comm, ADIO_cb_name_array * arrayp)
Packit Service c5cf8c
{
Packit Service c5cf8c
    /* this is copied from ROMIO, but since this test is for correctness,
Packit Service c5cf8c
     * not performance, note that we have removed the parts where ROMIO
Packit Service c5cf8c
     * uses a keyval to cache the name array.  We'll just rebuild it if we
Packit Service c5cf8c
     * need to */
Packit Service c5cf8c
Packit Service c5cf8c
    char my_procname[MPI_MAX_PROCESSOR_NAME], **procname = 0;
Packit Service c5cf8c
    int *procname_len = NULL, my_procname_len, *disp = NULL, i;
Packit Service c5cf8c
    int commsize, commrank;
Packit Service c5cf8c
    ADIO_cb_name_array array = NULL;
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Comm_size(comm, &commsize);
Packit Service c5cf8c
    MPI_Comm_rank(comm, &commrank);
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Get_processor_name(my_procname, &my_procname_len);
Packit Service c5cf8c
Packit Service c5cf8c
    /* allocate space for everything */
Packit Service c5cf8c
    array = (ADIO_cb_name_array) malloc(sizeof(*array));
Packit Service c5cf8c
    if (array == NULL) {
Packit Service c5cf8c
        return -1;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    array->refct = 1;
Packit Service c5cf8c
Packit Service c5cf8c
    if (commrank == 0) {
Packit Service c5cf8c
        /* process 0 keeps the real list */
Packit Service c5cf8c
        array->namect = commsize;
Packit Service c5cf8c
Packit Service c5cf8c
        array->names = (char **) ADIOI_Malloc(sizeof(char *) * commsize);
Packit Service c5cf8c
        if (array->names == NULL) {
Packit Service c5cf8c
            return -1;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        procname = array->names;        /* simpler to read */
Packit Service c5cf8c
Packit Service c5cf8c
        procname_len = (int *) ADIOI_Malloc(commsize * sizeof(int));
Packit Service c5cf8c
        if (procname_len == NULL) {
Packit Service c5cf8c
            return -1;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        /* everyone else just keeps an empty list as a placeholder */
Packit Service c5cf8c
        array->namect = 0;
Packit Service c5cf8c
        array->names = NULL;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    /* gather lengths first */
Packit Service c5cf8c
    MPI_Gather(&my_procname_len, 1, MPI_INT, procname_len, 1, MPI_INT, 0, comm);
Packit Service c5cf8c
Packit Service c5cf8c
    if (commrank == 0) {
Packit Service c5cf8c
#ifdef CB_CONFIG_LIST_DEBUG
Packit Service c5cf8c
        for (i = 0; i < commsize; i++) {
Packit Service c5cf8c
            FPRINTF(stderr, "len[%d] = %d\n", i, procname_len[i]);
Packit Service c5cf8c
        }
Packit Service c5cf8c
#endif
Packit Service c5cf8c
Packit Service c5cf8c
        for (i = 0; i < commsize; i++) {
Packit Service c5cf8c
            /* add one to the lengths because we need to count the
Packit Service c5cf8c
             * terminator, and we are going to use this list of lengths
Packit Service c5cf8c
             * again in the gatherv.
Packit Service c5cf8c
             */
Packit Service c5cf8c
            procname_len[i]++;
Packit Service c5cf8c
            procname[i] = malloc(procname_len[i]);
Packit Service c5cf8c
            if (procname[i] == NULL) {
Packit Service c5cf8c
                return -1;
Packit Service c5cf8c
            }
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
        /* create our list of displacements for the gatherv.  we're going
Packit Service c5cf8c
         * to do everything relative to the start of the region allocated
Packit Service c5cf8c
         * for procname[0]
Packit Service c5cf8c
         *
Packit Service c5cf8c
         * I suppose it is theoretically possible that the distance between
Packit Service c5cf8c
         * malloc'd regions could be more than will fit in an int.  We don't
Packit Service c5cf8c
         * cover that case.
Packit Service c5cf8c
         */
Packit Service c5cf8c
        disp = malloc(commsize * sizeof(int));
Packit Service c5cf8c
        disp[0] = 0;
Packit Service c5cf8c
        for (i = 1; i < commsize; i++) {
Packit Service c5cf8c
            disp[i] = (int) (procname[i] - procname[0]);
Packit Service c5cf8c
        }
Packit Service c5cf8c
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* now gather strings */
Packit Service c5cf8c
    if (commrank == 0) {
Packit Service c5cf8c
        MPI_Gatherv(my_procname, my_procname_len + 1, MPI_CHAR,
Packit Service c5cf8c
                    procname[0], procname_len, disp, MPI_CHAR, 0, comm);
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        /* if we didn't do this, we would need to allocate procname[]
Packit Service c5cf8c
         * on all processes...which seems a little silly.
Packit Service c5cf8c
         */
Packit Service c5cf8c
        MPI_Gatherv(my_procname, my_procname_len + 1, MPI_CHAR,
Packit Service c5cf8c
                    NULL, NULL, NULL, MPI_CHAR, 0, comm);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    if (commrank == 0) {
Packit Service c5cf8c
        /* no longer need the displacements or lengths */
Packit Service c5cf8c
        free(disp);
Packit Service c5cf8c
        free(procname_len);
Packit Service c5cf8c
Packit Service c5cf8c
#ifdef CB_CONFIG_LIST_DEBUG
Packit Service c5cf8c
        for (i = 0; i < commsize; i++) {
Packit Service c5cf8c
            fprintf(stderr, "name[%d] = %s\n", i, procname[i]);
Packit Service c5cf8c
        }
Packit Service c5cf8c
#endif
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    *arrayp = array;
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
void default_str(int mynod, int len, ADIO_cb_name_array array, char *dest)
Packit Service c5cf8c
{
Packit Service c5cf8c
    char *ptr;
Packit Service c5cf8c
    int i, p;
Packit Service c5cf8c
    if (!mynod) {
Packit Service c5cf8c
        ptr = dest;
Packit Service c5cf8c
        for (i = 0; i < array->namect; i++) {
Packit Service c5cf8c
            p = snprintf(ptr, len, "%s,", array->names[i]);
Packit Service c5cf8c
            ptr += p;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        /* chop off that last comma */
Packit Service c5cf8c
        dest[strlen(dest) - 1] = '\0';
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPI_Bcast(dest, len, MPI_CHAR, 0, MPI_COMM_WORLD);
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
void reverse_str(int mynod, int len, ADIO_cb_name_array array, char *dest)
Packit Service c5cf8c
{
Packit Service c5cf8c
    char *ptr;
Packit Service c5cf8c
    int i, p;
Packit Service c5cf8c
    if (!mynod) {
Packit Service c5cf8c
        ptr = dest;
Packit Service c5cf8c
        for (i = (array->namect - 1); i >= 0; i--) {
Packit Service c5cf8c
            p = snprintf(ptr, len, "%s,", array->names[i]);
Packit Service c5cf8c
            ptr += p;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        dest[strlen(dest) - 1] = '\0';
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPI_Bcast(dest, len, MPI_CHAR, 0, MPI_COMM_WORLD);
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
void reverse_alternating_str(int mynod, int len, ADIO_cb_name_array array, char *dest)
Packit Service c5cf8c
{
Packit Service c5cf8c
    char *ptr;
Packit Service c5cf8c
    int i, p;
Packit Service c5cf8c
    if (!mynod) {
Packit Service c5cf8c
        ptr = dest;
Packit Service c5cf8c
        /* evens */
Packit Service c5cf8c
        for (i = (array->namect - 1); i >= 0; i -= 2) {
Packit Service c5cf8c
            p = snprintf(ptr, len, "%s,", array->names[i]);
Packit Service c5cf8c
            ptr += p;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        /* odds */
Packit Service c5cf8c
        for (i = (array->namect - 2); i > 0; i -= 2) {
Packit Service c5cf8c
            p = snprintf(ptr, len, "%s,", array->names[i]);
Packit Service c5cf8c
            ptr += p;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        dest[strlen(dest) - 1] = '\0';
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPI_Bcast(dest, len, MPI_CHAR, 0, MPI_COMM_WORLD);
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
void simple_shuffle_str(int mynod, int len, ADIO_cb_name_array array, char *dest)
Packit Service c5cf8c
{
Packit Service c5cf8c
    char *ptr;
Packit Service c5cf8c
    int i, p;
Packit Service c5cf8c
    if (!mynod) {
Packit Service c5cf8c
        ptr = dest;
Packit Service c5cf8c
        for (i = (array->namect / 2); i < array->namect; i++) {
Packit Service c5cf8c
            p = snprintf(ptr, len, "%s,", array->names[i]);
Packit Service c5cf8c
            ptr += p;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        for (i = 0; i < (array->namect / 2); i++) {
Packit Service c5cf8c
            p = snprintf(ptr, len, "%s,", array->names[i]);
Packit Service c5cf8c
            ptr += p;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        dest[strlen(dest) - 1] = '\0';
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPI_Bcast(dest, len, MPI_CHAR, 0, MPI_COMM_WORLD);
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
int main(int argc, char **argv)
Packit Service c5cf8c
{
Packit Service c5cf8c
    int i, mynod, nprocs, len, errs = 0, sum_errs = 0, verbose = 0;
Packit Service c5cf8c
    char *filename;
Packit Service c5cf8c
    char *cb_config_string;
Packit Service c5cf8c
    int cb_config_len;
Packit Service c5cf8c
    ADIO_cb_name_array array;
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Init(&argc, &argv);
Packit Service c5cf8c
    MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
Packit Service c5cf8c
    MPI_Comm_rank(MPI_COMM_WORLD, &mynod);
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
    /* process 0 takes the file name as a command-line argument and
Packit Service c5cf8c
     * broadcasts it to other processes */
Packit Service c5cf8c
    if (!mynod) {
Packit Service c5cf8c
        i = 1;
Packit Service c5cf8c
        /* TODO: at some point, accept -v for verbose */
Packit Service c5cf8c
        while ((i < argc) && strcmp("-fname", *argv)) {
Packit Service c5cf8c
            i++;
Packit Service c5cf8c
            argv++;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        if (i >= argc) {
Packit Service c5cf8c
            fprintf(stderr, "\n*#  Usage: noncontig_coll -fname filename\n\n");
Packit Service c5cf8c
            MPI_Abort(MPI_COMM_WORLD, 1);
Packit Service c5cf8c
        }
Packit Service c5cf8c
        argv++;
Packit Service c5cf8c
        len = strlen(*argv);
Packit Service c5cf8c
        filename = (char *) malloc(len + 1);
Packit Service c5cf8c
        strcpy(filename, *argv);
Packit Service c5cf8c
        MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD);
Packit Service c5cf8c
        MPI_Bcast(filename, len + 1, MPI_CHAR, 0, MPI_COMM_WORLD);
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        MPI_Bcast(&len, 1, MPI_INT, 0, MPI_COMM_WORLD);
Packit Service c5cf8c
        filename = (char *) malloc(len + 1);
Packit Service c5cf8c
        MPI_Bcast(filename, len + 1, MPI_CHAR, 0, MPI_COMM_WORLD);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* want to hint the cb_config_list, but do so in a non-sequential way */
Packit Service c5cf8c
    cb_gather_name_array(MPI_COMM_WORLD, &array);
Packit Service c5cf8c
Packit Service c5cf8c
    /* sanity check */
Packit Service c5cf8c
    if (!mynod) {
Packit Service c5cf8c
        if (array->namect < 2) {
Packit Service c5cf8c
            fprintf(stderr, "Run this test on two or more hosts\n");
Packit Service c5cf8c
            MPI_Abort(MPI_COMM_WORLD, 1);
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
    /* get space for the permuted cb_config_string */
Packit Service c5cf8c
    if (!mynod) {
Packit Service c5cf8c
        cb_config_len = 0;
Packit Service c5cf8c
        for (i = 0; i < array->namect; i++) {
Packit Service c5cf8c
            /* +1: space for either a , or \0 if last */
Packit Service c5cf8c
            cb_config_len += strlen(array->names[i]) + 1;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        ++cb_config_len;
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPI_Bcast(&cb_config_len, 1, MPI_INT, 0, MPI_COMM_WORLD);
Packit Service c5cf8c
    if ((cb_config_string = malloc(cb_config_len)) == NULL) {
Packit Service c5cf8c
        perror("malloc");
Packit Service c5cf8c
        MPI_Abort(MPI_COMM_WORLD, 1);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* first, no hinting */
Packit Service c5cf8c
    errs += test_file(filename, mynod, nprocs, NULL, "collective w/o hinting", verbose);
Packit Service c5cf8c
Packit Service c5cf8c
    /* hint, but no change in order */
Packit Service c5cf8c
    default_str(mynod, cb_config_len, array, cb_config_string);
Packit Service c5cf8c
    errs +=
Packit Service c5cf8c
        test_file(filename, mynod, nprocs, cb_config_string, "collective w/ hinting: default order",
Packit Service c5cf8c
                  verbose);
Packit Service c5cf8c
Packit Service c5cf8c
    /*  reverse order */
Packit Service c5cf8c
    reverse_str(mynod, cb_config_len, array, cb_config_string);
Packit Service c5cf8c
    errs +=
Packit Service c5cf8c
        test_file(filename, mynod, nprocs, cb_config_string, "collective w/ hinting: reverse order",
Packit Service c5cf8c
                  verbose);
Packit Service c5cf8c
Packit Service c5cf8c
    /* reverse, every other */
Packit Service c5cf8c
    reverse_alternating_str(mynod, cb_config_len, array, cb_config_string);
Packit Service c5cf8c
    errs +=
Packit Service c5cf8c
        test_file(filename, mynod, nprocs, cb_config_string, "collective w/ hinting: permutation1",
Packit Service c5cf8c
                  verbose);
Packit Service c5cf8c
Packit Service c5cf8c
    /* second half, first half */
Packit Service c5cf8c
    simple_shuffle_str(mynod, cb_config_len, array, cb_config_string);
Packit Service c5cf8c
    errs +=
Packit Service c5cf8c
        test_file(filename, mynod, nprocs, cb_config_string, "collective w/ hinting: permutation2",
Packit Service c5cf8c
                  verbose);
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Allreduce(&errs, &sum_errs, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
Packit Service c5cf8c
Packit Service c5cf8c
    if (!mynod) {
Packit Service c5cf8c
        if (sum_errs)
Packit Service c5cf8c
            fprintf(stderr, "Found %d error cases\n", sum_errs);
Packit Service c5cf8c
        else
Packit Service c5cf8c
            printf(" No Errors\n");
Packit Service c5cf8c
    }
Packit Service c5cf8c
    free(filename);
Packit Service c5cf8c
    free(cb_config_string);
Packit Service c5cf8c
    MPI_Finalize();
Packit Service c5cf8c
    return 0;
Packit Service c5cf8c
}
Packit Service c5cf8c
Packit Service c5cf8c
#define SEEDER(x,y,z) ((x)*1000000 + (y) + (x)*(z))
Packit Service c5cf8c
Packit Service c5cf8c
int test_file(char *filename, int mynod, int nprocs, char *cb_hosts, const char *msg, int verbose)
Packit Service c5cf8c
{
Packit Service c5cf8c
    MPI_Datatype typevec, newtype, t[3];
Packit Service c5cf8c
    int *buf, i, b[3], errcode, errors = 0;
Packit Service c5cf8c
    MPI_File fh;
Packit Service c5cf8c
    MPI_Aint d[3];
Packit Service c5cf8c
    MPI_Status status;
Packit Service c5cf8c
    int SIZE = (STARTING_SIZE / nprocs) * nprocs;
Packit Service c5cf8c
    MPI_Info info;
Packit Service c5cf8c
Packit Service c5cf8c
    if (mynod == 0 && verbose)
Packit Service c5cf8c
        fprintf(stderr, "%s\n", msg);
Packit Service c5cf8c
Packit Service c5cf8c
    buf = (int *) malloc(SIZE * sizeof(int));
Packit Service c5cf8c
    if (buf == NULL) {
Packit Service c5cf8c
        perror("test_file");
Packit Service c5cf8c
        MPI_Abort(MPI_COMM_WORLD, -1);
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
Packit Service c5cf8c
    if (cb_hosts != NULL) {
Packit Service c5cf8c
        MPI_Info_create(&info;;
Packit Service c5cf8c
        MPI_Info_set(info, "cb_config_list", cb_hosts);
Packit Service c5cf8c
    } else {
Packit Service c5cf8c
        info = MPI_INFO_NULL;
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Type_vector(SIZE / nprocs, 1, nprocs, MPI_INT, &typevec);
Packit Service c5cf8c
Packit Service c5cf8c
    b[0] = b[1] = b[2] = 1;
Packit Service c5cf8c
    d[0] = 0;
Packit Service c5cf8c
    d[1] = mynod * sizeof(int);
Packit Service c5cf8c
    d[2] = SIZE * sizeof(int);
Packit Service c5cf8c
    t[0] = MPI_LB;
Packit Service c5cf8c
    t[1] = typevec;
Packit Service c5cf8c
    t[2] = MPI_UB;
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Type_struct(3, b, d, t, &newtype);
Packit Service c5cf8c
    MPI_Type_commit(&newtype);
Packit Service c5cf8c
    MPI_Type_free(&typevec);
Packit Service c5cf8c
Packit Service c5cf8c
    if (!mynod) {
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            fprintf(stderr,
Packit Service c5cf8c
                    "\ntesting noncontiguous in memory, noncontiguous in file using collective I/O\n");
Packit Service c5cf8c
        MPI_File_delete(filename, info);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPI_Barrier(MPI_COMM_WORLD);
Packit Service c5cf8c
Packit Service c5cf8c
    errcode = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_CREATE | MPI_MODE_RDWR, info, &fh;;
Packit Service c5cf8c
    if (errcode != MPI_SUCCESS) {
Packit Service c5cf8c
        handle_error(errcode, "MPI_File_open");
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_CHECK(MPI_File_set_view(fh, 0, MPI_INT, newtype, "native", info));
Packit Service c5cf8c
Packit Service c5cf8c
    for (i = 0; i < SIZE; i++)
Packit Service c5cf8c
        buf[i] = SEEDER(mynod, i, SIZE);
Packit Service c5cf8c
    errcode = MPI_File_write_all(fh, buf, 1, newtype, &status);
Packit Service c5cf8c
    if (errcode != MPI_SUCCESS) {
Packit Service c5cf8c
        handle_error(errcode, "nc mem - nc file: MPI_File_write_all");
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Barrier(MPI_COMM_WORLD);
Packit Service c5cf8c
Packit Service c5cf8c
    for (i = 0; i < SIZE; i++)
Packit Service c5cf8c
        buf[i] = -1;
Packit Service c5cf8c
Packit Service c5cf8c
    errcode = MPI_File_read_at_all(fh, 0, buf, 1, newtype, &status);
Packit Service c5cf8c
    if (errcode != MPI_SUCCESS) {
Packit Service c5cf8c
        handle_error(errcode, "nc mem - nc file: MPI_File_read_at_all");
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    /* the verification for N compute nodes is tricky. Say we have 3
Packit Service c5cf8c
     * processors.
Packit Service c5cf8c
     * process 0 sees: 0 -1 -1 3 -1 -1 ...
Packit Service c5cf8c
     * process 1 sees: -1 34 -1 -1 37 -1 ...
Packit Service c5cf8c
     * process 2 sees: -1 -1 68 -1 -1 71 ... */
Packit Service c5cf8c
Packit Service c5cf8c
    /* verify those leading -1s exist if they should */
Packit Service c5cf8c
    for (i = 0; i < mynod; i++) {
Packit Service c5cf8c
        if (buf[i] != -1) {
Packit Service c5cf8c
            if (verbose)
Packit Service c5cf8c
                fprintf(stderr, "Process %d: buf is %d, should be -1\n", mynod, buf[i]);
Packit Service c5cf8c
            errors++;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
    /* now the modulo games are hairy.  processor 0 sees real data in the 0th,
Packit Service c5cf8c
     * 3rd, 6th... elements of the buffer (assuming nprocs==3).  proc 1 sees
Packit Service c5cf8c
     * the data in 1st, 4th, 7th..., and proc 2 sees it in 2nd, 5th, 8th */
Packit Service c5cf8c
Packit Service c5cf8c
    for (/* 'i' set in above loop */ ; i < SIZE; i++) {
Packit Service c5cf8c
        if (((i - mynod) % nprocs) && buf[i] != -1) {
Packit Service c5cf8c
            if (verbose)
Packit Service c5cf8c
                fprintf(stderr, "Process %d: buf %d is %d, should be -1\n", mynod, i, buf[i]);
Packit Service c5cf8c
            errors++;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        if (!((i - mynod) % nprocs) && buf[i] != SEEDER(mynod, i, SIZE)) {
Packit Service c5cf8c
            if (verbose)
Packit Service c5cf8c
                fprintf(stderr, "Process %d: buf %d is %d, should be %d\n",
Packit Service c5cf8c
                        mynod, i, buf[i], SEEDER(mynod, i, SIZE));
Packit Service c5cf8c
            errors++;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPI_CHECK(MPI_File_close(&fh));
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Barrier(MPI_COMM_WORLD);
Packit Service c5cf8c
Packit Service c5cf8c
    if (!mynod) {
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            fprintf(stderr,
Packit Service c5cf8c
                    "\ntesting noncontiguous in memory, contiguous in file using collective I/O\n");
Packit Service c5cf8c
        MPI_File_delete(filename, info);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPI_Barrier(MPI_COMM_WORLD);
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_CHECK(MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_CREATE | MPI_MODE_RDWR, info, &fh));
Packit Service c5cf8c
Packit Service c5cf8c
    for (i = 0; i < SIZE; i++)
Packit Service c5cf8c
        buf[i] = SEEDER(mynod, i, SIZE);
Packit Service c5cf8c
    errcode = MPI_File_write_at_all(fh, mynod * (SIZE / nprocs) * sizeof(int),
Packit Service c5cf8c
                                    buf, 1, newtype, &status);
Packit Service c5cf8c
    if (errcode != MPI_SUCCESS)
Packit Service c5cf8c
        handle_error(errcode, "nc mem - c file: MPI_File_write_at_all");
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Barrier(MPI_COMM_WORLD);
Packit Service c5cf8c
Packit Service c5cf8c
    for (i = 0; i < SIZE; i++)
Packit Service c5cf8c
        buf[i] = -1;
Packit Service c5cf8c
Packit Service c5cf8c
    errcode = MPI_File_read_at_all(fh, mynod * (SIZE / nprocs) * sizeof(int),
Packit Service c5cf8c
                                   buf, 1, newtype, &status);
Packit Service c5cf8c
    if (errcode != MPI_SUCCESS)
Packit Service c5cf8c
        handle_error(errcode, "nc mem - c file: MPI_File_read_at_all");
Packit Service c5cf8c
Packit Service c5cf8c
    /* just like as above */
Packit Service c5cf8c
    for (i = 0; i < mynod; i++) {
Packit Service c5cf8c
        if (buf[i] != -1) {
Packit Service c5cf8c
            if (verbose)
Packit Service c5cf8c
                fprintf(stderr, "Process %d: buf is %d, should be -1\n", mynod, buf[i]);
Packit Service c5cf8c
            errors++;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
    for (/* i set in above loop */ ; i < SIZE; i++) {
Packit Service c5cf8c
        if (((i - mynod) % nprocs) && buf[i] != -1) {
Packit Service c5cf8c
            if (verbose)
Packit Service c5cf8c
                fprintf(stderr, "Process %d: buf %d is %d, should be -1\n", mynod, i, buf[i]);
Packit Service c5cf8c
            errors++;
Packit Service c5cf8c
        }
Packit Service c5cf8c
        if (!((i - mynod) % nprocs) && buf[i] != SEEDER(mynod, i, SIZE)) {
Packit Service c5cf8c
            if (verbose)
Packit Service c5cf8c
                fprintf(stderr, "Process %d: buf %d is %d, should be %d\n",
Packit Service c5cf8c
                        mynod, i, buf[i], SEEDER(mynod, i, SIZE));
Packit Service c5cf8c
            errors++;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_CHECK(MPI_File_close(&fh));
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Barrier(MPI_COMM_WORLD);
Packit Service c5cf8c
Packit Service c5cf8c
    if (!mynod) {
Packit Service c5cf8c
        if (verbose)
Packit Service c5cf8c
            fprintf(stderr,
Packit Service c5cf8c
                    "\ntesting contiguous in memory, noncontiguous in file using collective I/O\n");
Packit Service c5cf8c
        MPI_File_delete(filename, info);
Packit Service c5cf8c
    }
Packit Service c5cf8c
    MPI_Barrier(MPI_COMM_WORLD);
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_CHECK(MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_CREATE | MPI_MODE_RDWR, info, &fh));
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_CHECK(MPI_File_set_view(fh, 0, MPI_INT, newtype, "native", info));
Packit Service c5cf8c
Packit Service c5cf8c
    for (i = 0; i < SIZE; i++)
Packit Service c5cf8c
        buf[i] = SEEDER(mynod, i, SIZE);
Packit Service c5cf8c
    errcode = MPI_File_write_all(fh, buf, SIZE, MPI_INT, &status);
Packit Service c5cf8c
    if (errcode != MPI_SUCCESS)
Packit Service c5cf8c
        handle_error(errcode, "c mem - nc file: MPI_File_write_all");
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Barrier(MPI_COMM_WORLD);
Packit Service c5cf8c
Packit Service c5cf8c
    for (i = 0; i < SIZE; i++)
Packit Service c5cf8c
        buf[i] = -1;
Packit Service c5cf8c
Packit Service c5cf8c
    errcode = MPI_File_read_at_all(fh, 0, buf, SIZE, MPI_INT, &status);
Packit Service c5cf8c
    if (errcode != MPI_SUCCESS)
Packit Service c5cf8c
        handle_error(errcode, "c mem - nc file: MPI_File_read_at_all");
Packit Service c5cf8c
Packit Service c5cf8c
    /* same crazy checking */
Packit Service c5cf8c
    for (i = 0; i < SIZE; i++) {
Packit Service c5cf8c
        if (buf[i] != SEEDER(mynod, i, SIZE)) {
Packit Service c5cf8c
            if (verbose)
Packit Service c5cf8c
                fprintf(stderr, "Process %d: buf %d is %d, should be %d\n", mynod, i, buf[i],
Packit Service c5cf8c
                        SEEDER(mynod, i, SIZE));
Packit Service c5cf8c
            errors++;
Packit Service c5cf8c
        }
Packit Service c5cf8c
    }
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_CHECK(MPI_File_close(&fh));
Packit Service c5cf8c
Packit Service c5cf8c
    MPI_Type_free(&newtype);
Packit Service c5cf8c
    free(buf);
Packit Service c5cf8c
    if (info != MPI_INFO_NULL)
Packit Service c5cf8c
        MPI_Info_free(&info;;
Packit Service c5cf8c
    return errors;
Packit Service c5cf8c
}