From 4ee805640001bd22c3e4df5516adbb76de8d33a5 Mon Sep 17 00:00:00 2001 From: Podhorszki Norbert Date: Thu, 12 May 2022 10:38:12 -0400 Subject: [PATCH] Fix: BP5 Get() + Close() will retrieve deferred variables. Similarly, if EndStep() was not called, Close() will do it automatically. --- source/adios2/engine/bp5/BP5Reader.cpp | 8 + .../engine/bp/TestBPWriteReadADIOS2.cpp | 214 ++++++++++++++++++ 2 files changed, 222 insertions(+) diff --git a/source/adios2/engine/bp5/BP5Reader.cpp b/source/adios2/engine/bp5/BP5Reader.cpp index d498997b9a..82c4de4d1e 100644 --- a/source/adios2/engine/bp5/BP5Reader.cpp +++ b/source/adios2/engine/bp5/BP5Reader.cpp @@ -993,6 +993,14 @@ ADIOS2_FOREACH_STDTYPE_1ARG(declare_type) void BP5Reader::DoClose(const int transportIndex) { PERFSTUBS_SCOPED_TIMER("BP5Reader::Close"); + if (m_OpenMode == Mode::ReadRandomAccess) + { + PerformGets(); + } + else if (m_BetweenStepPairs) + { + EndStep(); + } m_DataFileManager.CloseFiles(); m_MDFileManager.CloseFiles(); } diff --git a/testing/adios2/engine/bp/TestBPWriteReadADIOS2.cpp b/testing/adios2/engine/bp/TestBPWriteReadADIOS2.cpp index 280f3805ab..a5be54744e 100644 --- a/testing/adios2/engine/bp/TestBPWriteReadADIOS2.cpp +++ b/testing/adios2/engine/bp/TestBPWriteReadADIOS2.cpp @@ -2081,6 +2081,220 @@ TEST_F(BPWriteReadTestADIOS2, ADIOS2BPWriteReadEmptyProcess) #endif } +TEST_F(BPWriteReadTestADIOS2, GetDeferredInClose) +{ + // Test if Get() will retrieve data in Close() + const std::string fname("GetDeferredInClose.bp"); + + int mpiRank = 0, mpiSize = 1; + + const std::size_t Nx = 10; + +#if ADIOS2_USE_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); + MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); +#endif + + std::vector localData(Nx); + std::iota(localData.begin(), localData.end(), mpiRank * Nx); + +#if ADIOS2_USE_MPI + adios2::ADIOS adios(MPI_COMM_WORLD); +#else + adios2::ADIOS adios; +#endif + { + adios2::IO io = adios.DeclareIO("StartCountWrite"); + if (!engineName.empty()) + { + io.SetEngine(engineName); + } + if (!engineParameters.empty()) + { + io.SetParameters(engineParameters); + } + + io.DefineVariable( + "range", {static_cast(Nx * mpiSize)}, + {static_cast(Nx * mpiRank)}, {Nx}); + + adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write); + + bpWriter.Put("range", localData.data()); + bpWriter.Close(); + } + // Reader + { + adios2::IO io = adios.DeclareIO("StartCountRead"); + if (!engineName.empty()) + { + io.SetEngine(engineName); + } + if (!engineParameters.empty()) + { + io.SetParameters(engineParameters); + } + + adios2::Engine bpReader = + io.Open(fname, adios2::Mode::ReadRandomAccess); + adios2::Variable varRange = + io.InquireVariable("range"); + + std::vector readData(Nx); + varRange.SetSelection({{static_cast(Nx * mpiRank)}, {Nx}}); + bpReader.Get(varRange, readData); + bpReader.Close(); + + for (size_t j = 0; j < Nx; ++j) + { + EXPECT_EQ(localData[j], readData[j]); + } + } +} + +TEST_F(BPWriteReadTestADIOS2, GetDeferredInEndStep) +{ + // Test if Get() will retrieve data in EndStep() + const std::string fname("GetDeferredInEndStep.bp"); + + int mpiRank = 0, mpiSize = 1; + + const std::size_t Nx = 10; + +#if ADIOS2_USE_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); + MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); +#endif + + std::vector localData(Nx); + std::iota(localData.begin(), localData.end(), mpiRank * Nx); + +#if ADIOS2_USE_MPI + adios2::ADIOS adios(MPI_COMM_WORLD); +#else + adios2::ADIOS adios; +#endif + { + adios2::IO io = adios.DeclareIO("StartCountWrite"); + if (!engineName.empty()) + { + io.SetEngine(engineName); + } + if (!engineParameters.empty()) + { + io.SetParameters(engineParameters); + } + + io.DefineVariable( + "range", {static_cast(Nx * mpiSize)}, + {static_cast(Nx * mpiRank)}, {Nx}); + + adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write); + + bpWriter.Put("range", localData.data()); + bpWriter.Close(); + } + // Reader + { + adios2::IO io = adios.DeclareIO("StartCountRead"); + if (!engineName.empty()) + { + io.SetEngine(engineName); + } + if (!engineParameters.empty()) + { + io.SetParameters(engineParameters); + } + + adios2::Engine bpReader = io.Open(fname, adios2::Mode::Read); + bpReader.BeginStep(); + adios2::Variable varRange = + io.InquireVariable("range"); + + std::vector readData(Nx); + varRange.SetSelection({{static_cast(Nx * mpiRank)}, {Nx}}); + bpReader.Get(varRange, readData); + bpReader.EndStep(); + for (size_t j = 0; j < Nx; ++j) + { + EXPECT_EQ(localData[j], readData[j]); + } + bpReader.Close(); + } +} + +TEST_F(BPWriteReadTestADIOS2, GetDeferredWithoutEndStep) +{ + // Test if Get() will retrieve data in Close() when EndStep() is not called + const std::string fname("GetDeferredWithoutEndStep.bp"); + + int mpiRank = 0, mpiSize = 1; + + const std::size_t Nx = 10; + +#if ADIOS2_USE_MPI + MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); + MPI_Comm_size(MPI_COMM_WORLD, &mpiSize); +#endif + + std::vector localData(Nx); + std::iota(localData.begin(), localData.end(), mpiRank * Nx); + +#if ADIOS2_USE_MPI + adios2::ADIOS adios(MPI_COMM_WORLD); +#else + adios2::ADIOS adios; +#endif + { + adios2::IO io = adios.DeclareIO("StartCountWrite"); + if (!engineName.empty()) + { + io.SetEngine(engineName); + } + if (!engineParameters.empty()) + { + io.SetParameters(engineParameters); + } + + io.DefineVariable( + "range", {static_cast(Nx * mpiSize)}, + {static_cast(Nx * mpiRank)}, {Nx}); + + adios2::Engine bpWriter = io.Open(fname, adios2::Mode::Write); + + bpWriter.Put("range", localData.data()); + bpWriter.Close(); + } + // Reader + { + adios2::IO io = adios.DeclareIO("StartCountRead"); + if (!engineName.empty()) + { + io.SetEngine(engineName); + } + if (!engineParameters.empty()) + { + io.SetParameters(engineParameters); + } + + adios2::Engine bpReader = io.Open(fname, adios2::Mode::Read); + bpReader.BeginStep(); + adios2::Variable varRange = + io.InquireVariable("range"); + + std::vector readData(Nx); + varRange.SetSelection({{static_cast(Nx * mpiRank)}, {Nx}}); + bpReader.Get(varRange, readData); + /* Missing call to bpReader.EndStep(); */ + bpReader.Close(); + + for (size_t j = 0; j < Nx; ++j) + { + EXPECT_EQ(localData[j], readData[j]); + } + } +} + //****************************************************************************** // main //******************************************************************************