diff --git a/include/openPMD/Series.hpp b/include/openPMD/Series.hpp index be73f09e0f..b4861e7cc1 100644 --- a/include/openPMD/Series.hpp +++ b/include/openPMD/Series.hpp @@ -362,10 +362,20 @@ class Series : public Attributable /** * @throw no_such_attribute_error If optional attribute is not present. + * @param collective Run this read operation collectively. + There might be an enormous IO overhead if running this + operation non-collectively. + To make this explicit to users, there is no default parameter. + Parameter is ignored if compiling without MPI support, (it is + present for the sake of a consistent API). * @return Vector with a String per (writing) MPI rank, indicating user- * defined meta information per rank. Example: host name. */ - chunk_assignment::RankMeta mpiRanksMetaInfo(); +#if openPMD_HAVE_MPI + chunk_assignment::RankMeta mpiRanksMetaInfo(bool collective); +#else + chunk_assignment::RankMeta mpiRanksMetaInfo(bool collective = false); +#endif /** * @brief Set the Mpi Ranks Meta Info attribute, i.e. a Vector with diff --git a/src/Series.cpp b/src/Series.cpp index 19f132dfa2..2d7054a3c8 100644 --- a/src/Series.cpp +++ b/src/Series.cpp @@ -186,7 +186,12 @@ Series &Series::setMeshesPath(std::string const &mp) return *this; } -chunk_assignment::RankMeta Series::mpiRanksMetaInfo() +#if openPMD_HAVE_MPI +chunk_assignment::RankMeta Series::mpiRanksMetaInfo(bool collective) +#else +chunk_assignment::RankMeta +Series::mpiRanksMetaInfo([[maybe_unused]] bool collective) +#endif { auto &series = get(); auto &rankTable = series.m_rankTable; @@ -263,7 +268,7 @@ chunk_assignment::RankMeta Series::mpiRanksMetaInfo() }; #if openPMD_HAVE_MPI - if (series.m_communicator.has_value()) + if (collective && series.m_communicator.has_value()) { auto comm = series.m_communicator.value(); int rank{0}, size{1}; @@ -275,6 +280,12 @@ chunk_assignment::RankMeta Series::mpiRanksMetaInfo() } MPI_Bcast(get.get(), writerRanks * lineWidth, MPI_CHAR, 0, comm); } + else if (collective) + { + throw error::WrongAPIUsage( + "Cannot read rank table collectively: Series was not constructed " + "collectively."); + } else { doReadDataset(); diff --git a/src/binding/python/Series.cpp b/src/binding/python/Series.cpp index b24f76ea6e..9fdda90a00 100644 --- a/src/binding/python/Series.cpp +++ b/src/binding/python/Series.cpp @@ -222,10 +222,14 @@ this method. .def_property("base_path", &Series::basePath, &Series::setBasePath) .def_property( "meshes_path", &Series::meshesPath, &Series::setMeshesPath) - .def_property( - "mpi_ranks_meta_info", + .def( + "get_mpi_ranks_meta_info", &Series::mpiRanksMetaInfo, - &Series::setMpiRanksMetaInfo) + py::arg("collective")) + .def( + "set_mpi_ranks_meta_info", + &Series::setMpiRanksMetaInfo, + py::arg("my_rank_info")) .def_property( "particles_path", &Series::particlesPath, &Series::setParticlesPath) .def_property("author", &Series::author, &Series::setAuthor) diff --git a/test/SerialIOTest.cpp b/test/SerialIOTest.cpp index 76988217bb..f511d878e6 100644 --- a/test/SerialIOTest.cpp +++ b/test/SerialIOTest.cpp @@ -1616,7 +1616,7 @@ inline void write_test(const std::string &backend) Series read("../samples/serial_write." + backend, Access::READ_ONLY); REQUIRE( - read.mpiRanksMetaInfo() == + read.mpiRanksMetaInfo(/* collective = */ false) == chunk_assignment::RankMeta{{0, host_info::hostname()}}); } @@ -2144,7 +2144,9 @@ inline void fileBased_write_test(const std::string &backend) std::string fullPath = std::string("../samples/subdir/") + entry->d_name; Series single_file(fullPath, Access::READ_ONLY); - REQUIRE(single_file.mpiRanksMetaInfo() == compare); + REQUIRE( + single_file.mpiRanksMetaInfo(/* collective = */ false) == + compare); } closedir(directory); close(dirfd);