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