mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-12-27 08:01:04 +08:00
a90bdbbcfc
These calls are non-C99 but protected by ifdefs and have no Windows equivalents: * HDalarm * HDasprintf * HDclock_gettime * HDfcntl * HDgethostname * HDgetrusage * HDsymlink
1244 lines
43 KiB
C
1244 lines
43 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* Copyright by The HDF Group. *
|
|
* All rights reserved. *
|
|
* *
|
|
* This file is part of HDF5. The full HDF5 copyright notice, including *
|
|
* terms governing use, modification, and redistribution, is contained in *
|
|
* the COPYING file, which can be found at the root of the source code *
|
|
* distribution tree, or in https://www.hdfgroup.org/licenses. *
|
|
* If you do not have access to either file, you may request a copy from *
|
|
* help@hdfgroup.org. *
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
/*
|
|
* MPIO independent overlapping writes.
|
|
*
|
|
* First n-1 processes open 1 file.
|
|
* Each of the n-1 process writes chunks of data to the file in round-robin
|
|
* fashion, in a interleaved but not overlapped fashion. Using increasing
|
|
* chunk sizes for the benefits of testing different write sizes and also
|
|
* reducing the numbers of writes.
|
|
*
|
|
* Last process (n-1) just waits.
|
|
* First n-1 processes finish writing and cloose the file.
|
|
* Last process opens the same file and verifies the data.
|
|
*/
|
|
|
|
#include "testpar.h"
|
|
|
|
/* FILENAME and filenames must have the same number of names */
|
|
const char *FILENAME[2] = {"MPItest", NULL};
|
|
char filenames[2][200];
|
|
int nerrors = 0;
|
|
hid_t fapl; /* file access property list */
|
|
|
|
/* protocols */
|
|
static int errors_sum(int nerrs);
|
|
|
|
#define MPIO_TEST_WRITE_SIZE 1024 * 1024 /* 1 MB */
|
|
|
|
static int
|
|
test_mpio_overlap_writes(char *filename)
|
|
{
|
|
int mpi_size, mpi_rank;
|
|
MPI_Comm comm;
|
|
MPI_Info info = MPI_INFO_NULL;
|
|
int color, mrc;
|
|
MPI_File fh;
|
|
int i;
|
|
int vrfyerrs, nerrs;
|
|
unsigned char *buf = NULL;
|
|
int bufsize;
|
|
MPI_Offset stride;
|
|
MPI_Offset mpi_off;
|
|
MPI_Status mpi_stat;
|
|
|
|
if (VERBOSE_MED)
|
|
printf("MPIO independent overlapping writes test on file %s\n", filename);
|
|
|
|
nerrs = 0;
|
|
/* set up MPI parameters */
|
|
MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
|
|
|
|
/* Need at least 2 processes */
|
|
if (mpi_size < 2) {
|
|
if (MAINPROCESS)
|
|
printf("Need at least 2 processes to run MPIO test.\n");
|
|
printf(" -SKIP- \n");
|
|
return 0;
|
|
}
|
|
|
|
bufsize = 4093; /* use some prime number for size */
|
|
if (NULL == (buf = malloc((size_t)bufsize))) {
|
|
if (MAINPROCESS)
|
|
printf("couldn't allocate buffer\n");
|
|
return 1;
|
|
}
|
|
|
|
/* splits processes 0 to n-2 into one comm. and the last one into another */
|
|
color = ((mpi_rank < (mpi_size - 1)) ? 0 : 1);
|
|
mrc = MPI_Comm_split(MPI_COMM_WORLD, color, mpi_rank, &comm);
|
|
VRFY((mrc == MPI_SUCCESS), "Comm_split succeeded");
|
|
|
|
if (color == 0) {
|
|
/* First n-1 processes (color==0) open a file and write it */
|
|
mrc = MPI_File_open(comm, filename, MPI_MODE_CREATE | MPI_MODE_RDWR, info, &fh);
|
|
VRFY((mrc == MPI_SUCCESS), "");
|
|
|
|
stride = 1;
|
|
mpi_off = mpi_rank * stride;
|
|
while (mpi_off < MPIO_TEST_WRITE_SIZE) {
|
|
/* make sure the write does not exceed the TEST_WRITE_SIZE */
|
|
if (mpi_off + stride > MPIO_TEST_WRITE_SIZE)
|
|
stride = MPIO_TEST_WRITE_SIZE - mpi_off;
|
|
|
|
/* set data to some trivial pattern for easy verification */
|
|
for (i = 0; i < stride; i++)
|
|
buf[i] = (unsigned char)(mpi_off + i);
|
|
mrc = MPI_File_write_at(fh, mpi_off, buf, (int)stride, MPI_BYTE, &mpi_stat);
|
|
VRFY((mrc == MPI_SUCCESS), "");
|
|
|
|
/* move the offset pointer to last byte written by all processes */
|
|
mpi_off += (mpi_size - 1 - mpi_rank) * stride;
|
|
|
|
/* Increase chunk size without exceeding buffer size. */
|
|
/* Then move the starting offset for next write. */
|
|
stride *= 2;
|
|
if (stride > bufsize)
|
|
stride = bufsize;
|
|
mpi_off += mpi_rank * stride;
|
|
}
|
|
|
|
/* close file and free the communicator */
|
|
mrc = MPI_File_close(&fh);
|
|
VRFY((mrc == MPI_SUCCESS), "MPI_FILE_CLOSE");
|
|
mrc = MPI_Comm_free(&comm);
|
|
VRFY((mrc == MPI_SUCCESS), "MPI_Comm_free");
|
|
|
|
/* sync with the other waiting processes */
|
|
mrc = MPI_Barrier(MPI_COMM_WORLD);
|
|
VRFY((mrc == MPI_SUCCESS), "Sync after writes");
|
|
}
|
|
else {
|
|
/* last process waits till writes are done,
|
|
* then opens file to verify data.
|
|
*/
|
|
mrc = MPI_Barrier(MPI_COMM_WORLD);
|
|
VRFY((mrc == MPI_SUCCESS), "Sync after writes");
|
|
|
|
mrc = MPI_File_open(comm, filename, MPI_MODE_RDONLY, info, &fh);
|
|
VRFY((mrc == MPI_SUCCESS), "");
|
|
|
|
stride = bufsize;
|
|
for (mpi_off = 0; mpi_off < MPIO_TEST_WRITE_SIZE; mpi_off += bufsize) {
|
|
/* make sure it does not read beyond end of data */
|
|
if (mpi_off + stride > MPIO_TEST_WRITE_SIZE)
|
|
stride = MPIO_TEST_WRITE_SIZE - mpi_off;
|
|
mrc = MPI_File_read_at(fh, mpi_off, buf, (int)stride, MPI_BYTE, &mpi_stat);
|
|
VRFY((mrc == MPI_SUCCESS), "");
|
|
vrfyerrs = 0;
|
|
for (i = 0; i < stride; i++) {
|
|
unsigned char expected;
|
|
expected = (unsigned char)(mpi_off + i);
|
|
if ((expected != buf[i]) && (vrfyerrs++ < MAX_ERR_REPORT || VERBOSE_MED)) {
|
|
printf("proc %d: found data error at [%ld], expect %u, got %u\n", mpi_rank,
|
|
(long)(mpi_off + i), expected, buf[i]);
|
|
}
|
|
}
|
|
if (vrfyerrs > MAX_ERR_REPORT && !VERBOSE_MED)
|
|
printf("proc %d: [more errors ...]\n", mpi_rank);
|
|
|
|
nerrs += vrfyerrs;
|
|
}
|
|
|
|
/* close file and free the communicator */
|
|
mrc = MPI_File_close(&fh);
|
|
VRFY((mrc == MPI_SUCCESS), "MPI_FILE_CLOSE");
|
|
mrc = MPI_Comm_free(&comm);
|
|
VRFY((mrc == MPI_SUCCESS), "MPI_Comm_free");
|
|
}
|
|
|
|
/*
|
|
* one more sync to ensure all processes have done reading
|
|
* before ending this test.
|
|
*/
|
|
mrc = MPI_Barrier(MPI_COMM_WORLD);
|
|
VRFY((mrc == MPI_SUCCESS), "Sync before leaving test");
|
|
|
|
free(buf);
|
|
|
|
return (nerrs);
|
|
}
|
|
|
|
#define MB 1048576 /* 1024*1024 == 2**20 */
|
|
#define GB 1073741824 /* 1024**3 == 2**30 */
|
|
#define TWO_GB_LESS1 2147483647 /* 2**31 - 1 */
|
|
#define FOUR_GB_LESS1 4294967295L /* 2**32 - 1 */
|
|
/*
|
|
* Verify that MPI_Offset exceeding 2**31 can be computed correctly.
|
|
* Print any failure as information only, not as an error so that this
|
|
* won't abort the remaining test or other separated tests.
|
|
*
|
|
* Test if MPIO can write file from under 2GB to over 2GB and then
|
|
* from under 4GB to over 4GB.
|
|
* Each process writes 1MB in round robin fashion.
|
|
* Then reads the file back in by reverse order, that is process 0
|
|
* reads the data of process n-1 and vice versa.
|
|
*/
|
|
static int
|
|
test_mpio_gb_file(char *filename)
|
|
{
|
|
int mpi_size, mpi_rank;
|
|
MPI_Info info = MPI_INFO_NULL;
|
|
int mrc;
|
|
MPI_File fh;
|
|
int i, j, n;
|
|
int vrfyerrs;
|
|
int writerrs; /* write errors */
|
|
int nerrs;
|
|
int ntimes; /* how many times */
|
|
char *buf = NULL;
|
|
char expected;
|
|
MPI_Offset size;
|
|
MPI_Offset mpi_off;
|
|
MPI_Offset mpi_off_old;
|
|
MPI_Status mpi_stat;
|
|
int is_signed, sizeof_mpi_offset;
|
|
|
|
nerrs = 0;
|
|
/* set up MPI parameters */
|
|
MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
|
|
|
|
if (VERBOSE_MED)
|
|
printf("MPI_Offset range test\n");
|
|
|
|
/* figure out the signness and sizeof MPI_Offset */
|
|
mpi_off = 0;
|
|
is_signed = ((MPI_Offset)(mpi_off - 1)) < 0;
|
|
sizeof_mpi_offset = (int)(sizeof(MPI_Offset));
|
|
|
|
/*
|
|
* Verify the sizeof MPI_Offset and correctness of handling multiple GB
|
|
* sizes.
|
|
*/
|
|
if (MAINPROCESS) { /* only process 0 needs to check it*/
|
|
printf("MPI_Offset is %s %d bytes integral type\n", is_signed ? "signed" : "unsigned",
|
|
(int)sizeof(MPI_Offset));
|
|
if (sizeof_mpi_offset <= 4 && is_signed) {
|
|
printf("Skipped 2GB range test "
|
|
"because MPI_Offset cannot support it\n");
|
|
}
|
|
else {
|
|
/* verify correctness of assigning 2GB sizes */
|
|
mpi_off = 2 * 1024 * (MPI_Offset)MB;
|
|
INFO((mpi_off > 0), "2GB OFFSET assignment no overflow");
|
|
INFO((mpi_off - 1) == TWO_GB_LESS1, "2GB OFFSET assignment succeed");
|
|
|
|
/* verify correctness of increasing from below 2 GB to above 2GB */
|
|
mpi_off = TWO_GB_LESS1;
|
|
for (i = 0; i < 3; i++) {
|
|
mpi_off_old = mpi_off;
|
|
mpi_off = mpi_off + 1;
|
|
/* no overflow */
|
|
INFO((mpi_off > 0), "2GB OFFSET increment no overflow");
|
|
/* correct inc. */
|
|
INFO((mpi_off - 1) == mpi_off_old, "2GB OFFSET increment succeed");
|
|
}
|
|
}
|
|
|
|
if (sizeof_mpi_offset <= 4) {
|
|
printf("Skipped 4GB range test "
|
|
"because MPI_Offset cannot support it\n");
|
|
}
|
|
else {
|
|
/* verify correctness of assigning 4GB sizes */
|
|
mpi_off = 4 * 1024 * (MPI_Offset)MB;
|
|
INFO((mpi_off > 0), "4GB OFFSET assignment no overflow");
|
|
INFO((mpi_off - 1) == FOUR_GB_LESS1, "4GB OFFSET assignment succeed");
|
|
|
|
/* verify correctness of increasing from below 4 GB to above 4 GB */
|
|
mpi_off = FOUR_GB_LESS1;
|
|
for (i = 0; i < 3; i++) {
|
|
mpi_off_old = mpi_off;
|
|
mpi_off = mpi_off + 1;
|
|
/* no overflow */
|
|
INFO((mpi_off > 0), "4GB OFFSET increment no overflow");
|
|
/* correct inc. */
|
|
INFO((mpi_off - 1) == mpi_off_old, "4GB OFFSET increment succeed");
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Verify if we can write to a file of multiple GB sizes.
|
|
*/
|
|
if (VERBOSE_MED)
|
|
printf("MPIO GB file test %s\n", filename);
|
|
|
|
if (sizeof_mpi_offset <= 4) {
|
|
printf("Skipped GB file range test "
|
|
"because MPI_Offset cannot support it\n");
|
|
}
|
|
else {
|
|
buf = (char *)malloc(MB);
|
|
VRFY((buf != NULL), "malloc succeed");
|
|
|
|
/* open a new file. Remove it first in case it exists. */
|
|
/* Must delete because MPI_File_open does not have a Truncate mode. */
|
|
/* Don't care if it has error. */
|
|
MPI_File_delete(filename, MPI_INFO_NULL);
|
|
MPI_Barrier(MPI_COMM_WORLD); /* prevent racing condition */
|
|
|
|
mrc = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_CREATE | MPI_MODE_RDWR, info, &fh);
|
|
VRFY((mrc == MPI_SUCCESS), "MPI_FILE_OPEN");
|
|
|
|
printf("MPIO GB file write test %s\n", filename);
|
|
|
|
/* instead of writing every bytes of the file, we will just write
|
|
* some data around the 2 and 4 GB boundaries. That should cover
|
|
* potential integer overflow and filesystem size limits.
|
|
*/
|
|
writerrs = 0;
|
|
for (n = 2; n <= 4; n += 2) {
|
|
ntimes = GB / MB * n / mpi_size + 1;
|
|
for (i = ntimes - 2; i <= ntimes; i++) {
|
|
mpi_off = (i * mpi_size + mpi_rank) * (MPI_Offset)MB;
|
|
if (VERBOSE_MED)
|
|
fprintf(stdout, "proc %d: write to mpi_off=%016llx, %lld\n", mpi_rank, mpi_off, mpi_off);
|
|
/* set data to some trivial pattern for easy verification */
|
|
for (j = 0; j < MB; j++)
|
|
*(buf + j) = (int8_t)(i * mpi_size + mpi_rank);
|
|
if (VERBOSE_MED)
|
|
fprintf(stdout, "proc %d: writing %d bytes at offset %lld\n", mpi_rank, MB, mpi_off);
|
|
mrc = MPI_File_write_at(fh, mpi_off, buf, MB, MPI_BYTE, &mpi_stat);
|
|
INFO((mrc == MPI_SUCCESS), "GB size file write");
|
|
if (mrc != MPI_SUCCESS)
|
|
writerrs++;
|
|
}
|
|
}
|
|
|
|
/* close file and free the communicator */
|
|
mrc = MPI_File_close(&fh);
|
|
VRFY((mrc == MPI_SUCCESS), "MPI_FILE_CLOSE");
|
|
|
|
mrc = MPI_Barrier(MPI_COMM_WORLD);
|
|
VRFY((mrc == MPI_SUCCESS), "Sync after writes");
|
|
|
|
/*
|
|
* Verify if we can read the multiple GB file just created.
|
|
*/
|
|
/* open it again to verify the data written */
|
|
/* but only if there was no write errors */
|
|
printf("MPIO GB file read test %s\n", filename);
|
|
if (errors_sum(writerrs) > 0) {
|
|
printf("proc %d: Skip read test due to previous write errors\n", mpi_rank);
|
|
goto finish;
|
|
}
|
|
mrc = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_RDONLY, info, &fh);
|
|
VRFY((mrc == MPI_SUCCESS), "");
|
|
|
|
/* Only read back parts of the file that have been written. */
|
|
for (n = 2; n <= 4; n += 2) {
|
|
ntimes = GB / MB * n / mpi_size + 1;
|
|
for (i = ntimes - 2; i <= ntimes; i++) {
|
|
mpi_off = (i * mpi_size + (mpi_size - mpi_rank - 1)) * (MPI_Offset)MB;
|
|
if (VERBOSE_MED)
|
|
fprintf(stdout, "proc %d: read from mpi_off=%016llx, %lld\n", mpi_rank, mpi_off, mpi_off);
|
|
mrc = MPI_File_read_at(fh, mpi_off, buf, MB, MPI_BYTE, &mpi_stat);
|
|
INFO((mrc == MPI_SUCCESS), "GB size file read");
|
|
expected = (int8_t)(i * mpi_size + (mpi_size - mpi_rank - 1));
|
|
vrfyerrs = 0;
|
|
for (j = 0; j < MB; j++) {
|
|
if ((*(buf + j) != expected) && (vrfyerrs++ < MAX_ERR_REPORT || VERBOSE_MED)) {
|
|
printf("proc %d: found data error at [%ld+%d], expect %d, got %d\n", mpi_rank,
|
|
(long)mpi_off, j, expected, *(buf + j));
|
|
}
|
|
}
|
|
if (vrfyerrs > MAX_ERR_REPORT && !VERBOSE_MED)
|
|
printf("proc %d: [more errors ...]\n", mpi_rank);
|
|
|
|
nerrs += vrfyerrs;
|
|
}
|
|
}
|
|
|
|
/* close file and free the communicator */
|
|
mrc = MPI_File_close(&fh);
|
|
VRFY((mrc == MPI_SUCCESS), "MPI_FILE_CLOSE");
|
|
|
|
/*
|
|
* one more sync to ensure all processes have done reading
|
|
* before ending this test.
|
|
*/
|
|
mrc = MPI_Barrier(MPI_COMM_WORLD);
|
|
VRFY((mrc == MPI_SUCCESS), "Sync before leaving test");
|
|
|
|
printf("Test if MPI_File_get_size works correctly with %s\n", filename);
|
|
|
|
mrc = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_RDONLY, info, &fh);
|
|
VRFY((mrc == MPI_SUCCESS), "");
|
|
|
|
if (MAINPROCESS) { /* only process 0 needs to check it*/
|
|
mrc = MPI_File_get_size(fh, &size);
|
|
VRFY((mrc == MPI_SUCCESS), "");
|
|
VRFY((size == mpi_off + MB), "MPI_File_get_size doesn't return correct file size.");
|
|
}
|
|
|
|
/* close file and free the communicator */
|
|
mrc = MPI_File_close(&fh);
|
|
VRFY((mrc == MPI_SUCCESS), "MPI_FILE_CLOSE");
|
|
|
|
/*
|
|
* one more sync to ensure all processes have done reading
|
|
* before ending this test.
|
|
*/
|
|
mrc = MPI_Barrier(MPI_COMM_WORLD);
|
|
VRFY((mrc == MPI_SUCCESS), "Sync before leaving test");
|
|
}
|
|
|
|
finish:
|
|
if (buf)
|
|
free(buf);
|
|
return (nerrs);
|
|
}
|
|
|
|
/*
|
|
* MPI-IO Test: One writes, Many reads.
|
|
* Verify if only one process writes some data and then all other
|
|
* processes can read them back correctly. This tests if the
|
|
* underlying parallel I/O and file system supports parallel I/O
|
|
* correctly.
|
|
*
|
|
* Algorithm: Only one process (e.g., process 0) writes some data.
|
|
* Then all processes, including the writing process, read the data
|
|
* back and verify them against the original values.
|
|
*/
|
|
|
|
/*
|
|
* Default filename can be specified via first program argument.
|
|
* Each process writes something, then reads all data back.
|
|
*/
|
|
|
|
#define DIMSIZE 32 /* Dimension size. */
|
|
#define PRINTID printf("Proc %d: ", mpi_rank)
|
|
#define USENONE 0
|
|
#define USEATOM 1 /* request atomic I/O */
|
|
#define USEFSYNC 2 /* request file_sync */
|
|
|
|
static int
|
|
test_mpio_1wMr(char *filename, int special_request)
|
|
{
|
|
char hostname[128];
|
|
int mpi_size, mpi_rank;
|
|
MPI_File fh;
|
|
char mpi_err_str[MPI_MAX_ERROR_STRING];
|
|
int mpi_err_strlen;
|
|
int mpi_err;
|
|
unsigned char writedata[DIMSIZE], readdata[DIMSIZE];
|
|
unsigned char expect_val;
|
|
int i, irank;
|
|
int nerrs = 0; /* number of errors */
|
|
int atomicity;
|
|
MPI_Offset mpi_off;
|
|
MPI_Status mpi_stat;
|
|
|
|
MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
|
|
|
|
if (MAINPROCESS && VERBOSE_MED) {
|
|
printf("Testing one process writes, all processes read.\n");
|
|
printf("Using %d processes accessing file %s\n", mpi_size, filename);
|
|
printf(" (Filename can be specified via program argument)\n");
|
|
}
|
|
|
|
/* show the hostname so that we can tell where the processes are running */
|
|
if (VERBOSE_DEF) {
|
|
#ifdef H5_HAVE_GETHOSTNAME
|
|
if (gethostname(hostname, sizeof(hostname)) < 0) {
|
|
printf("gethostname failed\n");
|
|
hostname[0] = '\0';
|
|
}
|
|
#else
|
|
printf("gethostname unavailable\n");
|
|
hostname[0] = '\0';
|
|
#endif
|
|
PRINTID;
|
|
printf("hostname=%s\n", hostname);
|
|
}
|
|
|
|
/* Delete any old file in order to start anew. */
|
|
/* Must delete because MPI_File_open does not have a Truncate mode. */
|
|
/* Don't care if it has error. */
|
|
MPI_File_delete(filename, MPI_INFO_NULL);
|
|
MPI_Barrier(MPI_COMM_WORLD); /* prevent racing condition */
|
|
|
|
if ((mpi_err = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_RDWR | MPI_MODE_CREATE, MPI_INFO_NULL,
|
|
&fh)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
PRINTID;
|
|
printf("MPI_File_open failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
if (special_request & USEATOM) {
|
|
/* ==================================================
|
|
* Set atomcity to true (1). A POSIX compliant filesystem
|
|
* should not need this.
|
|
* ==================================================*/
|
|
if ((mpi_err = MPI_File_get_atomicity(fh, &atomicity)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
PRINTID;
|
|
printf("MPI_File_get_atomicity failed (%s)\n", mpi_err_str);
|
|
}
|
|
if (VERBOSE_HI)
|
|
printf("Initial atomicity = %d\n", atomicity);
|
|
if ((mpi_err = MPI_File_set_atomicity(fh, 1)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
PRINTID;
|
|
printf("MPI_File_set_atomicity failed (%s)\n", mpi_err_str);
|
|
}
|
|
if ((mpi_err = MPI_File_get_atomicity(fh, &atomicity)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
PRINTID;
|
|
printf("MPI_File_get_atomicity failed (%s)\n", mpi_err_str);
|
|
}
|
|
if (VERBOSE_HI)
|
|
printf("After set_atomicity atomicity = %d\n", atomicity);
|
|
}
|
|
|
|
/* This barrier is not necessary but do it anyway. */
|
|
MPI_Barrier(MPI_COMM_WORLD);
|
|
if (VERBOSE_HI) {
|
|
PRINTID;
|
|
printf("between MPI_Barrier and MPI_File_write_at\n");
|
|
}
|
|
|
|
/* ==================================================
|
|
* Each process calculates what to write but
|
|
* only process irank(0) writes.
|
|
* ==================================================*/
|
|
irank = 0;
|
|
for (i = 0; i < DIMSIZE; i++)
|
|
writedata[i] = (uint8_t)(irank * DIMSIZE + i);
|
|
mpi_off = irank * DIMSIZE;
|
|
|
|
/* Only one process writes */
|
|
if (mpi_rank == irank) {
|
|
if (VERBOSE_HI) {
|
|
PRINTID;
|
|
printf("wrote %d bytes at %ld\n", DIMSIZE, (long)mpi_off);
|
|
}
|
|
if ((mpi_err = MPI_File_write_at(fh, mpi_off, writedata, DIMSIZE, MPI_BYTE, &mpi_stat)) !=
|
|
MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
PRINTID;
|
|
printf("MPI_File_write_at offset(%ld), bytes (%d), failed (%s)\n", (long)mpi_off, DIMSIZE,
|
|
mpi_err_str);
|
|
return 1;
|
|
};
|
|
};
|
|
|
|
/* Bcast the return code and */
|
|
/* make sure all writing are done before reading. */
|
|
MPI_Bcast(&mpi_err, 1, MPI_INT, irank, MPI_COMM_WORLD);
|
|
if (VERBOSE_HI) {
|
|
PRINTID;
|
|
printf("MPI_Bcast: mpi_err = %d\n", mpi_err);
|
|
}
|
|
|
|
if (special_request & USEFSYNC) {
|
|
/* ==================================================
|
|
* Do a file sync. A POSIX compliant filesystem
|
|
* should not need this.
|
|
* ==================================================*/
|
|
if (VERBOSE_HI)
|
|
printf("Apply MPI_File_sync\n");
|
|
/* call file_sync to force the write out */
|
|
if ((mpi_err = MPI_File_sync(fh)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
PRINTID;
|
|
printf("MPI_File_sync failed (%s)\n", mpi_err_str);
|
|
}
|
|
MPI_Barrier(MPI_COMM_WORLD);
|
|
/* call file_sync to force the write out */
|
|
if ((mpi_err = MPI_File_sync(fh)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
PRINTID;
|
|
printf("MPI_File_sync failed (%s)\n", mpi_err_str);
|
|
}
|
|
}
|
|
|
|
/* This barrier is not necessary because the Bcase or File_sync above */
|
|
/* should take care of it. Do it anyway. */
|
|
MPI_Barrier(MPI_COMM_WORLD);
|
|
if (VERBOSE_HI) {
|
|
PRINTID;
|
|
printf("after MPI_Barrier\n");
|
|
}
|
|
|
|
/* ==================================================
|
|
* Each process reads what process 0 wrote and verify.
|
|
* ==================================================*/
|
|
irank = 0;
|
|
mpi_off = irank * DIMSIZE;
|
|
if ((mpi_err = MPI_File_read_at(fh, mpi_off, readdata, DIMSIZE, MPI_BYTE, &mpi_stat)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
PRINTID;
|
|
printf("MPI_File_read_at offset(%ld), bytes (%d), failed (%s)\n", (long)mpi_off, DIMSIZE,
|
|
mpi_err_str);
|
|
return 1;
|
|
};
|
|
for (i = 0; i < DIMSIZE; i++) {
|
|
expect_val = (uint8_t)(irank * DIMSIZE + i);
|
|
if (readdata[i] != expect_val) {
|
|
PRINTID;
|
|
printf("read data[%d:%d] got %02x, expect %02x\n", irank, i, readdata[i], expect_val);
|
|
nerrs++;
|
|
}
|
|
}
|
|
|
|
MPI_File_close(&fh);
|
|
|
|
if (VERBOSE_HI) {
|
|
PRINTID;
|
|
printf("%d data errors detected\n", nerrs);
|
|
}
|
|
|
|
mpi_err = MPI_Barrier(MPI_COMM_WORLD);
|
|
return nerrs;
|
|
}
|
|
|
|
/*
|
|
|
|
Function: test_mpio_derived_dtype
|
|
|
|
Test Whether the Displacement of MPI derived datatype
|
|
(+ File_set_view + MPI_write)works or not on this MPI-IO package
|
|
and this platform.
|
|
|
|
1. Details for the test:
|
|
1) Create two derived datatypes with MPI_Type_create_hindexed:
|
|
datatype1:
|
|
count = 1, blocklens = 1, offsets = 0,
|
|
base type = MPI_BYTE(essentially a char)
|
|
datatype2:
|
|
count = 1, blocklens = 1, offsets = 1(byte),
|
|
base type = MPI_BYTE
|
|
|
|
2) Using these two derived datatypes,
|
|
Build another derived datatype with MPI_Type_create_struct:
|
|
advtype: derived from datatype1 and datatype2
|
|
advtype:
|
|
count = 2, blocklens[0] = 1, blocklens[1]=1,
|
|
offsets[0] = 0, offsets[1] = 1(byte),
|
|
bas_type[0]=datatype1,
|
|
bas_type[1] = datatype2;
|
|
|
|
3) Setting MPI file view with advtype
|
|
4) Writing 2 bytes 1 to 2 using MPI_File_write to a file
|
|
5) File content:
|
|
Suppose the fill value of the file is 0(most machines indeed do so)
|
|
and Fill value is embraced with "() in the following output:
|
|
Expected output should be:
|
|
1,0,2
|
|
|
|
|
|
|
|
However, at some platforms, for example, IBM AIX(at March 23rd, 2005):
|
|
the following values were obtained:
|
|
1,2,0
|
|
|
|
The problem is that the displacement of the second derived datatype(datatype2) which formed the final derived
|
|
datatype(advtype) has been put after the basic datatype(MPI_BYTE) of datatype2. This is a bug.
|
|
|
|
|
|
2. This test will verify whether the complicated derived datatype is working on
|
|
the current platform.
|
|
|
|
If this bug has been fixed in the previous not-working package, this test will issue a printf message to
|
|
tell the developer to change the configuration specific file of HDF5 so that we can change our
|
|
configurationsetting to support collective IO for irregular selections.
|
|
|
|
If it turns out that the previous working MPI-IO package no longer works, this test will also issue a message
|
|
to inform the corresponding failure so that we can turn off collective IO support for irregular selections.
|
|
*/
|
|
|
|
static int
|
|
test_mpio_derived_dtype(char *filename)
|
|
{
|
|
|
|
MPI_File fh;
|
|
char mpi_err_str[MPI_MAX_ERROR_STRING];
|
|
int mpi_err_strlen;
|
|
int mpi_err;
|
|
int i;
|
|
MPI_Datatype etype, filetype;
|
|
MPI_Datatype adv_filetype, bas_filetype[2];
|
|
MPI_Datatype filetypenew;
|
|
MPI_Offset disp;
|
|
MPI_Status Status;
|
|
MPI_Aint adv_disp[2];
|
|
MPI_Aint offsets[1];
|
|
int blocklens[1], adv_blocklens[2];
|
|
int count, outcount;
|
|
int retcode;
|
|
|
|
int mpi_rank, mpi_size;
|
|
|
|
char buf[3], outbuf[3] = {0};
|
|
|
|
MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
|
|
retcode = 0;
|
|
for (i = 0; i < 3; i++)
|
|
buf[i] = (char)(i + 1);
|
|
|
|
if ((mpi_err = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_RDWR | MPI_MODE_CREATE, MPI_INFO_NULL,
|
|
&fh)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_File_open failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
disp = 0;
|
|
etype = MPI_BYTE;
|
|
|
|
count = 1;
|
|
blocklens[0] = 1;
|
|
offsets[0] = 0;
|
|
|
|
if ((mpi_err = MPI_Type_create_hindexed(count, blocklens, offsets, MPI_BYTE, &filetype)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_Type_contiguous failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
if ((mpi_err = MPI_Type_commit(&filetype)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_Type_commit failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
count = 1;
|
|
blocklens[0] = 1;
|
|
offsets[0] = 1;
|
|
if ((mpi_err = MPI_Type_create_hindexed(count, blocklens, offsets, MPI_BYTE, &filetypenew)) !=
|
|
MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_Type_contiguous failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
if ((mpi_err = MPI_Type_commit(&filetypenew)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_Type_commit failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
outcount = 2;
|
|
adv_blocklens[0] = 1;
|
|
adv_blocklens[1] = 1;
|
|
adv_disp[0] = 0;
|
|
adv_disp[1] = 1;
|
|
bas_filetype[0] = filetype;
|
|
bas_filetype[1] = filetypenew;
|
|
|
|
if ((mpi_err = MPI_Type_create_struct(outcount, adv_blocklens, adv_disp, bas_filetype, &adv_filetype)) !=
|
|
MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_Type_create_struct failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
if ((mpi_err = MPI_Type_commit(&adv_filetype)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_Type_commit failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
if ((mpi_err = MPI_File_set_view(fh, disp, etype, adv_filetype, "native", MPI_INFO_NULL)) !=
|
|
MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_File_set_view failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
if ((mpi_err = MPI_File_write(fh, buf, 3, MPI_BYTE, &Status)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_File_write failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
if ((mpi_err = MPI_File_close(&fh)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_File_close failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
if ((mpi_err = MPI_Type_free(&filetype)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_Type_free failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
if ((mpi_err = MPI_Type_free(&adv_filetype)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_Type_free failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
if ((mpi_err = MPI_Type_free(&filetypenew)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_Type_free failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
if ((mpi_err = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_RDONLY, MPI_INFO_NULL, &fh)) !=
|
|
MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_File_open failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
if ((mpi_err = MPI_File_set_view(fh, 0, MPI_BYTE, MPI_BYTE, "native", MPI_INFO_NULL)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_File_set_view failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
if ((mpi_err = MPI_File_read(fh, outbuf, 3, MPI_BYTE, &Status)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_File_read failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
if (outbuf[2] == 2) {
|
|
retcode = 0;
|
|
}
|
|
else {
|
|
/* if(mpi_rank == 0) {
|
|
printf("complicated derived datatype is NOT working at this platform\n");
|
|
printf("go back to hdf5/config and find the corresponding\n");
|
|
printf("configure-specific file and change ?????\n");
|
|
}
|
|
*/
|
|
retcode = -1;
|
|
}
|
|
|
|
if ((mpi_err = MPI_File_close(&fh)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_File_close failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
mpi_err = MPI_Barrier(MPI_COMM_WORLD);
|
|
if (retcode == -1) {
|
|
if (mpi_rank == 0) {
|
|
printf("Complicated derived datatype is NOT working at this platform\n");
|
|
printf(" Please report to help@hdfgroup.org about this problem.\n");
|
|
}
|
|
retcode = 1;
|
|
}
|
|
return retcode;
|
|
}
|
|
/*
|
|
|
|
Function: test_mpio_special_collective
|
|
|
|
Test Whether collective IO is still working when more than one process
|
|
has no contribution to IO. To properly test this case, at least FOUR
|
|
processes are needed.
|
|
|
|
1. Details for the test:
|
|
1) Create one derived datatype with MPI_Type_create_hindexed:
|
|
|
|
2) Choosing at least two processes to contribute none for IO with
|
|
the buf size inside MPI_Write_at_all to 0.
|
|
3) Choosing at least two processes to have real contributions for IO.
|
|
4) Do collective IO.
|
|
|
|
2. This test will fail with the MPI-IO package that doesn't support this. For example,
|
|
mpich 1.2.6.
|
|
|
|
If this bug has been fixed in the previous not-working package, this test will issue a printf message to
|
|
tell the developer to change the configuration specific file of HDF5 so that we can change our
|
|
configurationsetting to support special collective IO; currently only special collective IO.
|
|
|
|
If it turns out that the previous working MPI-IO package no longer works, this test will also issue a message
|
|
to inform the corresponding failure so that we can turn off the support for special collective IO; currently
|
|
only special collective IO.
|
|
*/
|
|
|
|
static int
|
|
test_mpio_special_collective(char *filename)
|
|
{
|
|
int mpi_size, mpi_rank;
|
|
MPI_File fh;
|
|
MPI_Datatype etype;
|
|
MPI_Datatype filetype = MPI_BYTE;
|
|
MPI_Datatype buftype = MPI_BYTE;
|
|
char mpi_err_str[MPI_MAX_ERROR_STRING];
|
|
int mpi_err_strlen;
|
|
int mpi_err;
|
|
char writedata[2 * DIMSIZE];
|
|
char filerep[7] = "native";
|
|
int i;
|
|
int count, bufcount;
|
|
int blocklens[2];
|
|
MPI_Aint offsets[2];
|
|
MPI_Offset mpi_off = 0;
|
|
MPI_Status mpi_stat;
|
|
int retcode = 0;
|
|
|
|
MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
|
|
|
|
/* create MPI data type */
|
|
etype = MPI_BYTE;
|
|
if (mpi_rank == 0 || mpi_rank == 1) {
|
|
count = DIMSIZE;
|
|
bufcount = 1;
|
|
} /* end if */
|
|
else {
|
|
count = 0;
|
|
bufcount = 0;
|
|
} /* end else */
|
|
|
|
blocklens[0] = count;
|
|
offsets[0] = mpi_rank * count;
|
|
blocklens[1] = count;
|
|
offsets[1] = (mpi_size + mpi_rank) * count;
|
|
|
|
if (count != 0) {
|
|
if ((mpi_err = MPI_Type_create_hindexed(2, blocklens, offsets, etype, &filetype)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_Type_contiguous failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
} /* end if */
|
|
|
|
if ((mpi_err = MPI_Type_commit(&filetype)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_Type_commit failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
} /* end if */
|
|
|
|
if ((mpi_err = MPI_Type_create_hindexed(2, blocklens, offsets, etype, &buftype)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_Type_contiguous failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
} /* end if */
|
|
|
|
if ((mpi_err = MPI_Type_commit(&buftype)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_Type_commit failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
} /* end if */
|
|
} /* end if */
|
|
|
|
/* Open a file */
|
|
if ((mpi_err = MPI_File_open(MPI_COMM_WORLD, filename, MPI_MODE_RDWR | MPI_MODE_CREATE, MPI_INFO_NULL,
|
|
&fh)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_File_open failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
} /* end if */
|
|
|
|
/* each process writes some data */
|
|
for (i = 0; i < 2 * DIMSIZE; i++)
|
|
writedata[i] = (char)(mpi_rank * DIMSIZE + i);
|
|
|
|
/* Set the file view */
|
|
if ((mpi_err = MPI_File_set_view(fh, mpi_off, MPI_BYTE, filetype, filerep, MPI_INFO_NULL)) !=
|
|
MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_File_set_view failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
} /* end if */
|
|
|
|
if (filetype != MPI_BYTE && (mpi_err = MPI_Type_free(&filetype)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_Type_free failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
/* Collectively write into the file */
|
|
if ((mpi_err = MPI_File_write_at_all(fh, mpi_off, writedata, bufcount, buftype, &mpi_stat)) !=
|
|
MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_File_write_at offset(%ld), bytes (%d), failed (%s)\n", (long)mpi_off, bufcount,
|
|
mpi_err_str);
|
|
return 1;
|
|
} /* end if */
|
|
|
|
if (buftype != MPI_BYTE && (mpi_err = MPI_Type_free(&buftype)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_Type_free failed (%s)\n", mpi_err_str);
|
|
return 1;
|
|
}
|
|
|
|
/* Close the file */
|
|
if ((mpi_err = MPI_File_close(&fh)) != MPI_SUCCESS) {
|
|
MPI_Error_string(mpi_err, mpi_err_str, &mpi_err_strlen);
|
|
printf("MPI_File_close failed. \n");
|
|
return 1;
|
|
} /* end if */
|
|
|
|
/* Perform a barrier */
|
|
mpi_err = MPI_Barrier(MPI_COMM_WORLD);
|
|
if (retcode != 0) {
|
|
if (mpi_rank == 0) {
|
|
printf("special collective IO is NOT working at this platform\n");
|
|
printf(" Please report to help@hdfgroup.org about this problem.\n");
|
|
} /* end if */
|
|
retcode = 1;
|
|
} /* end if */
|
|
|
|
return retcode;
|
|
|
|
} /* test_mpio_special_collective */
|
|
|
|
/*
|
|
* parse the command line options
|
|
*/
|
|
static int
|
|
parse_options(int argc, char **argv)
|
|
{
|
|
while (--argc) {
|
|
if (**(++argv) != '-') {
|
|
break;
|
|
}
|
|
else {
|
|
switch (*(*argv + 1)) {
|
|
case 'v':
|
|
if (*((*argv + 1) + 1))
|
|
ParseTestVerbosity((*argv + 1) + 1);
|
|
else
|
|
SetTestVerbosity(VERBO_MED);
|
|
break;
|
|
case 'f':
|
|
if (--argc < 1) {
|
|
nerrors++;
|
|
return (1);
|
|
}
|
|
if (**(++argv) == '-') {
|
|
nerrors++;
|
|
return (1);
|
|
}
|
|
paraprefix = *argv;
|
|
break;
|
|
case 'h': /* print help message--return with nerrors set */
|
|
return (1);
|
|
default:
|
|
nerrors++;
|
|
return (1);
|
|
}
|
|
}
|
|
} /*while*/
|
|
|
|
/* compose the test filenames */
|
|
{
|
|
int i, n;
|
|
hid_t plist;
|
|
|
|
plist = H5Pcreate(H5P_FILE_ACCESS);
|
|
H5Pset_fapl_mpio(plist, MPI_COMM_WORLD, MPI_INFO_NULL);
|
|
n = sizeof(FILENAME) / sizeof(FILENAME[0]) - 1; /* exclude the NULL */
|
|
|
|
for (i = 0; i < n; i++)
|
|
if (h5_fixname(FILENAME[i], plist, filenames[i], sizeof(filenames[i])) == NULL) {
|
|
printf("h5_fixname failed\n");
|
|
nerrors++;
|
|
return (1);
|
|
}
|
|
H5Pclose(plist);
|
|
if (VERBOSE_MED) {
|
|
printf("Test filenames are:\n");
|
|
for (i = 0; i < n; i++)
|
|
printf(" %s\n", filenames[i]);
|
|
}
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* Show command usage
|
|
*/
|
|
static void
|
|
usage(void)
|
|
{
|
|
printf("Usage: t_mpi [-v<verbosity>] [-f <prefix>]\n");
|
|
printf("\t-v<verbosity>\tset verbose level (0-9,l,m,h)\n");
|
|
printf("\t-f <prefix>\tfilename prefix\n");
|
|
printf("\n");
|
|
}
|
|
|
|
/*
|
|
* return the sum of all errors.
|
|
*/
|
|
static int
|
|
errors_sum(int nerrs)
|
|
{
|
|
int temp;
|
|
MPI_Allreduce(&nerrs, &temp, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
|
|
return (temp);
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
int mpi_size, mpi_rank; /* mpi variables */
|
|
int ret_code;
|
|
|
|
MPI_Init(&argc, &argv);
|
|
MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
|
|
|
|
/* Attempt to turn off atexit post processing so that in case errors
|
|
* happen during the test and the process is aborted, it will not get
|
|
* hang in the atexit post processing in which it may try to make MPI
|
|
* calls. By then, MPI calls may not work.
|
|
*/
|
|
if (H5dont_atexit() < 0) {
|
|
printf("Failed to turn off atexit processing. Continue.\n");
|
|
};
|
|
H5open();
|
|
if (parse_options(argc, argv) != 0) {
|
|
if (MAINPROCESS)
|
|
usage();
|
|
goto finish;
|
|
}
|
|
|
|
if (MAINPROCESS) {
|
|
printf("===================================\n");
|
|
printf("MPI functionality tests\n");
|
|
printf("===================================\n");
|
|
}
|
|
|
|
if (VERBOSE_MED)
|
|
h5_show_hostname();
|
|
|
|
fapl = H5Pcreate(H5P_FILE_ACCESS);
|
|
H5Pset_fapl_mpio(fapl, MPI_COMM_WORLD, MPI_INFO_NULL);
|
|
|
|
/* set alarm. */
|
|
TestAlarmOn();
|
|
|
|
/*=======================================
|
|
* MPIO 1 write Many read test
|
|
*=======================================*/
|
|
MPI_BANNER("MPIO 1 write Many read test...");
|
|
ret_code = test_mpio_1wMr(filenames[0], USENONE);
|
|
ret_code = errors_sum(ret_code);
|
|
if (mpi_rank == 0 && ret_code > 0) {
|
|
printf("***FAILED with %d total errors\n", ret_code);
|
|
nerrors += ret_code;
|
|
}
|
|
|
|
/* test atomicity and file sync in high verbose mode only */
|
|
/* since they often hang when broken and PHDF5 does not use them. */
|
|
if (VERBOSE_HI) {
|
|
MPI_BANNER("MPIO 1 write Many read test with atomicity...");
|
|
ret_code = test_mpio_1wMr(filenames[0], USEATOM);
|
|
ret_code = errors_sum(ret_code);
|
|
if (mpi_rank == 0 && ret_code > 0) {
|
|
printf("***FAILED with %d total errors\n", ret_code);
|
|
nerrors += ret_code;
|
|
}
|
|
|
|
MPI_BANNER("MPIO 1 write Many read test with file sync...");
|
|
ret_code = test_mpio_1wMr(filenames[0], USEFSYNC);
|
|
ret_code = errors_sum(ret_code);
|
|
if (mpi_rank == 0 && ret_code > 0) {
|
|
printf("***FAILED with %d total errors\n", ret_code);
|
|
nerrors += ret_code;
|
|
}
|
|
}
|
|
|
|
/*=======================================
|
|
* MPIO MPIO File size range test
|
|
*=======================================*/
|
|
MPI_BANNER("MPIO File size range test...");
|
|
#ifndef H5_HAVE_WIN32_API
|
|
ret_code = test_mpio_gb_file(filenames[0]);
|
|
ret_code = errors_sum(ret_code);
|
|
if (mpi_rank == 0 && ret_code > 0) {
|
|
printf("***FAILED with %d total errors\n", ret_code);
|
|
nerrors += ret_code;
|
|
}
|
|
#else
|
|
if (mpi_rank == 0)
|
|
printf(" will be skipped on Windows (JIRA HDDFV-8064)\n");
|
|
#endif
|
|
|
|
/*=======================================
|
|
* MPIO independent overlapping writes
|
|
*=======================================*/
|
|
MPI_BANNER("MPIO independent overlapping writes...");
|
|
ret_code = test_mpio_overlap_writes(filenames[0]);
|
|
ret_code = errors_sum(ret_code);
|
|
if (mpi_rank == 0 && ret_code > 0) {
|
|
printf("***FAILED with %d total errors\n", ret_code);
|
|
nerrors += ret_code;
|
|
}
|
|
|
|
/*=======================================
|
|
* MPIO complicated derived datatype test
|
|
*=======================================*/
|
|
MPI_BANNER("MPIO complicated derived datatype test...");
|
|
ret_code = test_mpio_derived_dtype(filenames[0]);
|
|
ret_code = errors_sum(ret_code);
|
|
if (mpi_rank == 0 && ret_code > 0) {
|
|
printf("***FAILED with %d total errors\n", ret_code);
|
|
nerrors += ret_code;
|
|
}
|
|
|
|
/*=======================================
|
|
* MPIO special collective IO test
|
|
*=======================================*/
|
|
if (mpi_size < 4) {
|
|
MPI_BANNER("MPIO special collective io test SKIPPED.");
|
|
if (mpi_rank == 0)
|
|
printf("This test needs at least four processes to run.\n");
|
|
ret_code = 0;
|
|
goto sc_finish;
|
|
} /* end if */
|
|
|
|
MPI_BANNER("MPIO special collective io test...");
|
|
ret_code = test_mpio_special_collective(filenames[0]);
|
|
|
|
sc_finish:
|
|
ret_code = errors_sum(ret_code);
|
|
if (mpi_rank == 0 && ret_code > 0) {
|
|
printf("***FAILED with %d total errors\n", ret_code);
|
|
nerrors += ret_code;
|
|
}
|
|
|
|
finish:
|
|
/* make sure all processes are finished before final report, cleanup
|
|
* and exit.
|
|
*/
|
|
MPI_Barrier(MPI_COMM_WORLD);
|
|
if (MAINPROCESS) { /* only process 0 reports */
|
|
printf("===================================\n");
|
|
if (nerrors) {
|
|
printf("***MPI tests detected %d errors***\n", nerrors);
|
|
}
|
|
else {
|
|
printf("MPI tests finished with no errors\n");
|
|
}
|
|
printf("===================================\n");
|
|
}
|
|
|
|
/* turn off alarm */
|
|
TestAlarmOff();
|
|
|
|
h5_clean_files(FILENAME, fapl);
|
|
H5close();
|
|
|
|
/* MPI_Finalize must be called AFTER H5close which may use MPI calls */
|
|
MPI_Finalize();
|
|
|
|
/* cannot just return (nerrors) because exit code is limited to 1byte */
|
|
return (nerrors != 0);
|
|
}
|