aboutsummaryrefslogtreecommitdiff
path: root/CarpetDev/CarpetIOF5/src/iof5.cc
diff options
context:
space:
mode:
Diffstat (limited to 'CarpetDev/CarpetIOF5/src/iof5.cc')
-rw-r--r--CarpetDev/CarpetIOF5/src/iof5.cc119
1 files changed, 82 insertions, 37 deletions
diff --git a/CarpetDev/CarpetIOF5/src/iof5.cc b/CarpetDev/CarpetIOF5/src/iof5.cc
index c9ebb028f..469a7c105 100644
--- a/CarpetDev/CarpetIOF5/src/iof5.cc
+++ b/CarpetDev/CarpetIOF5/src/iof5.cc
@@ -249,6 +249,29 @@ namespace CarpetIOF5 {
// We don't know how to open multiple files yet
assert(CCTK_EQUALS(file_content, "everything"));
+ // Determine number of I/O processes
+ int const myproc = CCTK_MyProc(cctkGH);
+ int const nprocs = CCTK_nProcs(cctkGH);
+
+ int const ioproc_every =
+ max_nioprocs == 0 ? 1 : (nprocs + max_nioprocs - 1) / max_nioprocs;
+ assert(ioproc_every > 0);
+ int const nioprocs = nprocs / ioproc_every;
+ assert(nioprocs > 0 and nioprocs <= max_nioprocs);
+ int const myioproc = myproc / ioproc_every * ioproc_every;
+ // We split processes into "I/O groups" which range from
+ // myioproc to myioproc+ioproc_every-1 (inclusive). Within each
+ // group, at most one process can perform I/O.
+
+ // If I am not the first process in my I/O group, wait for a
+ // token from my predecessor
+ if (myproc > myioproc) {
+ MPI_Recv(NULL, 0, MPI_INT, myproc-1, 0, dist::comm(),
+ MPI_STATUS_IGNORE);
+ }
+
+
+
// Open file
static bool first_time = true;
@@ -257,17 +280,17 @@ namespace CarpetIOF5 {
int const vindex = CCTK_VarIndex(varname);
assert(vindex >= 0);
string const basename = generate_basename(cctkGH, vindex);
- int const myproc = CCTK_MyProc(cctkGH);
- int const proc = myproc;
+ int const ioproc = myioproc / ioproc_every;
string const name =
- create_filename(cctkGH, basename, cctkGH->cctk_iteration, proc,
+ create_filename(cctkGH, basename, cctkGH->cctk_iteration, ioproc,
io_dir_output, first_time);
indent_t indent;
- cout << indent << "process=" << proc << "\n";
+ cout << indent << "I/O process=" << ioproc << "\n";
enter_keep_file_open();
- bool const truncate_file = first_time and IO_TruncateOutputFiles(cctkGH);
+ bool const truncate_file =
+ first_time and IO_TruncateOutputFiles(cctkGH) and myproc == myioproc;
if (file < 0) {
// Reuse file hid if file is already open
file =
@@ -285,6 +308,16 @@ namespace CarpetIOF5 {
// Close file
leave_keep_file_open();
+
+
+ // If I am not the last process in my I/O group, send a token to
+ // my successor
+ if (myproc < max(myioproc + ioproc_every, nprocs) - 1) {
+ MPI_Send(NULL, 0, MPI_INT, myproc+1-1, 0, dist::comm());
+ }
+
+
+
} END_GLOBAL_MODE;
return 0; // no error
@@ -478,38 +511,48 @@ namespace CarpetIOF5 {
// expect exactly that many files
int const myproc = CCTK_MyProc(cctkGH);
int const nprocs = CCTK_nProcs(cctkGH);
- // Loop over all (possible) files
- for (int proc=myproc; ; proc+=nprocs) {
- string const name =
- create_filename(cctkGH, basename, cctkGH->cctk_iteration, proc,
- in_recovery ? io_dir_recover : io_dir_input, false);
-
- bool file_exists;
- H5E_BEGIN_TRY {
- file_exists = H5Fis_hdf5(name.c_str()) > 0;
- } H5E_END_TRY;
- if (not file_exists) {
- notfoundproc = proc;
- break;
+
+ int const ioproc_every =
+ max_nioprocs == 0 ? 1 : (nprocs + max_nioprocs - 1) / max_nioprocs;
+ assert(ioproc_every > 0);
+ int const nioprocs = nprocs / ioproc_every;
+ assert(nioprocs > 0 and nioprocs <= max_nioprocs);
+ int const myioproc = myproc / ioproc_every * ioproc_every;
+
+ if (myproc == myioproc) {
+ // Loop over all (possible) files
+ for (int ioproc = myioproc / ioproc_every; ; ioproc += nioprocs) {
+ string const name =
+ create_filename(cctkGH, basename, cctkGH->cctk_iteration, ioproc,
+ in_recovery ? io_dir_recover : io_dir_input, false);
+
+ bool file_exists;
+ H5E_BEGIN_TRY {
+ file_exists = H5Fis_hdf5(name.c_str()) > 0;
+ } H5E_END_TRY;
+ if (not file_exists) {
+ notfoundproc = ioproc;
+ break;
+ }
+ foundproc = ioproc;
+
+ indent_t indent;
+ cout << indent << "I/O process=" << ioproc << "\n";
+
+ hid_t const file = H5Fopen(name.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
+ assert(file >= 0);
+
+ // Iterate over all time slices
+ bool const input_past_timelevels = in_recovery;
+ // TODO: read metadata when recoverying parameters
+ bool const input_metadata = false;
+ input(cctkGH, file, input_var, input_past_timelevels, input_metadata,
+ scatter);
+
+ // Close file
+ herr = H5Fclose(file);
+ assert(not herr);
}
- foundproc = proc;
-
- indent_t indent;
- cout << indent << "process=" << proc << "\n";
-
- hid_t const file = H5Fopen(name.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
- assert(file >= 0);
-
- // Iterate over all time slices
- bool const input_past_timelevels = in_recovery;
- // TODO: read metadata when recoverying parameters
- bool const input_metadata = false;
- input(cctkGH, file, input_var, input_past_timelevels, input_metadata,
- scatter);
-
- // Close file
- herr = H5Fclose(file);
- assert(not herr);
}
{
@@ -526,13 +569,15 @@ namespace CarpetIOF5 {
"Could not read input file \"%s\"", name.c_str());
return 1;
}
- if (notfoundproc <= maxfoundproc) {
+ if (notfoundproc > -1 and notfoundproc <= maxfoundproc) {
CCTK_VWarn(CCTK_WARN_ALERT, __LINE__, __FILE__, CCTK_THORNSTRING,
"Could not read file of process %d (but could read file of process %d)",
notfoundproc, maxfoundproc);
}
}
+ // The scatter object is implicitly destroyed here
+
} END_GLOBAL_MODE;
return 0; // no error