diff --git a/bindings/C/adios2/adios2_c_enums.h b/bindings/C/adios2/adios2_c_enums.h index 3ea471ee62f4013d8ef8702c6d44083d8737a2c2..836b8b6f2d0e426b9cb052d2354205d720da4496 100644 --- a/bindings/C/adios2/adios2_c_enums.h +++ b/bindings/C/adios2/adios2_c_enums.h @@ -64,7 +64,6 @@ typedef enum { adios2_open_mode_write, adios2_open_mode_read, adios2_open_mode_append, - adios2_open_mode_read_write } adios2_open_mode; #ifdef __cplusplus diff --git a/bindings/C/adios2_c.cpp b/bindings/C/adios2_c.cpp index fb13516feffa1031645f1e229dfe2723581295a3..c898ca3c4e2a3f88defd769e2ef4922c424965b5 100644 --- a/bindings/C/adios2_c.cpp +++ b/bindings/C/adios2_c.cpp @@ -257,11 +257,6 @@ void adios2_set_transport_param(adios2_IO *io, transport_index, key, value); } -struct adios2_Engine -{ - std::shared_ptr<adios2::Engine> EngineCpp; -}; - adios2_Engine *adios2_open(adios2_IO *io, const char *name, const adios2_open_mode open_mode) { @@ -274,27 +269,21 @@ adios2_Engine *adios2_open_new_comm(adios2_IO *io, const char *name, MPI_Comm mpi_comm) { auto &ioCpp = *reinterpret_cast<adios2::IO *>(io); - adios2_Engine *engine = new adios2_Engine; + adios2::Engine *engine = nullptr; switch (open_mode) { case adios2_open_mode_write: - engine->EngineCpp = ioCpp.Open(name, adios2::OpenMode::Write, mpi_comm); + engine = &ioCpp.Open(name, adios2::Mode::Write, mpi_comm); break; case adios2_open_mode_read: - engine->EngineCpp = ioCpp.Open(name, adios2::OpenMode::Read, mpi_comm); + engine = &ioCpp.Open(name, adios2::Mode::Read, mpi_comm); break; case adios2_open_mode_append: - engine->EngineCpp = - ioCpp.Open(name, adios2::OpenMode::Append, mpi_comm); - break; - - case adios2_open_mode_read_write: - engine->EngineCpp = - ioCpp.Open(name, adios2::OpenMode::ReadWrite, mpi_comm); + engine = &ioCpp.Open(name, adios2::Mode::Append, mpi_comm); break; case adios2_open_mode_undefined: @@ -302,7 +291,7 @@ adios2_Engine *adios2_open_new_comm(adios2_IO *io, const char *name, break; } - return engine; + return reinterpret_cast<adios2_Engine *>(engine); } void adios2_write(adios2_Engine *engine, adios2_Variable *variable, @@ -315,21 +304,27 @@ void adios2_write(adios2_Engine *engine, adios2_Variable *variable, void adios2_write_by_name(adios2_Engine *engine, const char *variable_name, const void *values) { - engine->EngineCpp->Write(variable_name, values); + auto &engineCpp = *reinterpret_cast<adios2::Engine *>(engine); + engineCpp.Write(variable_name, values); } -void adios2_advance(adios2_Engine *engine) { engine->EngineCpp->Advance(); } +void adios2_advance(adios2_Engine *engine) +{ + auto &engineCpp = *reinterpret_cast<adios2::Engine *>(engine); + engineCpp.Advance(); +} void adios2_close(adios2_Engine *engine) { - engine->EngineCpp->Close(); - delete engine; + auto &engineCpp = *reinterpret_cast<adios2::Engine *>(engine); + engineCpp.Close(); } void adios2_close_by_index(adios2_Engine *engine, const unsigned int transport_index) { - engine->EngineCpp->Close(transport_index); + auto &engineCpp = *reinterpret_cast<adios2::Engine *>(engine); + engineCpp.Close(transport_index); } void adios2_finalize(adios2_ADIOS *adios) diff --git a/bindings/fortran/adios2_params_mod.f90 b/bindings/fortran/adios2_params_mod.f90 index 59f934e3e0aa499b9f411f9500b266675dbb0df0..fb22985afbdeee486d4421d2bcc9bcd59598f937 100644 --- a/bindings/fortran/adios2_params_mod.f90 +++ b/bindings/fortran/adios2_params_mod.f90 @@ -36,6 +36,5 @@ module adios2_params integer, parameter :: adios2_open_mode_write = 1 integer, parameter :: adios2_open_mode_read = 2 integer, parameter :: adios2_open_mode_append = 3 - integer, parameter :: adios2_open_mode_read_write = 4 end module diff --git a/bindings/python/EnginePy.cpp b/bindings/python/EnginePy.cpp index 3a203a5d6552a43b34573fc2618abe61510d3e47..12da987ccac15960e39d286e72882ec15771936a 100644 --- a/bindings/python/EnginePy.cpp +++ b/bindings/python/EnginePy.cpp @@ -15,7 +15,7 @@ namespace adios2 { -EnginePy::EnginePy(IO &io, const std::string &name, const OpenMode openMode, +EnginePy::EnginePy(IO &io, const std::string &name, const Mode openMode, MPI_Comm mpiComm) : m_IO(io), m_Engine(m_IO.Open(name, openMode, mpiComm)), m_DebugMode(m_IO.m_DebugMode) @@ -56,12 +56,12 @@ void EnginePy::Write(VariablePy &variable, const pyArray &array) void EnginePy::Advance(const float timeoutSeconds) { - m_Engine->Advance(timeoutSeconds); + m_Engine.Advance(timeoutSeconds); } void EnginePy::Close(const int transportIndex) { - m_Engine->Close(transportIndex); + m_Engine.Close(transportIndex); } -} // end namespace adios +} // end namespace adios2 diff --git a/bindings/python/EnginePy.h b/bindings/python/EnginePy.h index 10046b3a65699660e3764c866448d7e5c8ffaf4b..ff5bb679d98307f2e40912399a5307069c76a3b9 100644 --- a/bindings/python/EnginePy.h +++ b/bindings/python/EnginePy.h @@ -28,7 +28,7 @@ class EnginePy { public: - EnginePy(IO &io, const std::string &name, const OpenMode openMode, + EnginePy(IO &io, const std::string &name, const Mode openMode, MPI_Comm mpiComm); ~EnginePy() = default; @@ -41,7 +41,7 @@ public: private: IO &m_IO; - std::shared_ptr<Engine> m_Engine; + Engine &m_Engine; const bool m_DebugMode; template <class T> diff --git a/bindings/python/EnginePy.inl b/bindings/python/EnginePy.inl index eea3e71aa32fad6d3f4b7ce502d562c57b3374d2..9e82af68f4a9e04f9844dc3481ab1dff4134ba6b 100644 --- a/bindings/python/EnginePy.inl +++ b/bindings/python/EnginePy.inl @@ -34,10 +34,10 @@ void EnginePy::DefineVariableInIO(VariablePy &variable) template <class T> void EnginePy::WriteInIO(VariablePy &variable, const pyArray &array) { - m_Engine->Write(*dynamic_cast<Variable<T> *>(variable.m_VariableBase), - reinterpret_cast<const T *>(array.data())); + m_Engine.Write(*dynamic_cast<Variable<T> *>(variable.m_VariableBase), + reinterpret_cast<const T *>(array.data())); } -} // end namespace adios +} // end namespace adios2 -#endif /* BINDINGS_PYTHON_SOURCE_ENGINEPY_TCC_ */ +#endif /* BINDINGS_PYTHON_SOURCE_ENGINEPY_INL_ */ diff --git a/bindings/python/IOPy.cpp b/bindings/python/IOPy.cpp index 1ae9475b1f5a2dea518390d7af54f2a8a497d567..da69d9c55b759275fc9819521554ecc09daf0fee 100644 --- a/bindings/python/IOPy.cpp +++ b/bindings/python/IOPy.cpp @@ -69,7 +69,7 @@ VariablePy &IOPy::GetVariable(const std::string &name) EnginePy IOPy::Open(const std::string &name, const int openMode) { - return EnginePy(m_IO, name, static_cast<adios2::OpenMode>(openMode), + return EnginePy(m_IO, name, static_cast<adios2::Mode>(openMode), m_IO.m_MPIComm); } diff --git a/bindings/python/gluePyBind11.cpp b/bindings/python/gluePyBind11.cpp index 85f5ec219461a07de5c4a89ce690b5f426f100dd..cc42f332b8dbd28461b715e1c0e95926207cdbfb 100644 --- a/bindings/python/gluePyBind11.cpp +++ b/bindings/python/gluePyBind11.cpp @@ -91,10 +91,9 @@ PYBIND11_PLUGIN(adios2) m.attr("DebugON") = true; m.attr("DebugOFF") = false; m.attr("ConstantDims") = true; - m.attr("OpenModeWrite") = static_cast<int>(adios2::OpenMode::Write); - m.attr("OpenModeRead") = static_cast<int>(adios2::OpenMode::Read); - m.attr("OpenModeAppend") = static_cast<int>(adios2::OpenMode::Append); - m.attr("OpenModeReadWrite") = static_cast<int>(adios2::OpenMode::ReadWrite); + m.attr("ModeWrite") = static_cast<int>(adios2::Mode::Write); + m.attr("ModeRead") = static_cast<int>(adios2::Mode::Read); + m.attr("ModeAppend") = static_cast<int>(adios2::Mode::Append); m.def("ADIOS", &ADIOSPyInit, "Function that creates an ADIOS class object"); m.def("ADIOS", &ADIOSPyInitConfig, "Function that creates an ADIOS class object using a config file"); diff --git a/examples/basics/globalArray/globalArray_write.cpp b/examples/basics/globalArray/globalArray_write.cpp index 7a1b98ac36012be999362d19227b37a12aba3583..a53074375b98ec520013d83e9bc01c463f4b7380 100644 --- a/examples/basics/globalArray/globalArray_write.cpp +++ b/examples/basics/globalArray/globalArray_write.cpp @@ -75,11 +75,7 @@ int main(int argc, char *argv[]) // Open file. "w" means we overwrite any existing file on disk, // but Advance() will append steps to the same file. - auto writer = io.Open("globalArray.bp", adios2::OpenMode::Write); - - if (!writer) - throw std::ios_base::failure( - "ERROR: failed to open file with ADIOS\n"); + adios2::Engine &writer = io.Open("globalArray.bp", adios2::Mode::Write); for (int step = 0; step < NSTEPS; step++) { @@ -90,18 +86,19 @@ int main(int argc, char *argv[]) // Make a 2D selection to describe the local dimensions of the // variable we write and its offsets in the global spaces - adios2::SelectionBoundingBox sel({(unsigned int)rank, 0}, {1, Nx}); - varGlobalArray.SetSelection(sel); - writer->Write<double>(varGlobalArray, row.data()); + // adios2::SelectionBoundingBox sel(); + varGlobalArray.SetSelection(adios2::Box<adios2::Dims>( + {static_cast<size_t>(rank), 0}, {1, static_cast<size_t>(Nx)})); + writer.Write<double>(varGlobalArray, row.data()); // Indicate we are done for this step. // Disk I/O will be performed during this call unless // time aggregation postpones all of that to some later step - writer->Advance(); + writer.Advance(); } // Called once: indicate that we are done with this output for the run - writer->Close(); + writer.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/basics/joinedArray/joinedArray_write.cpp b/examples/basics/joinedArray/joinedArray_write.cpp index d22438dda7dfe985b869d9abc8c9911efc186ad0..a2939b6f9739c0ae640db32008362836fa54a86d 100644 --- a/examples/basics/joinedArray/joinedArray_write.cpp +++ b/examples/basics/joinedArray/joinedArray_write.cpp @@ -83,11 +83,7 @@ int main(int argc, char *argv[]) // Open file. "w" means we overwrite any existing file on disk, // but Advance() will append steps to the same file. - auto writer = io.Open("joinedArray.bp", adios2::OpenMode::Write); - - if (writer == nullptr) - throw std::ios_base::failure( - "ERROR: failed to open file with ADIOS\n"); + adios2::Engine &writer = io.Open("joinedArray.bp", adios2::Mode::Write); for (int step = 0; step < NSTEPS; step++) { @@ -100,12 +96,12 @@ int main(int argc, char *argv[]) } } - writer->Write<double>(varTable, mytable.data()); + writer.Write<double>(varTable, mytable.data()); - writer->Advance(); + writer.Advance(); } - writer->Close(); + writer.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/basics/localArray/localArray_write.cpp b/examples/basics/localArray/localArray_write.cpp index 7a0e741eb2d29979d305d79be5b46b22e585dd5e..761c4a35f7f1a304965b452c7745bf3739c9174b 100644 --- a/examples/basics/localArray/localArray_write.cpp +++ b/examples/basics/localArray/localArray_write.cpp @@ -85,11 +85,7 @@ int main(int argc, char *argv[]) // Open file. "w" means we overwrite any existing file on disk, // but Advance() will append steps to the same file. - auto writer = io.Open("localArray.bp", adios2::OpenMode::Write); - - if (writer == nullptr) - throw std::ios_base::failure( - "ERROR: failed to open file with ADIOS\n"); + adios2::Engine &writer = io.Open("localArray.bp", adios2::Mode::Write); for (int step = 0; step < NSTEPS; step++) { @@ -98,7 +94,7 @@ int main(int argc, char *argv[]) v1[i] = rank * 1.0 + step * 0.1; } - writer->Write<double>(varV1, v1.data()); + writer.Write<double>(varV1, v1.data()); // random size per process per step, 5..10 each Nelems = rand() % 6 + 5; @@ -110,13 +106,13 @@ int main(int argc, char *argv[]) // Set the size of the array now because we did not know // the size at the time of definition - varV2.SetSelection({}, {Nelems}); - writer->Write<double>(varV2, v2.data()); + varV2.SetSelection(adios2::Box<adios2::Dims>({}, {Nelems})); + writer.Write<double>(varV2, v2.data()); - writer->Advance(); + writer.Advance(); } - writer->Close(); + writer.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/basics/values/values_write.cpp b/examples/basics/values/values_write.cpp index 6ba9acf3d72d57a823830f4fad161c8818b04af3..22e80453bf00ed9e5a97e99f8248b878f6a0bfe6 100644 --- a/examples/basics/values/values_write.cpp +++ b/examples/basics/values/values_write.cpp @@ -86,11 +86,7 @@ int main(int argc, char *argv[]) // Open file. "w" means we overwrite any existing file on disk, // but Advance() will append steps to the same file. - auto writer = io.Open("values.bp", adios2::OpenMode::Write); - - if (!writer) - throw std::ios_base::failure( - "ERROR: failed to open file with ADIOS\n"); + adios2::Engine &writer = io.Open("values.bp", adios2::Mode::Write); for (int step = 0; step < NSTEPS; step++) { @@ -103,27 +99,27 @@ int main(int argc, char *argv[]) // 1. Writing a global constant value only once if (step == 0) { - writer->Write<int>("Nproc", nproc); + writer.Write<int>("Nproc", nproc); } - writer->Write<int>(varStep, step); + writer.Write<int>(varStep, step); } // 3. and 4. Writing a local value on every process. Will be shown // at reading as a 1D array if (step == 0) { - writer->Write<int>(varProcessID, rank); + writer.Write<int>(varProcessID, rank); } - writer->Write<unsigned int>(varNparts, Nparts); + writer.Write<unsigned int>(varNparts, Nparts); // Indicate we are done for this step. // Disk I/O will be performed during this call unless // time aggregation postpones all of that to some later step - writer->Advance(); + writer.Advance(); } // Called once: indicate that we are done with this output for the run - writer->Close(); + writer.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/experimental/api/FileDeferredRead.cpp b/examples/experimental/api/FileDeferredRead.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e9c8fe8627f8703b16bba66184f60864560a8329 --- /dev/null +++ b/examples/experimental/api/FileDeferredRead.cpp @@ -0,0 +1,98 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * FileReadAPIDeferred.cpp : + * + * Created on: Sep 22, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include <adios2.h> +#include <mpi.h> + +#include <vector> + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + /** Application variable */ + const std::size_t Nx = 10; + std::vector<float> myFloats(Nx); + std::vector<int> myInts(Nx); + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended */ + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO &bpIO = adios.DeclareIO("ReadBP"); + + /** + * Engine derived class, spawned to start IO operations + * Deferred expects a "Get" to execute all the Reads + */ + adios2::Engine &bpReader = bpIO.Open( + "myVector.bp", adios2::Mode::Read | adios2::Mode::Deferred); + + /** Write variable for buffering */ + adios2::Variable<float> *bpFloats = + bpReader.InquireVariable<float>("bpFloats"); + adios2::Variable<int> *bpInts = bpReader.InquireVariable<int>("bpInts"); + + // Set selection + /** Dimensions Bounding Box {start}, {count} */ + adios2::Box<adios2::Dims> boxDims({0}, {5}); + + /** Steps Bounding Box {start}, {count} */ + adios2::Box<adios2::Steps> boxSteps({1}, {2}); + + if (bpFloats != nullptr) + { + bpFloats->SetSelection(boxDims, boxSteps); + bpReader.Read<float>(*bpFloats, myFloats.data()); + // myFloats.data() is not available + } + + if (bpInts != nullptr) + { + bpFloats->SetSelection(boxDims, boxSteps); + bpReader.Read<int>(*bpInts, myInts.data()); + // myInts.data() is not available + } + + /** execute all the deferred Read instructions */ + bpReader.Get(); + + /** Close bp file, engine becomes unreachable after this */ + bpReader.Close(); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM " + "from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + + MPI_Finalize(); + + return 0; +} diff --git a/examples/experimental/api/FileDeferredWrite.cpp b/examples/experimental/api/FileDeferredWrite.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03300b20531b4d4ab219becb08d6735d9cf5e874 --- /dev/null +++ b/examples/experimental/api/FileDeferredWrite.cpp @@ -0,0 +1,104 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * FileDeferredWrite.cpp + * + * Created on: Sep 22, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include <ios> //std::ios_base::failure +#include <iostream> //std::cout +#include <mpi.h> +#include <stdexcept> //std::invalid_argument std::exception +#include <vector> + +#include <adios2.h> + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + /** Application variable */ + std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::vector<int> myInts = {0, -1, -2, -3, -4, -5, -6, -7, -8, -9}; + const std::size_t Nx = myFloats.size(); + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended */ + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO &bpIO = adios.DeclareIO("BPFile_N2N"); + + /// Setting flush policy + // the user can set the memory explicitly for ADIOS (more advance users) + bpIO.SetSingleParameter("MaxBufferSize", "100Mb"); + // or by number of steps (naively trying to allocate "N=3" steps before + // flushing + // bpIO.SetSingleParameter("StepsToBuffer", "3"); + + /** global array : name, { shape (total) }, { start (local) }, { + * count + * (local) }, all are constant dimensions */ + adios2::Variable<float> &bpFloats = bpIO.DefineVariable<float>( + "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); + + adios2::Variable<int> &bpInts = bpIO.DefineVariable<int>( + "bpInts", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); + + /** Engine derived class, spawned to start IO operations */ + /** Deferred Mode: Write buffering will be done at Put(), the user makes + * the commitment that pointers passed at Write won't be reused */ + auto bpWriter = bpIO.Open("myVector.bp", + adios2::Mode::Write | adios2::Mode::Deferred); + + // default = 0, in bp1 format this is translated to 1, but user should + // be able to start at any step + bpWriter.SetStep(1); + + /** Write variable for buffering */ + for (unsigned int t = 0; t < 100; ++t) + { + bpWriter.Write<float>(bpFloats, myFloats.data()); + bpWriter.Write<int>(bpInts, myInts.data()); + bpWriter.Advance(); // advances step + + if (t % 10 == 0) // checkpoint/restart every 10 steps, force flush + { + bpWriter.Flush(); + } + } + + /** Engine becomes unreachable after Close */ + bpWriter.Close(); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM " + "from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + + MPI_Finalize(); + + return 0; +} diff --git a/examples/experimental/api/FileRead.cpp b/examples/experimental/api/FileRead.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03fbe4c0d944ddfdb8f35d37d0ad105dd3172c4b --- /dev/null +++ b/examples/experimental/api/FileRead.cpp @@ -0,0 +1,91 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * FileReadAPI.cpp + * + * Created on: Sep 22, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include <adios2.h> +#include <mpi.h> + +#include <vector> + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + /** Application variable */ + const std::size_t Nx = 10; + std::vector<float> myFloats(Nx); + std::vector<int> myInts(Nx); + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended */ + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO &bpIO = adios.DeclareIO("ReadBP"); + + /** Engine derived class, spawned to start IO operations */ + auto bpReader = bpIO.Open("myVector.bp", adios2::Mode::Read); + + /** Write variable for buffering */ + adios2::Variable<float> *bpFloats = + bpReader.InquireVariable<float>("bpFloats"); + adios2::Variable<int> *bpInts = bpReader.InquireVariable<int>("bpInts"); + + // Set selection + /** Dimensions Bounding Box {start}, {count} */ + adios2::Box<adios2::Dims> boxDims({0}, {5}); + + /** Steps Bounding Box {start}, {count} */ + adios2::Box<adios2::Steps> boxSteps({1}, {2}); + + if (bpFloats != nullptr) + { + bpFloats->SetSelection(boxDims, boxSteps); + bpReader.Read<float>(*bpFloats, myFloats.data()); + // myFloats.data() is available + } + + if (bpInts != nullptr) + { + bpFloats->SetSelection(boxDims, boxSteps); + bpReader.Read<int>(*bpInts, myInts.data()); + // myInts.data() is available + } + + /** Close bp file, engine becomes unreachable after this */ + bpReader.Close(); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM " + "from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + + MPI_Finalize(); + + return 0; +} diff --git a/examples/experimental/api/FileTransientDeferredRead.cpp b/examples/experimental/api/FileTransientDeferredRead.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e8b94ab7743bacaceae0381bd97ee2b32e0abfa --- /dev/null +++ b/examples/experimental/api/FileTransientDeferredRead.cpp @@ -0,0 +1,116 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * FileTransientDeferredRead.cpp + * + * Created on: Sep 25, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include <adios2.h> +#include <mpi.h> + +#include <vector> + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + /** Application variable */ + const std::size_t Nx = 10; + std::vector<float> myFloats(Nx); + std::vector<int> myInts(Nx); + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended */ + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO &bpIO = adios.DeclareIO("ReadBP"); + + /** + * Engine derived class, spawned to start IO operations + * Deferred expects a "Get" to execute all the Reads + */ + adios2::Engine &bpReader = bpIO.Open( + "myVector.bp", adios2::Mode::Read | adios2::Mode::Deferred); + + /** Find variables for reading */ + adios2::Variable<float> *bpFloats = + bpReader.InquireVariable<float>("bpFloats"); + + if (bpFloats == nullptr) + { + throw std::runtime_error("ERROR: variable " + bpFloats->m_Name + + " not found\n"); + } + + adios2::Variable<int> *bpInts = bpReader.InquireVariable<int>("bpInts"); + + if (bpInts == nullptr) + { + throw std::runtime_error("ERROR: variable " + bpInts->m_Name + + " not found\n"); + } + + /** Dimensions Bounding Box {start}, {count} assume constant across time + * iterations */ + adios2::Box<adios2::Dims> boxDims({0}, {5}); + bpFloats->SetSelection(boxDims); + bpInts->SetSelection(boxDims); + + for (unsigned int t = 0; t < 100; ++t) + { + // Set time selection + /** Steps Bounding Box {start}, {count} */ + adios2::Box<adios2::Steps> boxSteps({static_cast<std::size_t>(t)}, + {1}); + + bpFloats->SetStepSelection(boxSteps); + bpInts->SetStepSelection(boxSteps); + + bpReader.Read<float>(*bpFloats, myFloats.data()); + bpReader.Read<int>(*bpInts, myInts.data()); + + /** execute all the deferred Read instructions within step, pointer + * data is only ready at Get */ + if (bpReader.GetAdvanceStatus() == adios2::AdvanceStatus::OK) + { + bpReader.Get(); + } + + // do tasks here with the pointers ... + } + + /** Close bp file, engine becomes unreachable after this */ + bpReader.Close(); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM " + "from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + + MPI_Finalize(); + + return 0; +} diff --git a/examples/experimental/api/FileTransientDeferredWrite.cpp b/examples/experimental/api/FileTransientDeferredWrite.cpp new file mode 100644 index 0000000000000000000000000000000000000000..65a4a01d6d7b0267d980235b0615842515482238 --- /dev/null +++ b/examples/experimental/api/FileTransientDeferredWrite.cpp @@ -0,0 +1,88 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * FileTransientDeferredWrite.cpp : deferred write in a transient (time + * aggregation) loop. Buffering is done at Flush + * + * Created on: Sep 25, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include <adios2.h> +#include <mpi.h> + +#include <vector> + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + /** Application variable */ + std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::vector<int> myInts = {0, -1, -2, -3, -4, -5, -6, -7, -8, -9}; + const std::size_t Nx = myFloats.size(); + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended */ + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO &bpIO = adios.DeclareIO("BPFile_N2N"); + + /** global array : name, { shape (total) }, { start (local) }, { + * count + * (local) }, all are constant dimensions */ + adios2::Variable<float> &bpFloats = bpIO.DefineVariable<float>( + "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); + + adios2::Variable<int> &bpInts = bpIO.DefineVariable<int>( + "bpInts", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); + + /** Engine derived class, spawned to start IO operations */ + /** Deferred Mode: Write buffering will be done at Flush(). + * The user must be the one enforcing the commitment that pointers + * passed at Write won't be reused between Write and Flush */ + auto bpWriter = bpIO.Open("myVector.bp", + adios2::Mode::Write | adios2::Mode::Deferred); + + for (unsigned int t = 0; t < 100; ++t) + { + + /** Write variable for buffering */ + bpWriter.Write<float>(bpFloats, myFloats.data()); + bpWriter.Write<int>(bpInts, myInts.data()); + bpWriter.Flush(); + } + + /** Create bp file, engine becomes unreachable after this*/ + bpWriter.Close(); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM " + "from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + + MPI_Finalize(); + + return 0; +} diff --git a/examples/experimental/api/FileTransientRead.cpp b/examples/experimental/api/FileTransientRead.cpp new file mode 100644 index 0000000000000000000000000000000000000000..adebe2f1f93c4cdf128085530cff913e8b62a1ee --- /dev/null +++ b/examples/experimental/api/FileTransientRead.cpp @@ -0,0 +1,113 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * FileTransientRead.cpp + * + * Created on: Sep 25, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include <adios2.h> +#include <mpi.h> + +#include <vector> + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + /** Application variable */ + const std::size_t Nx = 10; + std::vector<float> myFloats(Nx); + std::vector<int> myInts(Nx); + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended */ + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO &bpIO = adios.DeclareIO("ReadBP"); + + /** + * Engine derived class, spawned to start IO operations + */ + adios2::Engine &bpReader = bpIO.Open("myVector.bp", adios2::Mode::Read); + + /** Find variables for reading */ + adios2::Variable<float> *bpFloats = + bpReader.InquireVariable<float>("bpFloats"); + + if (bpFloats == nullptr) + { + throw std::runtime_error("ERROR: variable " + bpFloats->m_Name + + " not found\n"); + } + + adios2::Variable<int> *bpInts = bpReader.InquireVariable<int>("bpInts"); + + if (bpInts == nullptr) + { + throw std::runtime_error("ERROR: variable " + bpInts->m_Name + + " not found\n"); + } + + /** Dimensions Bounding Box {start}, {count} assume constant across time + * iterations */ + adios2::Box<adios2::Dims> boxDims({0}, {5}); + bpFloats->SetSelection(boxDims); + bpInts->SetSelection(boxDims); + + for (unsigned int t = 0; t < 100; ++t) + { + // Set time selection + /** Steps Bounding Box {start}, {count} */ + adios2::Box<adios2::Steps> boxSteps({static_cast<std::size_t>(t)}, + {1}); + + bpFloats->SetStepSelection(boxSteps); + bpInts->SetStepSelection(boxSteps); + + /** execute Read instructions within step one by one, pointer data + * is available after Read*/ + if (bpReader.GetAdvanceStatus() == adios2::AdvanceStatus::OK) + { + bpReader.Read<float>(*bpFloats, myFloats.data()); + bpReader.Read<int>(*bpInts, myInts.data()); + } + + // do tasks here with the variables + // ... + } + + /** Close bp file, engine becomes unreachable after this */ + bpReader.Close(); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM " + "from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + + MPI_Finalize(); + + return 0; +} diff --git a/examples/experimental/api/FileTransientWrite.cpp b/examples/experimental/api/FileTransientWrite.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9fe4c1a05a46b84c455e5cf4a709b6a8ff8138a3 --- /dev/null +++ b/examples/experimental/api/FileTransientWrite.cpp @@ -0,0 +1,104 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * FileTransientWrite.cpp + * + * Created on: Sep 22, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include <ios> //std::ios_base::failure +#include <iostream> //std::cout +#include <mpi.h> +#include <stdexcept> //std::invalid_argument std::exception +#include <vector> + +#include <adios2.h> + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + /** Application variable */ + std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::vector<int> myInts = {0, -1, -2, -3, -4, -5, -6, -7, -8, -9}; + const std::size_t Nx = myFloats.size(); + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended */ + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO &bpIO = adios.DeclareIO("BPFile_N2N"); + + /// Setting flush policy + // the user can set the memory explicitly for ADIOS2 + bpIO.SetSingleParameter("MaxBufferSize", "100Mb"); + // or by number of steps (naively trying to allocate "N=3" steps before + // flushing + // bpIO.SetSingleParameter("StepsToBuffer", "3"); + + /** global array : name, { shape (total) }, { start (local) }, { + * count + * (local) }, all are constant dimensions */ + adios2::Variable<float> &bpFloats = bpIO.DefineVariable<float>( + "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); + + adios2::Variable<int> &bpInts = bpIO.DefineVariable<int>( + "bpInts", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); + + /** Engine derived class, spawned to start IO operations */ + /** Buffering is done at every Write */ + auto bpWriter = bpIO.Open("myVector.bp", adios2::Mode::Write); + + // default = 0, in bp1 format this is translated to 1, but user should + // be able to start at any step + bpWriter.SetStep(1); + + /** Write variable for buffering */ + for (unsigned int t = 0; t < 100; ++t) + { + bpWriter.Write<float>(bpFloats, myFloats.data()); + bpWriter.Write<int>(bpInts, myInts.data()); + bpWriter.Advance(); // advances step + + // checkpoint/restart every 10 steps, force flush regardless of + // buffer status + if (t % 10 == 0) + { + bpWriter.Flush(); + } + } + + /** Engine becomes unreachable after Close */ + bpWriter.Close(); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM " + "from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + + MPI_Finalize(); + + return 0; +} diff --git a/examples/experimental/api/StreamingAsyncWrite.cpp b/examples/experimental/api/StreamingAsyncWrite.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c6cb435672911c27ea40357b29da55979a5359a --- /dev/null +++ b/examples/experimental/api/StreamingAsyncWrite.cpp @@ -0,0 +1,142 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * StreamingAsyncWrite.cpp + * + * Created on: Sep 22, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include <future> +#include <ios> //std::ios_base::failure +#include <iostream> //std::cout +#include <mpi.h> +#include <stdexcept> //std::invalid_argument std::exception +#include <vector> + +#include <adios2.h> + +void Acquire(adios2::VariableBase &variable, std::vector<float> &data) +{ + // can be anything to set time and data +} + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + /** Application variable */ + std::vector<float> myTime = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::vector<float> mySound = {0, -1, -2, -3, -4, -5, -6, -7, -8, -9}; + const std::size_t Nx = myTime.size(); + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended + */ + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO &streamingIO = adios.DeclareIO("StreamingWrite"); + streamingIO.SetEngine("DataManWriter"); + + auto wanStream = streamingIO.AddTransport( + "WAN", {{"IPAddress", "127.0.0.1"}, {"Port", "22"}}); + + /// Setting flush policy + // the user can set the memory explicitly for ADIOS2 + streamingIO.SetSingleParameter("MaxBufferSize", "100Mb"); + // or by number of steps (naively trying to allocate "N=3" steps + // before + // flushing + // bpIO.SetSingleParameter("StepsToBuffer", "3"); + + /** global array : name, { shape (total) }, { start (local) }, + * { count (local) }, all are constant dimensions */ + adios2::Variable<float> &bpSound = streamingIO.DefineVariable<float>( + "bpSound", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); + + adios2::Variable<float> &bpTime = streamingIO.DefineVariable<int>( + "bpTime", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); + + /** Engine derived class, spawned to start IO operations */ + /** Buffering is done at every Write */ + // we can choose between deferred and synch (default) + auto bpStreamWriter = + streamingIO.Open("myVector.bp", adios2::Mode::Write); + + /** Write variable for buffering */ + bool acquiringData = true; + bool launchedAsync = false; + std::future<void> advanceFuture; + + // infinite loop, unless error is detected + while (acquiringData) + { + try + { + // can be anything depending on the data coming in + Acquire(bpSound, mySound); + Acquire(bpTime, myTime); + + bpStreamWriter.Write<float>(bpTime, myTime.data()); + bpStreamWriter.Write<float>(bpSound, mySound.data()); + + if (launchedAsync) + { + advanceFuture.get(); + } + + // if buffer is full it will flush, otherwise it only updates + // step "batch"...bpTime and bpSound might have different "time + // steps" + advanceFuture = bpStreamWriter.AdvanceAsync(); + launchedAsync = true; + } + catch (std::exception &e) + { + if (rank == 0) + { + std::cout << "Detected runtime error, stopping streaming\n"; + } + acquiringData = false; + } + } + + // wait for last Advance if still buffering + if (advanceFuture.valid()) + { + advanceFuture.wait(); + } + + /** Engine becomes unreachable after Close */ + bpStreamWriter.Close(); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM " + "from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + + MPI_Finalize(); + + return 0; +} diff --git a/examples/experimental/api/StreamingRead.cpp b/examples/experimental/api/StreamingRead.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ffabc3ae53979b96c3a51e858b14bab1104427af --- /dev/null +++ b/examples/experimental/api/StreamingRead.cpp @@ -0,0 +1,141 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * FileStreamingRead.cpp : Reads from a stream of bp self-describing variables, + * extract variables of unknown and known type, flush to disk + * + * Created on: Sep 25, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include <adios2.h> +#include <mpi.h> + +#include <vector> + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + /** Application variable */ + const std::size_t Nx = 10; + std::vector<float> myFloats; + int *myInts = nullptr; + void *myAnyType = nullptr; + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended */ + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO &streamingIO = adios.DeclareIO("ReadBP"); + streamingIO.SetEngine("DataManReader"); + streamingIO.SetParameters({{"MaxBufferMemory", "1Gb"}}); + + auto wanStream = + streamingIO.AddTransport("WAN", {{"IPAddress", "127.0.0.1"}, + {"Port", "22"}, + {"MaxWaitingTime", "1hr"}}); + auto fileStream = streamingIO.AddTransport( + "File", {{"Library", "POSIX"}, {"Name", "TelescopeImages1"}}); + + // assumes we know what variables we are receiving + + /** + * Engine starts listening + */ + adios2::Engine &bpStreamReader = + streamingIO.Open("myVector.bp", adios2::Mode::Read); + + while (bpStreamReader.GetAdvanceStatus() == adios2::AdvanceStatus::OK) + { + // Gets data until buffer is full (1Gb from SetParameters) + bpStreamReader.Get(wanStream); + + /// EXTRACT data duplicating memory + adios2::Variable<float> *bpFloats = + bpStreamReader.InquireVariable<float>("bpFloats"); + + // pre-allocate, this will duplicate memory (just like file Write) + if (bpFloats != nullptr) + { + for (unsigned int t = 0; t < bpFloats->GetAvailableStepsCount(); + ++t) + { + myFloats.reserve(bpFloats->TotalSize()); + myFloats.resize(0); + + adios2::Box<std::size_t> stepBox( + {bpFloats->GetAvailableStepsStart() + t}, {1}); + bpFloats->SetStepSelection(stepBox); + bpStreamReader.Read<float>(*bpFloats, myFloats.data()); + } + } + + adios2::Variable<int> *bpInts = + bpStreamReader.InquireVariable<int>("bpInts"); + + /// EXTRACT data without duplicating memory + // this will not duplicate memory, internal reference to current bp + // buffer + if (bpFloats != nullptr) + { + bpStreamReader.Read<int>(*bpInts, myInts); + } + + /// EXTRACT any type data (this demotes to void*), without + /// duplicating memory + adios2::VariableBase *bpAny = + bpStreamReader.InquireVariableAny("bpUnknown"); + + if (bpAny != nullptr) + { + // by now we must know the type + if (bpAny->m_Type == "int") + { + bpStreamReader.Read<int>( + *dynamic_cast<adios2::Variable<int> *>(bpAny), + reinterpret_cast<int *>(myAnyType)); + } + } + + bpStreamReader.Flush(fileStream); + } + + bpStreamReader.Close(wanStream); // release wanStream + + // do more tasks with data in-memory... + + /** Close all opened transports (in this case only fileStream), engine + * becomes unreachable after + * this call */ + bpStreamReader.Close(); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM " + "from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + + MPI_Finalize(); + return 0; +} diff --git a/examples/experimental/multistep/reader_allsteps.cpp b/examples/experimental/multistep/reader_allsteps.cpp index 84020d2f4d9c030ec9c8aa8b64ba72b832b85b21..50ef831f82405b3847a91412923525c9993a2d0b 100644 --- a/examples/experimental/multistep/reader_allsteps.cpp +++ b/examples/experimental/multistep/reader_allsteps.cpp @@ -123,7 +123,7 @@ int main(int argc, char *argv[]) // auto bpReader = adios.Open( "myNumbers.bp", "r" ); // this would just open with a default transport, which is "BP" auto bpReader = - bpReaderSettings.Open("myNumbers.bp", adios2::OpenMode::Read); + bpReaderSettings.Open("myNumbers.bp", adios2::Mode::Read); if (!bpReader) throw std::ios_base::failure( diff --git a/examples/experimental/multistep/reader_stepping.cpp b/examples/experimental/multistep/reader_stepping.cpp index e8c8decc6f56cfedea0569c4b26b9c3b188ce09a..35322ebfd7253604d8149d21d3f78402ad06b270 100644 --- a/examples/experimental/multistep/reader_stepping.cpp +++ b/examples/experimental/multistep/reader_stepping.cpp @@ -71,7 +71,7 @@ int main(int argc, char *argv[]) } auto bpReader = - bpReaderSettings.Open("myNumbers.bp", adios2::OpenMode::Read); + bpReaderSettings.Open("myNumbers.bp", adios2::Mode::Read); if (!bpReader) { int step = 0; diff --git a/examples/experimental/multistep/writer_multistep.cpp b/examples/experimental/multistep/writer_multistep.cpp index 43216e1728b73a770e215996afe1568c6f3ef49f..48e3f55cee20c81b5e6ca741f179da161cca9b9e 100644 --- a/examples/experimental/multistep/writer_multistep.cpp +++ b/examples/experimental/multistep/writer_multistep.cpp @@ -151,7 +151,7 @@ int main(int argc, char *argv[]) // will // append steps later. auto bpWriter = - bpWriterSettings.Open("myNumbers.bp", adios2::OpenMode::Write); + bpWriterSettings.Open("myNumbers.bp", adios2::Mode::Write); if (!bpWriter) { diff --git a/examples/experimental/runtimeconfig/hello/helloBPWriterXML.cpp b/examples/experimental/runtimeconfig/hello/helloBPWriterXML.cpp index dc34fa06e381e70e8563142cd24bd3905c497073..d0ac5222f83f6802fd918b5ae98e787269b61cc3 100644 --- a/examples/experimental/runtimeconfig/hello/helloBPWriterXML.cpp +++ b/examples/experimental/runtimeconfig/hello/helloBPWriterXML.cpp @@ -74,7 +74,7 @@ int main(int argc, char *argv[]) "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); /** Engine derived class, spawned to start IO operations */ - auto bpWriter = bpIO.Open("myVector.bp", adios2::OpenMode::Write); + auto bpWriter = bpIO.Open("myVector.bp", adios2::Mode::Write); if (!bpWriter) { diff --git a/examples/experimental/runtimeconfig/hello/helloBPWriterXML_nompi.cpp b/examples/experimental/runtimeconfig/hello/helloBPWriterXML_nompi.cpp index 50cf93e0016aec9456e5eaec23efdd68eb041b54..c9c7a7dd978025b40ff34444201415110355a500 100644 --- a/examples/experimental/runtimeconfig/hello/helloBPWriterXML_nompi.cpp +++ b/examples/experimental/runtimeconfig/hello/helloBPWriterXML_nompi.cpp @@ -61,7 +61,7 @@ int main(int argc, char *argv[]) "bpFloats", {}, {}, {Nx}, adios2::ConstantDims); /** Engine derived class, spawned to start IO operations */ - auto bpWriter = bpIO.Open("myVector.bp", adios2::OpenMode::Write); + auto bpWriter = bpIO.Open("myVector.bp", adios2::Mode::Write); if (!bpWriter) { diff --git a/examples/heatTransfer/read/heatRead_adios2.cpp b/examples/heatTransfer/read/heatRead_adios2.cpp index 35ec668372a3c950002659d1487cac773a4515c7..18fafc9299739302b52537200781a160e8b4c4ea 100644 --- a/examples/heatTransfer/read/heatRead_adios2.cpp +++ b/examples/heatTransfer/read/heatRead_adios2.cpp @@ -62,14 +62,8 @@ int main(int argc, char *argv[]) bpReaderIO.AddTransport("File", {{"verbose", "4"}}); } - auto bpReader = - bpReaderIO.Open(inputfile, adios2::OpenMode::Read, mpiReaderComm); - - if (!bpReader) - { - throw std::ios_base::failure("ERROR: failed to open " + - std::string(inputfile) + "\n"); - } + adios2::Engine &bpReader = + bpReaderIO.Open(inputfile, adios2::Mode::Read, mpiReaderComm); unsigned int gndx; unsigned int gndy; @@ -77,19 +71,20 @@ int main(int argc, char *argv[]) // bpReader->Read<unsigned int>("gndy", &gndy); adios2::Variable<unsigned int> *vgndx = - bpReader->InquireVariable<unsigned int>("gndx"); + bpReader.InquireVariable<unsigned int>("gndx"); gndx = vgndx->m_Data[0]; adios2::Variable<unsigned int> *vgndy = - bpReader->InquireVariable<unsigned int>("gndy"); + bpReader.InquireVariable<unsigned int>("gndy"); gndy = vgndy->m_Data[0]; if (rank == 0) { std::cout << "gndx = " << gndx << std::endl; std::cout << "gndy = " << gndy << std::endl; - std::cout << "# of steps = " << vgndy->m_AvailableSteps << std::endl; + std::cout << "# of steps = " << vgndy->GetAvailableStepsCount() + << std::endl; } // 1D decomposition of the columns, which is inefficient for reading! @@ -104,21 +99,24 @@ int main(int argc, char *argv[]) std::cout << "rank " << rank << " reads " << readsize[1] << " columns from offset " << offset[1] << std::endl; - adios2::Variable<double> *vT = bpReader->InquireVariable<double>("T"); + adios2::Variable<double> *vT = bpReader.InquireVariable<double>("T"); - double *T = new double[vT->m_AvailableSteps * readsize[0] * readsize[1]]; + double *T = + new double[vT->GetAvailableStepsCount() * readsize[0] * readsize[1]]; // Create a 2D selection for the subset - vT->SetSelection(offset, readsize); - vT->SetStepSelection(0, vT->m_AvailableSteps); + vT->SetSelection(adios2::Box<adios2::Dims>(offset, readsize)); + vT->SetStepSelection( + adios2::Box<std::size_t>(0, vT->GetAvailableStepsCount())); // Arrays are read by scheduling one or more of them // and performing the reads at once - bpReader->ScheduleRead<double>(*vT, T); - bpReader->PerformReads(adios2::ReadMode::Blocking); + // bpReader->ScheduleRead<double>(*vT, T); + // bpReader->PerformReads(adios2::ReadMode::Blocking); - printData(T, readsize.data(), offset.data(), rank, vT->m_AvailableSteps); - bpReader->Close(); + printData(T, readsize.data(), offset.data(), rank, + vT->GetAvailableStepsCount()); + bpReader.Close(); delete[] T; MPI_Finalize(); return 0; diff --git a/examples/heatTransfer/write/IO_adios2.cpp b/examples/heatTransfer/write/IO_adios2.cpp index e795d5976ef61e74f0c7613c5b41b411f1bb50d5..c3d9a22e73e72140e1ae54f5a9ea40a62e53e0b0 100644 --- a/examples/heatTransfer/write/IO_adios2.cpp +++ b/examples/heatTransfer/write/IO_adios2.cpp @@ -23,7 +23,7 @@ static int rank_saved; adios2::ADIOS *ad = nullptr; -std::shared_ptr<adios2::Engine> bpWriter; +adios2::Engine *bpWriter = nullptr; adios2::Variable<double> *varT = nullptr; adios2::Variable<unsigned int> *varGndx = nullptr; @@ -65,12 +65,7 @@ IO::IO(const Settings &s, MPI_Comm comm) // varT.AddTransform( tr, "" ); // varT.AddTransform( tr,"accuracy=0.001" ); // for ZFP - bpWriter = bpio.Open(m_outputfilename, adios2::OpenMode::Write, comm); - - if (!bpWriter) - { - throw std::ios_base::failure("ERROR: failed to open ADIOS bpWriter\n"); - } + bpWriter = &bpio.Open(m_outputfilename, adios2::Mode::Write, comm); } IO::~IO() @@ -90,8 +85,8 @@ void IO::write(int step, const HeatTransfer &ht, const Settings &s, // Make a selection to describe the local dimensions of the variable we // write and its offsets in the global spaces. This could have been done in // adios.DefineVariable() - adios2::SelectionBoundingBox sel({s.offsx, s.offsy}, {s.ndx, s.ndy}); - varT->SetSelection(sel); + varT->SetSelection( + adios2::Box<adios2::Dims>({s.offsx, s.offsy}, {s.ndx, s.ndy})); /* Select the area that we want to write from the data pointer we pass to the @@ -104,9 +99,7 @@ void IO::write(int step, const HeatTransfer &ht, const Settings &s, above. Default memspace is always the full selection. */ - adios2::SelectionBoundingBox memspace = - adios2::SelectionBoundingBox({1, 1}, {s.ndx, s.ndy}); - varT->SetMemorySelection(memspace); + varT->SetMemorySelection(adios2::Box<adios2::Dims>({1, 1}, {s.ndx, s.ndy})); bpWriter->Write<unsigned int>(*varGndx, s.gndx); bpWriter->Write<unsigned int>("gndy", s.gndy); diff --git a/examples/heatTransfer/write/IO_ph5_adios2.cpp b/examples/heatTransfer/write/IO_ph5_adios2.cpp index e4ce15343f77fa9d6a9a0c0bacc6245c036747e7..b2d57eefd07223f7a3cebadd27afbc571c282f4f 100644 --- a/examples/heatTransfer/write/IO_ph5_adios2.cpp +++ b/examples/heatTransfer/write/IO_ph5_adios2.cpp @@ -55,7 +55,7 @@ IO::IO(const Settings &s, MPI_Comm comm) // varT.AddTransform( tr, "" ); // varT.AddTransform( tr,"accuracy=0.001" ); // for ZFP - h5writer = h5io.Open(m_outputfilename, adios2::OpenMode::Write, comm); + h5writer = h5io.Open(m_outputfilename, adios2::Mode::Write, comm); if (h5writer == nullptr) throw std::ios_base::failure("ERROR: failed to open ADIOS h5writer\n"); diff --git a/examples/hello/adios1Writer/helloADIOS1Writer.cpp b/examples/hello/adios1Writer/helloADIOS1Writer.cpp index aa4a075b3eab992899094967aba67c8a5bb52407..b2daad010d1d58d1599fa632ef22fa7db9a97087 100644 --- a/examples/hello/adios1Writer/helloADIOS1Writer.cpp +++ b/examples/hello/adios1Writer/helloADIOS1Writer.cpp @@ -51,7 +51,7 @@ int main(int argc, char *argv[]) /** Engine derived class, spawned to start IO operations */ auto adios1Writer = - adios1IO.Open("myVector.bp", adios2::OpenMode::Write); + adios1IO.Open("myVector.bp", adios2::Mode::Write); if (!adios1Writer) { diff --git a/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp b/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp index 72231d5dbb051e96b49a2febd2a87b80a91e3f59..269579613db21907825a94172bdf6abae9ea0c75 100644 --- a/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp +++ b/examples/hello/adios1Writer/helloADIOS1Writer_nompi.cpp @@ -37,7 +37,7 @@ int main(int argc, char *argv[]) /** Engine derived class, spawned to start IO operations */ auto adios1Writer = - adios1IO.Open("myVector.bp", adios2::OpenMode::Write); + adios1IO.Open("myVector.bp", adios2::Mode::Write); if (!adios1Writer) { diff --git a/examples/hello/bpAttributeWriter/helloBPAttributeWriter.cpp b/examples/hello/bpAttributeWriter/helloBPAttributeWriter.cpp index 7061f1db3a7ffdc19c96bb5afe47e4c2f3c28288..896589f264c0c9c8de2dfa43f6ddce78e707e327 100644 --- a/examples/hello/bpAttributeWriter/helloBPAttributeWriter.cpp +++ b/examples/hello/bpAttributeWriter/helloBPAttributeWriter.cpp @@ -56,19 +56,14 @@ int main(int argc, char *argv[]) myDoubles.size()); /** Engine derived class, spawned to start IO operations */ - auto bpWriter = bpIO.Open("myVector.bp", adios2::OpenMode::Write); - - if (!bpWriter) - { - throw std::ios_base::failure( - "ERROR: bpWriter not created at Open\n"); - } + adios2::Engine &bpWriter = + bpIO.Open("myVector.bp", adios2::Mode::Write); /** Write variable for buffering */ - bpWriter->Write<float>(bpFloats, myFloats.data()); + bpWriter.Write<float>(bpFloats, myFloats.data()); /** Create bp file, engine becomes unreachable after this*/ - bpWriter->Close(); + bpWriter.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/hello/bpAttributeWriter/helloBPAttributeWriter_nompi.cpp b/examples/hello/bpAttributeWriter/helloBPAttributeWriter_nompi.cpp index 850d907ea325fa9348c29c910c1b074030c36716..6587f5e21338572637e26b0826d25f54bf4ea5af 100644 --- a/examples/hello/bpAttributeWriter/helloBPAttributeWriter_nompi.cpp +++ b/examples/hello/bpAttributeWriter/helloBPAttributeWriter_nompi.cpp @@ -49,7 +49,8 @@ int main(int argc, char *argv[]) myDoubles.size()); /** Engine derived class, spawned to start IO operations */ - auto bpWriter = bpIO.Open("myVector.bp", adios2::OpenMode::Write); + adios2::Engine &bpWriter = + bpIO.Open("myVector.bp", adios2::Mode::Write); if (!bpWriter) { @@ -58,10 +59,10 @@ int main(int argc, char *argv[]) } /** Write variable for buffering */ - bpWriter->Write<float>(bpFloats, myFloats.data()); + bpWriter.Write<float>(bpFloats, myFloats.data()); /** Create bp file, engine becomes unreachable after this*/ - bpWriter->Close(); + bpWriter.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/hello/bpFlushWriter/helloBPFlushWriter.cpp b/examples/hello/bpFlushWriter/helloBPFlushWriter.cpp index 9309811c7016a4df7aec82f052962c53fc6601a7..5c70b863e03e23721268c56218506b73af9c264c 100644 --- a/examples/hello/bpFlushWriter/helloBPFlushWriter.cpp +++ b/examples/hello/bpFlushWriter/helloBPFlushWriter.cpp @@ -50,24 +50,19 @@ int main(int argc, char *argv[]) "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); /** Engine derived class, spawned to start IO operations */ - auto bpWriter = bpIO.Open("myVectorFlush.bp", adios2::OpenMode::Write); - - if (!bpWriter) - { - throw std::ios_base::failure( - "ERROR: bpWriter not created at Open\n"); - } + adios2::Engine &bpWriter = + bpIO.Open("myVectorFlush.bp", adios2::Mode::Write); for (unsigned int t = 0; t < 100; ++t) { /** values to time step */ myFloats.assign(myFloats.size(), t); /** Write variable for buffering */ - bpWriter->Write<float>(bpFloats, myFloats.data()); + bpWriter.Write<float>(bpFloats, myFloats.data()); } /** Create bp file, engine becomes unreachable after this*/ - bpWriter->Close(); + bpWriter.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/hello/bpFlushWriter/helloBPFlushWriter_nompi.cpp b/examples/hello/bpFlushWriter/helloBPFlushWriter_nompi.cpp index 0a08af072a9e949079e48b2172e46c266368a1c1..02d47d2d8b00f162b8e8ee3626d9c945232aef24 100644 --- a/examples/hello/bpFlushWriter/helloBPFlushWriter_nompi.cpp +++ b/examples/hello/bpFlushWriter/helloBPFlushWriter_nompi.cpp @@ -36,19 +36,14 @@ int main(int argc, char *argv[]) "bpFloats", {}, {}, {Nx}, adios2::ConstantDims); /** Engine derived class, spawned to start IO operations */ - auto bpWriter = bpIO.Open("myVector.bp", adios2::OpenMode::Write); - - if (!bpWriter) - { - throw std::ios_base::failure( - "ERROR: bpWriter not created at Open\n"); - } + adios2::Engine &bpWriter = + bpIO.Open("myVector.bp", adios2::Mode::Write); /** Write variable for buffering */ - bpWriter->Write<float>(bpFloats, myFloats.data()); + bpWriter.Write<float>(bpFloats, myFloats.data()); /** Create bp file, engine becomes unreachable after this*/ - bpWriter->Close(); + bpWriter.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/hello/bpReader/helloBPReader.cpp b/examples/hello/bpReader/helloBPReader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd3b81368574e378e0fc2ee78359f58d7d0a050b --- /dev/null +++ b/examples/hello/bpReader/helloBPReader.cpp @@ -0,0 +1,94 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * helloBPReader.cpp: Simple self-descriptive example of how to read a variable + * to a BP File. + * + * Created on: Feb 16, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include <ios> //std::ios_base::failure +#include <iostream> //std::cout +#include <mpi.h> +#include <stdexcept> //std::invalid_argument std::exception +#include <vector> + +#include <adios2.h> + +int main(int argc, char *argv[]) +{ + MPI_Init(&argc, &argv); + int rank, size; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + MPI_Comm_size(MPI_COMM_WORLD, &size); + + /** Application variable */ + const std::size_t Nx = 10; + std::vector<float> myFloats(Nx); + std::vector<int> myInts(Nx); + + try + { + /** ADIOS class factory of IO class objects, DebugON is recommended */ + adios2::ADIOS adios(MPI_COMM_WORLD, adios2::DebugON); + + /*** IO class object: settings and factory of Settings: Variables, + * Parameters, Transports, and Execution: Engines */ + adios2::IO &bpIO = adios.DeclareIO("ReadBP"); + + /** Engine derived class, spawned to start IO operations */ + auto bpReader = bpIO.Open("myVector.bp", adios2::Mode::Read); + + if (!bpReader) + { + throw std::ios_base::failure( + "ERROR: bpWriter not created at Open\n"); + } + + /** Write variable for buffering */ + adios2::Variable<float> *bpFloats = + bpReader->InquireVariable<float>("bpFloats"); + adios2::Variable<int> *bpInts = + bpReader->InquireVariable<int>("bpInts"); + + /** Set selection */ + adios2::Box + + if (bpFloats != nullptr) + { + bpReader->Read<float>(*bpFloats, myFloats.data()); + } + + if (bpFloats != nullptr) + { + bpReader->Read<int>(*bpInts, myInts.data()); + } + + /** Create bp file, engine becomes unreachable after this*/ + bpReader->Close(); + } + catch (std::invalid_argument &e) + { + std::cout << "Invalid argument exception, STOPPING PROGRAM from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::ios_base::failure &e) + { + std::cout << "IO System base failure exception, STOPPING PROGRAM " + "from rank " + << rank << "\n"; + std::cout << e.what() << "\n"; + } + catch (std::exception &e) + { + std::cout << "Exception, STOPPING PROGRAM from rank " << rank << "\n"; + std::cout << e.what() << "\n"; + } + + MPI_Finalize(); + + return 0; +} diff --git a/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp b/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp index 6404d2061861a3b6937b48cd25f5ff629aea2448..7c5228626b8ed47f93ad96b709444c45411783a1 100644 --- a/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp +++ b/examples/hello/bpTimeWriter/helloBPTimeWriter.cpp @@ -49,29 +49,24 @@ int main(int argc, char *argv[]) bpIO.DefineVariable<unsigned int>("timeStep"); /** Engine derived class, spawned to start IO operations */ - auto bpWriter = bpIO.Open("myVector.bp", adios2::OpenMode::Write); - - if (!bpWriter) - { - throw std::ios_base::failure( - "ERROR: bpWriter not created at Open\n"); - } + adios2::Engine &bpWriter = + bpIO.Open("myVector.bp", adios2::Mode::Write); for (unsigned int timeStep = 0; timeStep < 10; ++timeStep) { if (rank == 0) // global single value, only saved by rank 0 { - bpWriter->Write<unsigned int>(bpTimeStep, timeStep); + bpWriter.Write<unsigned int>(bpTimeStep, timeStep); } myFloats[0] = timeStep; // template type is optional, but recommended - bpWriter->Write<float>(bpFloats, myFloats.data()); - bpWriter->Advance(); + bpWriter.Write<float>(bpFloats, myFloats.data()); + bpWriter.Advance(); } - bpWriter->Close(); + bpWriter.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/hello/bpTimeWriter/helloBPTimeWriter_nompi.cpp b/examples/hello/bpTimeWriter/helloBPTimeWriter_nompi.cpp index eb0007caccbc75b8b2b0754dd18f4b3cdddbc205..0b1a8d38f80447c1a4fcf71d1ae7e08227e3ff3c 100644 --- a/examples/hello/bpTimeWriter/helloBPTimeWriter_nompi.cpp +++ b/examples/hello/bpTimeWriter/helloBPTimeWriter_nompi.cpp @@ -39,7 +39,8 @@ int main(int argc, char *argv[]) bpIO.DefineVariable<unsigned int>("timeStep"); /** Engine derived class, spawned to start IO operations */ - auto bpWriter = bpIO.Open("myVector.bp", adios2::OpenMode::Write); + adios2::Engine &bpWriter = + bpIO.Open("myVector.bp", adios2::Mode::Write); if (!bpWriter) { @@ -50,14 +51,14 @@ int main(int argc, char *argv[]) for (unsigned int timeStep = 0; timeStep < 10; ++timeStep) { // template type is optional but recommended - bpWriter->Write<unsigned int>(bpTimeStep, timeStep); + bpWriter.Write<unsigned int>(bpTimeStep, timeStep); myFloats[0] = timeStep; - bpWriter->Write<float>(bpFloats, myFloats.data()); - bpWriter->Advance(); + bpWriter.Write<float>(bpFloats, myFloats.data()); + bpWriter.Advance(); } - bpWriter->Close(); + bpWriter.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/hello/bpWriter/helloBPWriter.cpp b/examples/hello/bpWriter/helloBPWriter.cpp index e2ff7da7ecc4b2cb1353202e0ab85a6e1bf437e2..d394152500006b9abd36a9e63716baaa56087f57 100644 --- a/examples/hello/bpWriter/helloBPWriter.cpp +++ b/examples/hello/bpWriter/helloBPWriter.cpp @@ -26,6 +26,7 @@ int main(int argc, char *argv[]) /** Application variable */ std::vector<float> myFloats = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + std::vector<int> myInts = {0, -1, -2, -3, -4, -5, -6, -7, -8, -9}; const std::size_t Nx = myFloats.size(); try @@ -36,26 +37,27 @@ int main(int argc, char *argv[]) /*** IO class object: settings and factory of Settings: Variables, * Parameters, Transports, and Execution: Engines */ adios2::IO &bpIO = adios.DeclareIO("BPFile_N2N"); + // bpIO.SetParameters({{"Threads", "2"}}); - /** global array : name, { shape (total) }, { start (local) }, { count + /** global array : name, { shape (total) }, { start (local) }, { + * count * (local) }, all are constant dimensions */ adios2::Variable<float> &bpFloats = bpIO.DefineVariable<float>( "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); - /** Engine derived class, spawned to start IO operations */ - auto bpWriter = bpIO.Open("myVector.bp", adios2::OpenMode::Write); + adios2::Variable<int> &bpInts = bpIO.DefineVariable<int>( + "bpInts", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); - if (!bpWriter) - { - throw std::ios_base::failure( - "ERROR: bpWriter not created at Open\n"); - } + /** Engine derived class, spawned to start IO operations */ + adios2::Engine &bpWriter = + bpIO.Open("myVector.bp", adios2::Mode::Write); /** Write variable for buffering */ - bpWriter->Write<float>(bpFloats, myFloats.data()); + bpWriter.Write<float>(bpFloats, myFloats.data()); + bpWriter.Write<int>(bpInts, myInts.data()); /** Create bp file, engine becomes unreachable after this*/ - bpWriter->Close(); + bpWriter.Close(); } catch (std::invalid_argument &e) { @@ -65,9 +67,9 @@ int main(int argc, char *argv[]) } catch (std::ios_base::failure &e) { - std::cout - << "IO System base failure exception, STOPPING PROGRAM from rank " - << rank << "\n"; + std::cout << "IO System base failure exception, STOPPING PROGRAM " + "from rank " + << rank << "\n"; std::cout << e.what() << "\n"; } catch (std::exception &e) diff --git a/examples/hello/bpWriter/helloBPWriter.py b/examples/hello/bpWriter/helloBPWriter.py index 7332f5e7333b159d00187035f4d3911c239a3f53..2e430ef423b7a25783de8e15455ee87b32b70596 100644 --- a/examples/hello/bpWriter/helloBPWriter.py +++ b/examples/hello/bpWriter/helloBPWriter.py @@ -16,7 +16,7 @@ rank = comm.Get_rank() size = comm.Get_size() # User data -myArray = numpy.array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]) +myArray = numpy.array([0, 1., 2., 3., 4., 5., 6., 7., 8., 9.]) Nx = myArray.size # ADIOS MPI Communicator, debug mode @@ -31,5 +31,6 @@ ioArray = bpIO.DefineVariable( # ADIOS Engine bpFileWriter = bpIO.Open("npArray.bp", adios2.OpenModeWrite) +# doesn't work: bpFileWriter = bpIO.Open("npArray.bp", adios2.OpenModeWrite, newcomm) bpFileWriter.Write(ioArray, myArray) bpFileWriter.Close() diff --git a/examples/hello/bpWriter/helloBPWriter_nompi.cpp b/examples/hello/bpWriter/helloBPWriter_nompi.cpp index 0a08af072a9e949079e48b2172e46c266368a1c1..02d47d2d8b00f162b8e8ee3626d9c945232aef24 100644 --- a/examples/hello/bpWriter/helloBPWriter_nompi.cpp +++ b/examples/hello/bpWriter/helloBPWriter_nompi.cpp @@ -36,19 +36,14 @@ int main(int argc, char *argv[]) "bpFloats", {}, {}, {Nx}, adios2::ConstantDims); /** Engine derived class, spawned to start IO operations */ - auto bpWriter = bpIO.Open("myVector.bp", adios2::OpenMode::Write); - - if (!bpWriter) - { - throw std::ios_base::failure( - "ERROR: bpWriter not created at Open\n"); - } + adios2::Engine &bpWriter = + bpIO.Open("myVector.bp", adios2::Mode::Write); /** Write variable for buffering */ - bpWriter->Write<float>(bpFloats, myFloats.data()); + bpWriter.Write<float>(bpFloats, myFloats.data()); /** Create bp file, engine becomes unreachable after this*/ - bpWriter->Close(); + bpWriter.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/hello/datamanReader/helloDataManReader.cpp b/examples/hello/datamanReader/helloDataManReader.cpp index 89f3e8472f3bca26141747913b7c0c1cdb18e6a9..cec8ccebb7fbb4c1f91b334baf3e52f73dd32f90 100644 --- a/examples/hello/datamanReader/helloDataManReader.cpp +++ b/examples/hello/datamanReader/helloDataManReader.cpp @@ -49,16 +49,10 @@ int main(int argc, char *argv[]) {"method_type", "stream"}, {"method", "dump"}}); - auto dataManReader = - dataManIO.Open("myDoubles.bp", adios2::OpenMode::Read); + adios2::Engine &dataManReader = + dataManIO.Open("myDoubles.bp", adios2::Mode::Read); - if (!dataManReader) - { - throw std::ios_base::failure( - "ERROR: failed to create DataMan I/O engine at Open\n"); - } - - dataManReader->SetCallBack(UserCallBack); + dataManReader.SetCallBack(UserCallBack); for (unsigned int i = 0; i < 3; ++i) { @@ -66,14 +60,14 @@ int main(int argc, char *argv[]) } adios2::Variable<double> *ioMyDoubles = - dataManReader->InquireVariable<double>("ioMyDoubles"); + dataManReader.InquireVariable<double>("ioMyDoubles"); if (ioMyDoubles == nullptr) { std::cout << "Variable ioMyDoubles not read...yet\n"; } - dataManReader->Close(); + dataManReader.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/hello/datamanReader/helloDataManReader_nompi.cpp b/examples/hello/datamanReader/helloDataManReader_nompi.cpp index c4516296031171f4cbde6c794a5104fcd5a7c65b..0e66cd99d396201941f5008152c79aa67c4f6403 100644 --- a/examples/hello/datamanReader/helloDataManReader_nompi.cpp +++ b/examples/hello/datamanReader/helloDataManReader_nompi.cpp @@ -44,7 +44,7 @@ int main(int argc, char *argv[]) {"method_type", "stream"}, {"method", "dump"}}); auto dataManReader = - dataManIO.Open("myDoubles.bp", adios2::OpenMode::Read); + dataManIO.Open("myDoubles.bp", adios2::Mode::Read); if (!dataManReader) { diff --git a/examples/hello/datamanWriter/helloDataManWriter.cpp b/examples/hello/datamanWriter/helloDataManWriter.cpp index b22b90a5e0fa0019e666b4ecd12c3e12377dbea8..3b0a28ace10e89cc7ddb8619171068233cda0368 100644 --- a/examples/hello/datamanWriter/helloDataManWriter.cpp +++ b/examples/hello/datamanWriter/helloDataManWriter.cpp @@ -42,17 +42,11 @@ int main(int argc, char *argv[]) // Create engine smart pointer to DataMan Engine due to polymorphism, // Open returns a smart pointer to Engine containing the Derived class - auto dataManWriter = - dataManIO.Open("myFloats.bp", adios2::OpenMode::Write); + adios2::Engine &dataManWriter = + dataManIO.Open("myFloats.bp", adios2::Mode::Write); - if (!dataManWriter) - { - throw std::ios_base::failure( - "ERROR: failed to create DataMan I/O engine at Open\n"); - } - - dataManWriter->Write<float>(bpFloats, myFloats.data()); - dataManWriter->Close(); + dataManWriter.Write<float>(bpFloats, myFloats.data()); + dataManWriter.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/hello/datamanWriter/helloDataManWriter_nompi.cpp b/examples/hello/datamanWriter/helloDataManWriter_nompi.cpp index 65c0ce4e87352b3110b908e3dd02099778f663a6..61f9f5bfb1c21032d845da86b611f0c1e08642ce 100644 --- a/examples/hello/datamanWriter/helloDataManWriter_nompi.cpp +++ b/examples/hello/datamanWriter/helloDataManWriter_nompi.cpp @@ -35,17 +35,11 @@ int main(int argc, char *argv[]) // Create engine smart pointer to DataMan Engine due to polymorphism, // Open returns a smart pointer to Engine containing the Derived class - auto dataManWriter = - dataManIO.Open("myFloats.bp", adios2::OpenMode::Write); + adios2::Engine &dataManWriter = + dataManIO.Open("myFloats.bp", adios2::Mode::Write); - if (!dataManWriter) - { - throw std::ios_base::failure( - "ERROR: failed to create DataMan I/O engine at Open\n"); - } - - dataManWriter->Write<float>(bpFloats, myFloats.data()); - dataManWriter->Close(); + dataManWriter.Write<float>(bpFloats, myFloats.data()); + dataManWriter.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/hello/hdf5Writer/helloHDF5Writer.cpp b/examples/hello/hdf5Writer/helloHDF5Writer.cpp index f67e27c10a7a8c6c49d7f64a80c35cb638a942fc..06cbcf57dde83d955c07eb93da0b74b472bea5e7 100644 --- a/examples/hello/hdf5Writer/helloHDF5Writer.cpp +++ b/examples/hello/hdf5Writer/helloHDF5Writer.cpp @@ -45,7 +45,8 @@ int main(int argc, char *argv[]) "bpFloats", {size * Nx}, {rank * Nx}, {Nx}, adios2::ConstantDims); /** Engine derived class, spawned to start IO operations */ - auto hdf5Writer = hdf5IO.Open("myVector.h5", adios2::OpenMode::Write); + adios2::Engine &hdf5Writer = + hdf5IO.Open("myVector.h5", adios2::Mode::Write); if (!hdf5Writer) { @@ -54,10 +55,10 @@ int main(int argc, char *argv[]) } /** Write variable for buffering */ - hdf5Writer->Write<float>(bpFloats, myFloats.data()); + hdf5Writer.Write<float>(bpFloats, myFloats.data()); /** Create bp file, engine becomes unreachable after this*/ - hdf5Writer->Close(); + hdf5Writer.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/hello/hdf5Writer/helloHDF5Writer_nompi.cpp b/examples/hello/hdf5Writer/helloHDF5Writer_nompi.cpp index 1890da58acad3c2cbaca23d823669f404bd1267e..44f428bfefb52f04d500fad05dfb9cf7ecc84b5d 100644 --- a/examples/hello/hdf5Writer/helloHDF5Writer_nompi.cpp +++ b/examples/hello/hdf5Writer/helloHDF5Writer_nompi.cpp @@ -38,19 +38,14 @@ int main(int argc, char *argv[]) "bpFloats", {}, {}, {Nx}, adios2::ConstantDims); /** Engine derived class, spawned to start IO operations */ - auto hdf5Writer = hdf5IO.Open("myVector.h5", adios2::OpenMode::Write); - - if (!hdf5Writer) - { - throw std::ios_base::failure( - "ERROR: hdf5Writer not created at Open\n"); - } + adios2::Engine &hdf5Writer = + hdf5IO.Open("myVector.h5", adios2::Mode::Write); /** Write variable for buffering */ - hdf5Writer->Write<float>(bpFloats, myFloats.data()); + hdf5Writer.Write<float>(bpFloats, myFloats.data()); /** Create bp file, engine becomes unreachable after this*/ - hdf5Writer->Close(); + hdf5Writer.Close(); } catch (std::invalid_argument &e) { diff --git a/examples/plugins/CMakeLists.txt b/examples/plugins/CMakeLists.txt index bd9914576866a2c9a4c1c4a6d7766e3d65acde19..e19355773a92d099fe98eb57e584169d1cd024b2 100644 --- a/examples/plugins/CMakeLists.txt +++ b/examples/plugins/CMakeLists.txt @@ -1 +1 @@ -add_subdirectory(engine) +#add_subdirectory(engine) diff --git a/examples/plugins/engine/ExampleEnginePlugin.cpp b/examples/plugins/engine/ExampleEnginePlugin.cpp index 09d55a509900e074eccb0df05b258f9b52dee8ba..01d12372720e92bfce88e806274d28301da6408e 100644 --- a/examples/plugins/engine/ExampleEnginePlugin.cpp +++ b/examples/plugins/engine/ExampleEnginePlugin.cpp @@ -54,7 +54,7 @@ namespace adios2 { ExampleEnginePlugin::ExampleEnginePlugin(IO &io, const std::string &name, - const OpenMode openMode, + const Mode openMode, MPI_Comm mpiComm) : adios2::PluginEngineInterface(io, name, openMode, mpiComm) { diff --git a/examples/plugins/engine/ExampleEnginePlugin.h b/examples/plugins/engine/ExampleEnginePlugin.h index aa81d0a1aa1c9e906d0dcaeb4ca91a7ab710e446..5cbd653f4034714e71812bd9bf6aca1692ba1eae 100644 --- a/examples/plugins/engine/ExampleEnginePlugin.h +++ b/examples/plugins/engine/ExampleEnginePlugin.h @@ -29,7 +29,7 @@ class ExampleEnginePlugin : public PluginEngineInterface { public: ExampleEnginePlugin(IO &io, const std::string &name, - const OpenMode openMode, MPI_Comm mpiComm); + const Mode openMode, MPI_Comm mpiComm); virtual ~ExampleEnginePlugin(); void Close(const int transportIndex = -1) override; diff --git a/examples/plugins/engine/examplePluginEngine_class.cpp b/examples/plugins/engine/examplePluginEngine_class.cpp index e8a65905dd72e905b3284e07c3f3919558fb1a73..e09a9a137e76edb37bddf84e9be0288e1a187801 100644 --- a/examples/plugins/engine/examplePluginEngine_class.cpp +++ b/examples/plugins/engine/examplePluginEngine_class.cpp @@ -44,7 +44,7 @@ int main(int argc, char *argv[]) /** Engine derived class, spawned to start IO operations */ io.SetEngine("PluginEngine"); io.SetParameters({{"PluginName", "MyPlugin"}}); - auto writer = io.Open("TestPlugin", adios2::OpenMode::Write); + auto writer = io.Open("TestPlugin", adios2::Mode::Write); if (!writer) { diff --git a/source/adios2.h b/source/adios2.h index 035df18888de4b63ebba0879f6c3783c10de971e..a3492f8d7f0a4372c724152490727e88f2df37c0 100644 --- a/source/adios2.h +++ b/source/adios2.h @@ -12,8 +12,6 @@ #include "adios2/core/ADIOS.h" #include "adios2/core/Engine.h" #include "adios2/core/IO.h" -#include "adios2/core/SelectionBoundingBox.h" -#include "adios2/core/SelectionPoints.h" #include "adios2/core/Transform.h" #endif /* ADIOS2_H_ */ diff --git a/source/adios2/ADIOSMacros.h b/source/adios2/ADIOSMacros.h index 1f01f9ea600594a77b764181b90a504aa3fd4174..d0bb9cbc67d570c7daf506782c0f6294764a9153 100644 --- a/source/adios2/ADIOSMacros.h +++ b/source/adios2/ADIOSMacros.h @@ -2,28 +2,35 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * ADIOSMacros.h - * This contains a set of helper macros used internally + * ADIOSMacros.h : a set of helper macros used internally + * + * Created on: March 23, 2017 + * Author: Chuck Atkins chuck.atkins@kitware.com */ + #ifndef ADIOS2_ADIOSMACROS_H #define ADIOS2_ADIOSMACROS_H #include <string> #include "adios2/ADIOSTypes.h" -// The ADIOS_FOREACH_TYPE_1ARG macro assumes the given argument is a macro which -// takes a single argument that is a type and then inserts the given MACRO for -// each of the known primitive types -// -// An example of this might be to instantiate a template function for each -// known type. For example: -// -// template<typename T> int foo() { /* some implementation of foo */ } -// -// #define instantiate_foo(T) template int foo<T>(); -// ADIOS_FOREACH_TYPE_1ARG(instantiate_foo) -// #undef instantiate_foo -// + +/** + <pre> + The ADIOS_FOREACH_TYPE_1ARG macro assumes the given argument is a macro which + takes a single argument that is a type and then inserts the given MACRO for + each of the known primitive types + + An example of this might be to instantiate a template function for each + known type. For example: + + template<typename T> int foo() { // some implementation of foo } + + #define instantiate_foo(T) template int foo<T>(); + ADIOS_FOREACH_TYPE_1ARG(instantiate_foo) + #undef instantiate_foo + </pre> +*/ #define ADIOS2_FOREACH_TYPE_1ARG(MACRO) \ MACRO(char) \ MACRO(signed char) \ @@ -60,7 +67,8 @@ #define ADIOS2_FOREACH_COMPLEX_TYPE_1ARG(MACRO) \ MACRO(float) \ - MACRO(double) + MACRO(double) \ + MACRO(long double) #define ADIOS2_FOREACH_ZFP_TYPE_1ARG(MACRO) \ MACRO(int32_t) \ @@ -85,29 +93,33 @@ MACRO(double) \ MACRO(long double) -// The ADIOS_FOREACH_TYPE_2ARGS macro assumes the given argument is a macro -// which takes two arguments, the first being a type, and the second being a -// label for that type, i.e. std::complex<float> and CFloat. -// -// An example of this might be to define a virtual method for each known -// type, and since the method is virtual then it cannot be a template. -// For example: -// -// #define declare_foo(T,L) virtual const T& foo ## L (std::string bar); -// ADIOS_FOREACH_TYPE_2ARGS(declare_foo) -// #undef declare_foo -// -// is equivalent to: -// -// virtual char& foo_Char(std::string bar); -// virtual unsigned char& foo_UChar(std::string bar); -// virtual short& foo_Short(std::string bar); -// virtual unsigned short& foo_UShort(std::string bar); -// ... -// virtual std::complex<long double>& foo_CLDouble(std::string bar); -// +/** + <pre> + The ADIOS_FOREACH_TYPE_2ARGS macro assumes the given argument is a macro + which takes two arguments, the first being a type, and the second being a + label for that type, i.e. std::complex<float> and CFloat. + + An example of this might be to define a virtual method for each known + type, and since the method is virtual then it cannot be a template. + For example: + + #define declare_foo(T,L) virtual const T& foo ## L (std::string bar); + ADIOS_FOREACH_TYPE_2ARGS(declare_foo) + #undef declare_foo + + is equivalent to: + + virtual char& foo_Char(std::string bar); + virtual unsigned char& foo_UChar(std::string bar); + virtual short& foo_Short(std::string bar); + virtual unsigned short& foo_UShort(std::string bar); + ... + virtual std::complex<long double>& foo_CLDouble(std::string bar); + </pre> +*/ #define ADIOS2_FOREACH_TYPE_2ARGS(MACRO) \ MACRO(char, Char) \ + MACRO(signed char, SChar) \ MACRO(unsigned char, UChar) \ MACRO(short, Short) \ MACRO(unsigned short, UShort) \ @@ -126,6 +138,7 @@ #define ADIOS2_FOREACH_PRIMITIVE_TYPE_2ARGS(MACRO) \ MACRO(char, Char) \ + MACRO(signed char, Char) \ MACRO(unsigned char, UChar) \ MACRO(short, Short) \ MACRO(unsigned short, UShort) \ @@ -136,10 +149,12 @@ MACRO(unsigned long int, ULInt) \ MACRO(unsigned long long int, ULLInt) \ MACRO(float, Float) \ - MACRO(double, Double) + MACRO(double, Double) \ + MACRO(long double, LDouble) #define ADIOS2_FOREACH_COMPLEX_TYPE_2ARGS(MACRO) \ MACRO(std::complex<float>, CFloat) \ - MACRO(std::complex<double>, CDouble) + MACRO(std::complex<double>, CDouble) \ + MACRO(std::complex<long double>, CLDouble) #endif /* ADIOS2_ADIOSMACROS_H */ diff --git a/source/adios2/ADIOSTypes.h b/source/adios2/ADIOSTypes.h index 0078b66b855ec5728cae3e43ad883c0d27fa1ddb..d05948c15d33848609a7d58d627b56bc8d853ebf 100644 --- a/source/adios2/ADIOSTypes.h +++ b/source/adios2/ADIOSTypes.h @@ -9,7 +9,6 @@ * Author: Chuck Atkins chuck.atkins@kitware.com * Norbert Podhorszki pnorbert@ornl.gov * William F Godoy godoywf@ornl.gov - * */ #ifndef ADIOS2_ADIOSTYPES_H_ @@ -24,6 +23,7 @@ #include <map> #include <string> #include <type_traits> +#include <utility> //std::pair #include <vector> /// \endcond @@ -51,13 +51,14 @@ enum class IOMode }; /** OpenMode in IO Open */ -enum class OpenMode +enum class Mode { Undefined, Write, Read, Append, - ReadWrite, + + Deferred }; enum class ReadMultiplexPattern @@ -134,14 +135,35 @@ enum class TimeUnit /** Type of selection */ enum class SelectionType { - BoundingBox, ///< Contiguous block of data defined by offsets and counts per - /// dimension + BoundingBox, ///< Contiguous block of data defined by offsets and counts + /// per dimension Points, ///< List of individual points WriteBlock, ///< Selection of an individual block written by a writer /// process Auto ///< Let the engine decide what to return }; +// Types +using std::size_t; + +using std::int8_t; +using std::int16_t; +using std::int32_t; +using std::int64_t; + +using std::uint8_t; +using std::uint16_t; +using std::uint32_t; +using std::uint64_t; + +// Complex +using cfloat = std::complex<float>; +using cdouble = std::complex<double>; +using cldouble = std::complex<long double>; + +// Limit +constexpr size_t MaxSizeT = std::numeric_limits<size_t>::max(); + // adios defaults #ifdef _WIN32 const std::string DefaultFileLibrary("fstream"); @@ -152,19 +174,19 @@ const std::string DefaultTimeUnit("Microseconds"); constexpr TimeUnit DefaultTimeUnitEnum(TimeUnit::Microseconds); /** default initial bp buffer size, 16Kb, in bytes */ -constexpr size_t DefaultInitialBufferSize(16 * 1024); +constexpr size_t DefaultInitialBufferSize = 16 * 1024; /** default maximum bp buffer size, unlimited, in bytes. * Needs to be studied for optimizing applications */ -constexpr size_t DefaultMaxBufferSize(std::numeric_limits<size_t>::max() - 1); +constexpr size_t DefaultMaxBufferSize = MaxSizeT - 1; /** default buffer growth factor. Needs to be studied * for optimizing applications*/ -constexpr float DefaultBufferGrowthFactor(1.05f); +constexpr float DefaultBufferGrowthFactor = 1.05f; /** default size for writing/reading files using POSIX/fstream/stdio write * 2Gb - 100Kb (tolerance)*/ -constexpr size_t DefaultMaxFileBatchSize(2147381248); +constexpr size_t DefaultMaxFileBatchSize = 2147381248; constexpr char PathSeparator = #ifdef _WIN32 @@ -177,34 +199,17 @@ constexpr char PathSeparator = constexpr bool DebugON = true; constexpr bool DebugOFF = false; constexpr size_t UnknownDim = 0; -constexpr size_t JoinedDim = std::numeric_limits<size_t>::max() - 1; -constexpr size_t LocalValueDim = std::numeric_limits<size_t>::max() - 2; -constexpr size_t IrregularDim = std::numeric_limits<size_t>::max() - 3; +constexpr size_t JoinedDim = MaxSizeT - 1; +constexpr size_t LocalValueDim = MaxSizeT - 2; +constexpr size_t IrregularDim = MaxSizeT - 3; constexpr bool ConstantDims = true; -constexpr bool ReadIn = true; - -using std::size_t; using Dims = std::vector<size_t>; using Params = std::map<std::string, std::string>; +using Steps = size_t; -// Primitives -// using schar = signed char; -using std::int8_t; -using std::int16_t; -using std::int32_t; -using std::int64_t; - -// using uchar = unsigned char; -using std::uint8_t; -using std::uint16_t; -using std::uint32_t; -using std::uint64_t; - -// Complex -using cfloat = std::complex<float>; -using cdouble = std::complex<double>; -using cldouble = std::complex<long double>; +template <class T> +using Box = std::pair<T, T>; // Get a fixed width integer type from a size specification template <size_t Bytes, bool Signed> @@ -279,6 +284,6 @@ struct TypeInfo<T, typename std::enable_if<std::is_same< using ValueType = typename T::value_type; }; -} // end namespace adios +} // end namespace adios2 #endif /* ADIOS2_ADIOSTYPES_H_ */ diff --git a/source/adios2/CMakeLists.txt b/source/adios2/CMakeLists.txt index 5cca920095ce3fcb6c74e737182a4590a58d50b9..9d9e03b68ade5abd9ca5dc9d4910251721254476 100644 --- a/source/adios2/CMakeLists.txt +++ b/source/adios2/CMakeLists.txt @@ -9,9 +9,6 @@ add_library(adios2 core/ADIOS.cpp core/Engine.cpp core/IO.cpp core/IO.tcc - core/Selection.cpp - core/SelectionBoundingBox.cpp - core/SelectionPoints.cpp core/Transform.cpp core/Transform.tcc core/Variable.cpp core/Variable.tcc core/VariableBase.cpp @@ -26,25 +23,25 @@ add_library(adios2 helper/adiosType.cpp helper/adiosXML.cpp -# engine/bp/BPFileReader.cpp + engine/bp/BPFileReader.cpp engine/bp/BPFileReader.tcc engine/bp/BPFileWriter.cpp engine/bp/BPFileWriter.tcc - engine/plugin/PluginEngine.h engine/plugin/PluginEngine.inl - engine/plugin/PluginEngine.cpp - engine/plugin/PluginEngineInterface.h engine/plugin/PluginEngineInterface.cpp +# engine/plugin/PluginEngine.h engine/plugin/PluginEngine.inl +# engine/plugin/PluginEngine.cpp +# engine/plugin/PluginEngineInterface.h engine/plugin/PluginEngineInterface.cpp - toolkit/capsule/Capsule.cpp - toolkit/capsule/heap/STLVector.cpp - + toolkit/format/BufferSTL.cpp + toolkit/format/bp1/BP1Base.cpp toolkit/format/bp1/BP1Base.tcc toolkit/format/bp1/BP1Aggregator.cpp toolkit/format/bp1/BP1Writer.cpp toolkit/format/bp1/BP1Writer.tcc + toolkit/format/bp1/BP1Reader.cpp toolkit/format/bp1/BP1Reader.tcc toolkit/profiling/iochrono/Timer.cpp toolkit/transport/Transport.cpp - toolkit/transport/file/FilePointer.cpp - toolkit/transport/file/FileStream.cpp + toolkit/transport/file/FileStdio.cpp + toolkit/transport/file/FileFStream.cpp toolkit/transportman/TransportMan.cpp @@ -59,11 +56,11 @@ target_link_libraries(adios2 PRIVATE adios2sys pugixml) target_link_libraries(adios2 PUBLIC ${CMAKE_THREAD_LIBS_INIT}) if(UNIX) - target_sources(adios2 PRIVATE toolkit/transport/file/FileDescriptor.cpp) + target_sources(adios2 PRIVATE toolkit/transport/file/FilePOSIX.cpp) endif() if(ADIOS2_HAVE_SysVShMem) - target_sources(adios2 PRIVATE toolkit/capsule/shmem/ShmSystemV.cpp) + target_sources(adios2 PRIVATE toolkit/transport/shm/ShmSystemV.cpp) endif() if(ADIOS2_HAVE_DataMan) diff --git a/source/adios2/core/ADIOS.cpp b/source/adios2/core/ADIOS.cpp index d4853c603d064962abc543a8caa94dfc36a01643..fadeb893a2276d8b99453d777eed95ea0e8c60c0 100644 --- a/source/adios2/core/ADIOS.cpp +++ b/source/adios2/core/ADIOS.cpp @@ -158,4 +158,4 @@ void ADIOS::CheckMPI() const } } -} // end namespace adios +} // end namespace adios2 diff --git a/source/adios2/core/ADIOS.h b/source/adios2/core/ADIOS.h index eba4e72430fa5b313253fb1fc8793c0f0adeef29..0a10b8f568bb0cb33cc169cfbb66bba94bbc422e 100644 --- a/source/adios2/core/ADIOS.h +++ b/source/adios2/core/ADIOS.h @@ -123,6 +123,6 @@ private: void CheckMPI() const; }; -} // end namespace adios +} // end namespace adios2 #endif /* ADIOS2_ADIOS_H_ */ diff --git a/source/adios2/core/Engine.cpp b/source/adios2/core/Engine.cpp index 9d19e892b7d357e35e1bbe3ef2de05ff4377df5c..8915ba5a73cb11dfd4b068a96c0e52def6907fc5 100644 --- a/source/adios2/core/Engine.cpp +++ b/source/adios2/core/Engine.cpp @@ -22,7 +22,7 @@ namespace adios2 { Engine::Engine(const std::string engineType, IO &io, const std::string &name, - const OpenMode openMode, MPI_Comm mpiComm) + const Mode openMode, MPI_Comm mpiComm) : m_EngineType(engineType), m_IO(io), m_Name(name), m_OpenMode(openMode), m_MPIComm(mpiComm), m_DebugMode(io.m_DebugMode) { @@ -47,10 +47,11 @@ void Engine::Write(const std::string &variableName, const void *values) void Engine::Advance(const float /*timeout_sec*/) {} void Engine::Advance(const AdvanceMode /*mode*/, const float /*timeout_sec*/) {} -void Engine::AdvanceAsync( - AdvanceMode /*mode*/, +std::future<void> Engine::AdvanceAsync( + AdvanceMode mode, std::function<void(std::shared_ptr<adios2::Engine>)> /*callback*/) { + return std::future<void>(); } AdvanceStatus Engine::GetAdvanceStatus() { return m_AdvanceStatus; } @@ -59,7 +60,6 @@ void Engine::Close(const int /*transportIndex*/) {} // READ void Engine::Release() {} -void Engine::PerformReads(ReadMode /*mode*/){}; // PROTECTED void Engine::Init() {} @@ -78,7 +78,8 @@ ADIOS2_FOREACH_TYPE_1ARG(declare_type) #undef declare_type void Engine::DoWrite(VariableCompound &variable, const void *values) -{ // TODO +{ + ThrowUp("Write Compound"); } void Engine::DoWrite(const std::string &variableName, const void *values) @@ -123,34 +124,30 @@ void Engine::DoWrite(const std::string &variableName, const void *values) } // end DoWrite // READ -VariableBase *Engine::InquireVariableUnknown(const std::string &name, - const bool readIn) -{ - return nullptr; -} - -#define define(T, L) \ - Variable<T> *Engine::InquireVariable##L(const std::string &name, \ - const bool readIn) \ +#define declare(T, L) \ + Variable<T> *Engine::DoInquireVariable##L( \ + const std::string & /*variableName*/) \ { \ + ThrowUp("DoInquireVariable"); \ return nullptr; \ } -ADIOS2_FOREACH_TYPE_2ARGS(define) -#undef define -#define declare_type(T) \ - void Engine::DoScheduleRead(Variable<T> &variable, const T *values) \ - { \ - ThrowUp("ScheduleRead"); \ - } \ - \ - void Engine::DoScheduleRead(const std::string &variableName, \ - const T *values) \ - { \ - ThrowUp("ScheduleRead"); \ - } -ADIOS2_FOREACH_TYPE_1ARG(declare_type) -#undef declare_type +ADIOS2_FOREACH_TYPE_2ARGS(declare) +#undef declare + +void Engine::Flush(const int transportIndex) {} + +void Engine::Get(const int transportIndex) {} + +std::future<void> Engine::FlushAsync(const int transportIndex) +{ + return std::future<void>(); +} + +std::future<void> Engine::GetAsync(const int transportIndex) +{ + return std::future<void>(); +} // PRIVATE void Engine::ThrowUp(const std::string function) const diff --git a/source/adios2/core/Engine.h b/source/adios2/core/Engine.h index 3a405452f07e5dd2c381d3e6884eb0974900f5ec..a55e45e07a0c53aef8c033194920f475b266e823 100644 --- a/source/adios2/core/Engine.h +++ b/source/adios2/core/Engine.h @@ -16,6 +16,7 @@ /// \cond EXCLUDE_FROM_DOXYGEN #include <functional> //std::function +#include <future> #include <map> #include <memory> //std::shared_ptr #include <set> @@ -25,6 +26,7 @@ #include "adios2/ADIOSConfig.h" #include "adios2/ADIOSMPICommOnly.h" +#include "adios2/ADIOSMacros.h" #include "adios2/ADIOSTypes.h" #include "adios2/core/IO.h" #include "adios2/core/Variable.h" @@ -50,10 +52,12 @@ public: * @param mpiComm new communicator passed at Open or from ADIOS class */ Engine(const std::string engineType, IO &io, const std::string &name, - const OpenMode openMode, MPI_Comm mpiComm); + const Mode openMode, MPI_Comm mpiComm); virtual ~Engine() = default; + void SetStep(const size_t step = 0); + /** * Write function that adds static checking on the variable to be passed by * values @@ -106,13 +110,16 @@ public: void Write(const std::string &variableName, const void *values); /** - * - * @param variableName - * @return + * Inquires if a variable of a certain type exists. + * Returns a pointer reference, not need to manage memory. + * @param variableName input to search + * @return pointer reference to existing variable, nullptr if variable + * doesn't exist */ template <class T> - Variable<T> *InquireVariable(const std::string &variableName, - const bool readIn = false); + Variable<T> *InquireVariable(const std::string &variableName); + + VariableBase *InquireVariableAny(const std::string &variableName); /** * Read function that adds static checking on the variable to be passed by @@ -124,56 +131,7 @@ public: * must use Read(variable) instead intentionally */ template <class T> - void Read(Variable<T> &variable, T *values); - - /** - * String version - * @param variableName - * @param values - */ - template <class T> - void Read(const std::string &variableName, T *values); - - /** - * Single value version - * @param variable - * @param values - */ - template <class T> - void Read(Variable<T> &variable, T &values); - - /** - * Single value version using string as variable handlers - * @param variableName - * @param values - */ - template <class T> - void Read(const std::string &variableName, T &values); - - /** - * Unallocated version, ADIOS will allocate space for incoming data - * @param variable - */ - template <class T> - void Read(Variable<T> &variable); - - /** - * Unallocated version, ADIOS will allocate space for incoming data - * @param variableName - */ - template <class T> - void Read(const std::string &variableName); - - /** - * Read function that adds static checking on the variable to be passed by - * values - * It then calls its corresponding derived class virtual function - * This version uses m_Group to look for the variableName. - * @param variable name of variable to the written - * @param values pointer passed from the application - */ - template <class T> - void ScheduleRead(Variable<T> &variable, T *values); + void Read(Variable<T> &variable, T *values = nullptr); /** * String version @@ -181,43 +139,7 @@ public: * @param values */ template <class T> - void ScheduleRead(const std::string &variableName, T *values); - - /** - * Single value version - * @param variable - * @param values - */ - template <class T> - void ScheduleRead(Variable<T> &variable, T &values); - - /** - * Single value version using string as variable handlers - * @param variableName - * @param values - */ - template <class T> - void ScheduleRead(const std::string &variableName, T &values); - - /** - * Unallocated version, ADIOS will allocate space for incoming data - * @param variableName - */ - // virtual void ScheduleRead(const std::string &variableName); - - /** - * Unallocated unspecified version, ADIOS will receive any variable and will - * allocate space for incoming data - */ - // virtual void ScheduleRead(); - - /** - * Perform all scheduled reads, either blocking until all reads completed, - * or - * return immediately. - * @param mode Blocking or non-blocking modes - */ - virtual void PerformReads(ReadMode mode); + void Read(const std::string &variableName, T *values = nullptr); /** * Reader application indicates that no more data will be read from the @@ -250,37 +172,14 @@ public: * readers * @param callback Will be called when advance is completed. */ - virtual void AdvanceAsync(const AdvanceMode mode, - AdvanceAsyncCallback callback); + // virtual void AdvanceAsync(const AdvanceMode mode, + // AdvanceAsyncCallback callback); + std::future<void> AdvanceAsync( + AdvanceMode mode, + std::function<void(std::shared_ptr<adios2::Engine>)> /*callback*/); AdvanceStatus GetAdvanceStatus(); - /** - * @brief Let ADIOS allocate memory for a variable in the buffer (bp), - * to be populated by the user. Variable dimensions are fixed. - * To decrease the cost of copying memory, a user may let ADIOS allocate - * the memory for a user-variable, - * according to the definition of an ADIOS-variable. The memory will be - * part - * of the ADIOS buffer used - * by the engine and it lives until the engine (file, stream) is closed. - * A variable that has been allocated this way (cannot have its local - * dimensions changed, and AdvanceAsync() should be - * used instead of Advance() and the user-variable must not be modified - * by - * the application until the notification arrives. - * This is required so that any reader can access the written data - * before - * the application overwrites it. - * @param var Variable with defined local dimensions and offsets in - * global - * space - * @param fillValue Fill the allocated array with this value - * @return A constant pointer reference to the allocated array. - */ - template <class T> - T *AllocateVariable(Variable<T> &var, T fillValue = 0); - /** * Needed for DataMan Engine * @param callback function passed from the user @@ -294,7 +193,7 @@ public: * reading * @return a vector of strings */ - std::vector<std::string> VariableNames(); + std::map<std::string, std::string> Variables(); /** * Closes a particular transport, or all if -1 @@ -302,6 +201,12 @@ public: */ virtual void Close(const int transportIndex = -1) = 0; + virtual void Flush(const int transportIndex = -1); + virtual void Get(const int transportIndex = -1); + + virtual std::future<void> FlushAsync(const int transportIndex = -1); + virtual std::future<void> GetAsync(const int transportIndex = -1); + protected: /** from derived class */ const std::string m_EngineType; @@ -313,7 +218,7 @@ protected: const std::string m_Name; /** open mode from ADIOSTypes.h OpenMode */ - const OpenMode m_OpenMode; + const Mode m_OpenMode; /** from ADIOS class passed to Engine created with Open * if no new communicator is passed */ @@ -355,30 +260,18 @@ protected: */ void DoWrite(const std::string &variableName, const void *values); - // READ - virtual VariableBase *InquireVariableUnknown(const std::string &name, - const bool readIn); +// READ #define declare(T, L) \ - virtual Variable<T> *InquireVariable##L(const std::string &name, \ - const bool readIn); + virtual Variable<T> *DoInquireVariable##L(const std::string &variableName); + ADIOS2_FOREACH_TYPE_2ARGS(declare) #undef declare -// Known-type -#define declare_type(T) \ - virtual void DoScheduleRead(Variable<T> &variable, const T *values); \ - virtual void DoScheduleRead(const std::string &variableName, \ - const T *values); - ADIOS2_FOREACH_TYPE_1ARG(declare_type) -#undef declare_type - - void DoScheduleRead(const std::string &variableName, void *values); - private: /** Throw exception by Engine virtual functions not implemented by a derived * class */ void ThrowUp(const std::string function) const; -}; +}; // END OF CLASS #define declare_template_instantiation(T) \ extern template void Engine::Write<T>(Variable<T> &, const T *); \ diff --git a/source/adios2/core/Engine.inl b/source/adios2/core/Engine.inl index 486df9c53c150d2a4d2813f5db81d85d9fcf5257..0a527ab664f92141f8956e9acf3405fbeed0b58c 100644 --- a/source/adios2/core/Engine.inl +++ b/source/adios2/core/Engine.inl @@ -17,80 +17,6 @@ namespace adios2 { -template <class T> -T *Engine::AllocateVariable(Variable<T> &variable, T fillValue) -{ - throw std::invalid_argument("ERROR: type not supported for variable " + - variable.m_Name + " in call to \n"); -} - -template <class T> -void Engine::Read(Variable<T> &variable, T *values) -{ - DoScheduleRead(variable, values); - PerformReads(ReadMode::Blocking); -} - -template <class T> -void Engine::Read(const std::string &variableName, T *values) -{ - DoScheduleRead(variableName, values); - PerformReads(ReadMode::Blocking); -} - -template <class T> -void Engine::Read(Variable<T> &variable, T &values) -{ - DoScheduleRead(variable, &values); - PerformReads(ReadMode::Blocking); -} - -template <class T> -void Engine::Read(const std::string &variableName, T &values) -{ - DoScheduleRead(variableName, &values); - PerformReads(ReadMode::Blocking); -} - -template <class T> -void Engine::Read(Variable<T> &variable) -{ - DoScheduleRead(variable); - PerformReads(ReadMode::Blocking); -} - -template <class T> -void Engine::Read(const std::string &variableName) -{ - // TODO - // DoScheduleRead(variableName); - // PerformReads(PerformReadMode::BLOCKINGREAD); -} - -template <class T> -void Engine::ScheduleRead(Variable<T> &variable, T *values) -{ - DoScheduleRead(variable, values); -} - -template <class T> -void Engine::ScheduleRead(const std::string &variableName, T *values) -{ - DoScheduleRead(variableName, values); -} - -template <class T> -void Engine::ScheduleRead(Variable<T> &variable, T &values) -{ - DoScheduleRead(variable, &values); -} - -template <class T> -void Engine::ScheduleRead(const std::string &variableName, T &values) -{ - DoScheduleRead(variableName, &values); -} - } // end namespace adios2 #endif /* ADIOS2_CORE_ENGINE_INL_ */ diff --git a/source/adios2/core/Engine.tcc b/source/adios2/core/Engine.tcc index 74666c7324f17e0fef9ee6ec6174763991883ece..d7d989e02712adf7435253de24008ebd53244b21 100644 --- a/source/adios2/core/Engine.tcc +++ b/source/adios2/core/Engine.tcc @@ -47,130 +47,16 @@ void Engine::Write(const std::string &variableName, const T values) Write(m_IO.GetVariable<T>(variableName), &values); } -template <> -Variable<char> *Engine::InquireVariable<char>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableChar(variableName, readIn); -} - -template <> -Variable<unsigned char> * -Engine::InquireVariable<unsigned char>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableUChar(variableName, readIn); -} - -template <> -Variable<short> *Engine::InquireVariable<short>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableShort(variableName, readIn); -} - -template <> -Variable<unsigned short> * -Engine::InquireVariable<unsigned short>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableUShort(variableName, readIn); -} - -template <> -Variable<int> *Engine::InquireVariable<int>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableInt(variableName, readIn); -} - -template <> -Variable<unsigned int> * -Engine::InquireVariable<unsigned int>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableUInt(variableName, readIn); -} - -template <> -Variable<long int> * -Engine::InquireVariable<long int>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableLInt(variableName, readIn); -} - -template <> -Variable<long long int> * -Engine::InquireVariable<long long int>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableLLInt(variableName, readIn); -} - -template <> -Variable<unsigned long int> * -Engine::InquireVariable<unsigned long int>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableULInt(variableName, readIn); -} - -template <> -Variable<unsigned long long int> * -Engine::InquireVariable<unsigned long long int>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableULLInt(variableName, readIn); -} - -template <> -Variable<float> *Engine::InquireVariable<float>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableFloat(variableName, readIn); -} - -template <> -Variable<double> * -Engine::InquireVariable<double>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableDouble(variableName, readIn); -} - -template <> -Variable<long double> * -Engine::InquireVariable<long double>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableLDouble(variableName, readIn); -} - -template <> -Variable<cfloat> * -Engine::InquireVariable<cfloat>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCFloat(variableName, readIn); -} - -template <> -Variable<cdouble> * -Engine::InquireVariable<cdouble>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCDouble(variableName, readIn); -} - -template <> -Variable<cldouble> * -Engine::InquireVariable<cldouble>(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCLDouble(variableName, readIn); -} +// READ +#define define(T, L) \ + template <> \ + Variable<T> *Engine::InquireVariable<T>(const std::string &name) \ + { \ + return DoInquireVariable##L(name); \ + } +ADIOS2_FOREACH_TYPE_2ARGS(define) +#undef define -} // end namespace adios +} // end namespace adios2 #endif /** ADIOS2_CORE_ENGINE_TCC_ */ diff --git a/source/adios2/core/IO.cpp b/source/adios2/core/IO.cpp index e635a100863235e804bc300dae48218382ededc5..f36f87103b4fd2fab314a406dd965478cbdb511a 100644 --- a/source/adios2/core/IO.cpp +++ b/source/adios2/core/IO.cpp @@ -12,8 +12,9 @@ #include "IO.tcc" #include "adios2/ADIOSMPI.h" +#include "adios2/engine/bp/BPFileReader.h" #include "adios2/engine/bp/BPFileWriter.h" -#include "adios2/engine/plugin/PluginEngine.h" +//#include "adios2/engine/plugin/PluginEngine.h" #include "adios2/helper/adiosFunctions.h" //BuildParametersMap #ifdef ADIOS2_HAVE_DATAMAN // external dependencies @@ -191,34 +192,27 @@ bool IO::RemoveVariable(const std::string &name) noexcept return isRemoved; } -std::shared_ptr<Engine> IO::Open(const std::string &name, - const OpenMode openMode, MPI_Comm mpiComm) +Engine &IO::Open(const std::string &name, const Mode openMode, MPI_Comm mpiComm) { if (m_DebugMode) { - // Check if Engine already exists - if (m_EngineNames.count(name) == 1) + if (m_Engines.count(name) == 1) { - throw std::invalid_argument( - "ERROR: IO Engine with name " + name + - " already created by Open, in call from Open.\n"); + throw std::invalid_argument("ERROR: IO Engine with name " + name + + " already created, in call to Open.\n"); } } std::shared_ptr<Engine> engine; - m_EngineNames.insert(name); const bool isDefaultWriter = m_EngineType.empty() && - (openMode == OpenMode::Write || openMode == OpenMode::Append) + (openMode == Mode::Write || openMode == Mode::Append) ? true : false; const bool isDefaultReader = - m_EngineType.empty() && - (openMode == OpenMode::Read || openMode == OpenMode::ReadWrite) - ? true - : false; + m_EngineType.empty() && (openMode == Mode::Read) ? true : false; if (isDefaultWriter || m_EngineType == "BPFileWriter") { @@ -226,8 +220,7 @@ std::shared_ptr<Engine> IO::Open(const std::string &name, } else if (isDefaultReader || m_EngineType == "BPFileReader") { - // engine = std::make_shared<BPFileReader>(*this, name, openMode, - // mpiComm); + engine = std::make_shared<BPFileReader>(*this, name, openMode, mpiComm); } else if (m_EngineType == "DataManWriter") { @@ -291,7 +284,8 @@ std::shared_ptr<Engine> IO::Open(const std::string &name, } else if (m_EngineType == "PluginEngine") { - engine = std::make_shared<PluginEngine>(*this, name, openMode, mpiComm); + // engine = std::make_shared<PluginEngine>(*this, name, openMode, + // mpiComm); } else { @@ -304,11 +298,22 @@ std::shared_ptr<Engine> IO::Open(const std::string &name, } } - return engine; + auto itEngine = m_Engines.emplace(name, std::move(engine)); + + if (m_DebugMode) + { + if (!itEngine.second) + { + throw std::invalid_argument( + "ERROR: engine of type " + m_EngineType + " and name " + name + + " could not be created, in call to Open\n"); + } + } + // return a reference + return *itEngine.first->second.get(); } -std::shared_ptr<Engine> IO::Open(const std::string &name, - const OpenMode openMode) +Engine &IO::Open(const std::string &name, const Mode openMode) { return Open(name, openMode, m_MPIComm); } diff --git a/source/adios2/core/IO.h b/source/adios2/core/IO.h index f29191dac387e7d9b97b44d9ee8b8b5d3cca1ce1..1e58801725c60281df64c2d0aef93d16db31e112 100644 --- a/source/adios2/core/IO.h +++ b/source/adios2/core/IO.h @@ -14,8 +14,8 @@ /// \cond EXCLUDE_FROM_DOXYGEN #include <map> #include <memory> //std:shared_ptr -#include <set> #include <string> +#include <unordered_set> #include <utility> //std::pair #include <vector> /// \endcond @@ -260,8 +260,8 @@ public: * @param mpiComm assigns a new communicator to the Engine * @return a smart pointer to a derived object of the Engine class */ - std::shared_ptr<Engine> Open(const std::string &name, - const OpenMode openMode, MPI_Comm mpiComm); + Engine &Open(const std::string &name, const Mode openMode, + MPI_Comm mpiComm); /** * Overloaded version that reuses the MPI_Comm object passed @@ -271,8 +271,7 @@ public: * @param openMode write, read, append from ADIOSTypes.h OpenMode * @return a smart pointer to a derived object of the Engine class */ - std::shared_ptr<Engine> Open(const std::string &name, - const OpenMode openMode); + Engine &Open(const std::string &name, const Mode openMode); // READ FUNCTIONS: void SetReadMultiplexPattern(const ReadMultiplexPattern pattern); @@ -354,6 +353,8 @@ private: template <class T> std::map<unsigned int, Attribute<T>> &GetAttributeMap(); + std::map<std::string, std::shared_ptr<Engine>> m_Engines; + /** * Gets map index for Variables or Attributes * @param name @@ -368,8 +369,6 @@ private: * signatures */ void CheckAttributeCommon(const std::string &name) const; - std::set<std::string> m_EngineNames; - /** * Checks if iterator points to end. Used for Variables and Attributes. * @param itDataMap iterator to be tested diff --git a/source/adios2/core/Selection.cpp b/source/adios2/core/Selection.cpp deleted file mode 100644 index c531a823a307cb6213fb42139a54083939ee2196..0000000000000000000000000000000000000000 --- a/source/adios2/core/Selection.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * Selection.cpp - * - * Created on: May 19, 2017 - * Author: Norbert Podhorszki pnorbert@ornl.gov - * William F Godoy godoywf@ornl.gov - */ - -#include "Selection.h" - -namespace adios2 -{ - -Selection::Selection(const SelectionType type, const bool debugMode) -: m_Type(type), m_DebugMode(debugMode) -{ -} - -} // end namespace adios diff --git a/source/adios2/core/Selection.h b/source/adios2/core/Selection.h deleted file mode 100644 index cb7e915d19464d81f4cabfbd7c26f8d95d3119dc..0000000000000000000000000000000000000000 --- a/source/adios2/core/Selection.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * Created on: May 17, 2017 - * Author: Norbert Podhorszki pnorbert@ornl.gov - * William F Godoy godoywf@ornl.gov - */ - -/* - * Selection API in C++ - * - * A SELECTION is the data ranges resulting from a QUERY over a file and - * variable(s). - * - * A SELECTION can be a list of bounding boxes and point-sets. Other data - * structures - * are not supported. Any query will result in such a selection. - * Other selections are the write-block and auto. - * - * Write block is a block of data written - * by a writer process, it is identified by an index. If each writer outputs - * one block - * then the index equals to the rank of the write process. With multi-var - * writing and - * multiple steps in a file, index runs from 0 as rank 0 process' first block. - * - * Auto selection lets the read method to automatically choose what to return. - * It will - * be a block / blocks of selected writers. - * - * If a query is a simple bounding box, the selection is the bounding box - * itself, so - * the application does not need to retrieve the selection to work on the read - * data. - */ - -#ifndef ADIOS2_CORE_SELECTION_H_ -#define ADIOS2_CORE_SELECTION_H_ - -#include "adios2/ADIOSConfig.h" -#include "adios2/ADIOSTypes.h" - -namespace adios2 -{ -/** Base class for Selection (query) types */ -class Selection -{ -public: - /** from derived class */ - const SelectionType m_Type; - - /** - * Unique constructor - * @param type derived class type - */ - Selection(const SelectionType type, const bool debugMode = false); - - virtual ~Selection() = default; - -protected: - /** true: extra checks (recommended) */ - const bool m_DebugMode; -}; - -} // namespace adios - -#endif /* ADIOS2_CORE_SELECTION_H_ */ diff --git a/source/adios2/core/SelectionBoundingBox.cpp b/source/adios2/core/SelectionBoundingBox.cpp deleted file mode 100644 index 8af89532538bab99d90f683f38fc9997b57a84d2..0000000000000000000000000000000000000000 --- a/source/adios2/core/SelectionBoundingBox.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * SelectionBoundingBox.cpp - * - * Created on: May 17, 2017 - * Author: Norbert Podhorszki pnorbert@ornl.gov - * William F Godoy godoywf@ornl.gov - * - */ - -#include "SelectionBoundingBox.h" - -/// \cond EXCLUDE_FROM_DOXYGEN -#include <stdexcept> -/// \endcond - -#include "adios2/helper/adiosFunctions.h" //Uint64VectorToSizetVector - -namespace adios2 -{ - -SelectionBoundingBox::SelectionBoundingBox(const Dims start, const Dims count, - const bool debugMode) -: Selection(SelectionType::BoundingBox, debugMode), m_Start(start), - m_Count(count) -{ - if (m_DebugMode) - { - CheckBoundingBox(); - } -} - -void SelectionBoundingBox::CheckBoundingBox() const -{ - - auto lf_Throw = [](const std::string &message) { - throw std::invalid_argument( - "ERROR: " + message + - ", in call to SelectionBoundingBox constructor\n"); - }; - - if (m_Start.size() != m_Count.size()) - { - lf_Throw("start and count must have the same size"); - } - - if (m_Start.empty()) - { - lf_Throw("start is empty"); - } - - if (m_Count.empty()) - { - lf_Throw("count is empty"); - } -} - -} // end namespace adios diff --git a/source/adios2/core/SelectionBoundingBox.h b/source/adios2/core/SelectionBoundingBox.h deleted file mode 100644 index b59b3d8aa1544610d05aa99b8f31b502009394c4..0000000000000000000000000000000000000000 --- a/source/adios2/core/SelectionBoundingBox.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * SelectionBoundingBox.h - * - * Created on: May 17, 2017 - * Author: Norbert Podhorszki pnorbert@ornl.gov - * William F Godoy godoywf@ornl.gov - */ - -#ifndef ADIOS2_CORE_SELECTIONBOUNDINGBOX_H_ -#define ADIOS2_CORE_SELECTIONBOUNDINGBOX_H_ - -/// \cond EXCLUDE_FROM_DOXYGEN -#include <vector> -/// \endcond - -#include "adios2/ADIOSConfig.h" -#include "adios2/core/Selection.h" - -namespace adios2 -{ - -/** Bounding box selection to read a subset of a non-scalar variable. - * @param start array of offsets to start reading in each dimension - * @param count number of data elements to read in each dimension - */ -class SelectionBoundingBox : public Selection -{ -public: - /** Starting coodinates of bounding box */ - Dims m_Start; - /** From start of bounding box */ - Dims m_Count; - - /** - * Constructor using uint64_t vectors - * @param start of bounding box - * @param count from start of bounding box - */ - // SelectionBoundingBox(const std::vector<uint64_t> start, - // const std::vector<uint64_t> count, - // const bool debugMode = false); - - /** - * Constructor using size_t vectors - * @param start of bounding box - * @param count from start of bounding box - */ - SelectionBoundingBox(const Dims start, const Dims count, - const bool debugMode = false); - - ~SelectionBoundingBox() = default; - -private: - /** Check in debug mode to make sure bounding box is valid */ - void CheckBoundingBox() const; -}; - -} // end namespace adios - -#endif /* ADIOS2_CORE_SELECTIONBOUNDINGBOX_H_ */ diff --git a/source/adios2/core/SelectionPoints.cpp b/source/adios2/core/SelectionPoints.cpp deleted file mode 100644 index 271d5256de9c62004ff42cbeb6ada3a2638c997a..0000000000000000000000000000000000000000 --- a/source/adios2/core/SelectionPoints.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * SelectionPoints.cpp - * - * Created on: May 17, 2017 - * Author: Norbert Podhorszki pnorbert@ornl.gov - * William F Godoy godoywf@ornl.gov - */ - -#include "SelectionPoints.h" - -namespace adios2 -{ - -SelectionPoints::SelectionPoints(size_t dimensionsSize, - std::vector<uint64_t> &points) -: Selection(SelectionType::Points), m_DimensionsSize(dimensionsSize), - m_PointsVec(&points), m_PointsSize(points.size()) -{ -} - -SelectionPoints::SelectionPoints(size_t dimensionsSize, size_t pointsSize, - uint64_t *points) -: Selection(SelectionType::Points), m_DimensionsSize(dimensionsSize), - m_PointsSize(pointsSize), m_PointsPointer(points) -{ -} - -} // end namespace adios diff --git a/source/adios2/core/SelectionPoints.h b/source/adios2/core/SelectionPoints.h deleted file mode 100644 index 04999ac994d7fa888b7a2def2271ac76ee052a8e..0000000000000000000000000000000000000000 --- a/source/adios2/core/SelectionPoints.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * SelectionPoints.h - * - * Created on: May 17, 2017 - * Author: Norbert Podhorszki pnorbert@ornl.gov - * William F Godoy godoywf@ornl.gov - */ - -#ifndef ADIOS2_CORE_SELECTIONPOINTS_H_ -#define ADIOS2_CORE_SELECTIONPOINTS_H_ - -/// \cond EXCLUDE_FROM_DOXYGEN -#include <vector> -/// \endcond - -#include "adios2/ADIOSConfig.h" -#include "adios2/ADIOSTypes.h" -#include "adios2/core/Selection.h" - -namespace adios2 -{ - -/** Selection for a selection of an enumeration of positions. - * @param ndim Number of dimensions - * @param npoints Number of points of the selection - * @param points 1D array of indices, compacted for all dimension - * (e.g. [i1,j1,k1,i2,j2,k2,...,in,jn,kn] for - * n points in a 3D space. - */ -class SelectionPoints : public Selection -{ -public: - /** number of dimensions from constructor */ - const size_t m_DimensionsSize; - - /** reference to points in constructor, must use a pointer as nullptr is - * valid if an array is passed in the constructor instead */ - std::vector<uint64_t> *m_PointsVec = nullptr; - - /** pointer based applications needed size*/ - const size_t m_PointsSize; - /** pointer based applications needed array*/ - uint64_t *m_PointsPointer = nullptr; - - /** - * Constructor that takes a vector<uint64_t> for points - * @param dimensionsSize - * @param pointsSize - * @param points - */ - SelectionPoints(size_t dimensionsSize, std::vector<uint64_t> &points); - - SelectionPoints(size_t dimensionsSize, size_t pointsSize, uint64_t *points); - - virtual ~SelectionPoints() = default; -}; - -} // end namespace adios - -#endif /* ADIOS2_CORE_SELECTIONPOINTS_H_ */ diff --git a/source/adios2/core/Variable.h b/source/adios2/core/Variable.h index dbf5ec2dc00f5754d098f8ef79c8cee44f971b3f..3ec670583695f7dabaa51cae60245f435e6f6b9c 100644 --- a/source/adios2/core/Variable.h +++ b/source/adios2/core/Variable.h @@ -53,8 +53,6 @@ public: const bool debugMode); ~Variable<T>() = default; - - void ApplyTransforms() final; }; } // end namespace adios2 diff --git a/source/adios2/core/Variable.tcc b/source/adios2/core/Variable.tcc index 0de077a2e58fc3dd66314eca48143213f82c335d..0680a34c2c1c58d1c0adaa3205014de27422a362 100644 --- a/source/adios2/core/Variable.tcc +++ b/source/adios2/core/Variable.tcc @@ -28,11 +28,6 @@ namespace adios2 : VariableBase(name, GetType<T>(), sizeof(T), shape, start, count, \ constantDims, debugMode) \ { \ - } \ - \ - template <> \ - void Variable<T>::ApplyTransforms() \ - { \ } ADIOS2_FOREACH_TYPE_1ARG(declare_type) diff --git a/source/adios2/core/VariableBase.cpp b/source/adios2/core/VariableBase.cpp index 775944e0a775fb2f0ff635c36b50ec790cdf54f0..5313929b7214eef6cf604eae97624a3e29cacae6 100644 --- a/source/adios2/core/VariableBase.cpp +++ b/source/adios2/core/VariableBase.cpp @@ -41,8 +41,12 @@ size_t VariableBase::TotalSize() const noexcept return GetTotalSize(m_Count); } -void VariableBase::SetSelection(const Dims &start, const Dims &count) +void VariableBase::SetSelection(const std::pair<Dims, Dims> &boxDims, + const std::pair<size_t, size_t> &boxSteps) { + const Dims &start = boxDims.first; + const Dims &count = boxDims.second; + if (m_DebugMode) { if (m_SingleValue) @@ -82,17 +86,16 @@ void VariableBase::SetSelection(const Dims &start, const Dims &count) } } - m_Count = count; m_Start = start; + m_Count = count; + SetStepSelection(boxSteps); } -void VariableBase::SetSelection(const SelectionBoundingBox &selection) +void VariableBase::SetMemorySelection(const std::pair<Dims, Dims> &boxDims) { - SetSelection(selection.m_Start, selection.m_Count); -} + const Dims &start = boxDims.first; + const Dims &count = boxDims.second; -void VariableBase::SetMemorySelection(const SelectionBoundingBox &selection) -{ if (m_DebugMode) { if (m_SingleValue) @@ -102,26 +105,35 @@ void VariableBase::SetMemorySelection(const SelectionBoundingBox &selection) m_Name + ", in call to SetMemorySelection\n"); } - if (m_Shape.size() != selection.m_Count.size() || - m_Shape.size() != selection.m_Start.size()) + + if (m_Shape.size() != start.size() || m_Shape.size() != count.size()) { throw std::invalid_argument( - "ERROR: selection argument m_Count and m_Start sizes must be " - "the " - "same as variable " + + "ERROR: selection Dims start, count sizes must be " + "the same as variable " + m_Name + " m_Shape, in call to SetMemorySelction\n"); } } - m_MemoryCount = selection.m_Count; - m_MemoryStart = selection.m_Start; + m_MemoryStart = start; + m_MemoryCount = count; } -void VariableBase::SetStepSelection(const unsigned int startStep, - const unsigned int countStep) +size_t VariableBase::GetAvailableStepsStart() { return m_AvailableStepsStart; } +size_t VariableBase::GetAvailableStepsCount() { return m_AvailableStepsCount; } + +void VariableBase::SetStepSelection(const std::pair<size_t, size_t> &boxSteps) { - m_ReadFromStep = startStep; - m_ReadNSteps = countStep; + if (boxSteps.second == 0) + { + throw std::invalid_argument("ERROR: boxSteps.second count argument " + " can't be zero, from variable " + + m_Name + + ", in call to Setting Step Selection\n"); + } + + m_StepStart = boxSteps.first; + m_StepCount = boxSteps.second; } // transforms related functions @@ -232,7 +244,7 @@ void VariableBase::InitShapeType() m_Name + "\n"); } } - else //(m_Shape.empty()) + else { if (m_Start.empty()) { @@ -258,7 +270,9 @@ void VariableBase::InitShapeType() /* Extra checks for invalid settings */ if (m_DebugMode) + { CheckDimsCommon("DefineVariable(" + m_Name + ")"); + } } void VariableBase::CheckDimsCommon(const std::string hint) const @@ -311,4 +325,4 @@ void VariableBase::CheckDimsBeforeWrite(const std::string hint) const // TODO need to think more exceptions here } -} // end namespace adios +} // end namespace adios2 diff --git a/source/adios2/core/VariableBase.h b/source/adios2/core/VariableBase.h index f169a3299d8251eda7f6d599e6ec2b042673c15d..2acecc7edbcb4843f90364760faea7b0bbfd9993 100644 --- a/source/adios2/core/VariableBase.h +++ b/source/adios2/core/VariableBase.h @@ -20,7 +20,6 @@ #include "adios2/ADIOSConfig.h" #include "adios2/ADIOSTypes.h" -#include "adios2/core/SelectionBoundingBox.h" #include "adios2/core/Transform.h" namespace adios2 @@ -47,20 +46,24 @@ public: Dims m_Start; ///< starting point (offsets) in global shape Dims m_Count; ///< dimensions from m_Start in global shape - Dims m_MemoryStart; ///< offset of memory selection - Dims m_MemoryCount; ///< subset of m_Shape (e.g. remove ghost points) - - /** Read from this step (must be 0 in staging) */ - unsigned int m_ReadFromStep = 0; - /** Read this many steps at once (must be 1 in staging) */ - unsigned int m_ReadNSteps = 1; /** Global array was written as Joined array, so read accordingly */ bool m_ReadAsJoined = false; /** Global array was written as Local value, so read accordingly */ bool m_ReadAsLocalValue = false; - /** number of steps available in a file (or 1 in staging) filled by - * InquireVariable*/ - unsigned int m_AvailableSteps = 1; + + /** Transforms metadata info */ + struct TransformInfo + { + /** reference to object derived from Transform class */ + Transform &Operator; + /** parameters from AddTransform */ + Params Parameters; + /** resulting sizes from transformation */ + Dims Sizes; + }; + + /** Registered transforms */ + std::vector<TransformInfo> m_TransformsInfo; VariableBase(const std::string &name, const std::string type, const size_t elementSize, const Dims &shape, const Dims &start, @@ -81,29 +84,28 @@ public: */ size_t TotalSize() const noexcept; - /** Set the local dimension and global offset of the variable */ - void SetSelection(const Dims &start, const Dims &count); + /** Set Dims and Time start and count */ + void SetSelection(const std::pair<Dims, Dims> &boxDims, + const std::pair<size_t, size_t> &boxSteps = + std::pair<size_t, size_t>(0, 1)); - /** Overloaded version of SetSelection using a SelectionBoundingBox */ - void SetSelection(const SelectionBoundingBox &selection); + /** + * Set the steps for the variable. The pointer passed at + * reading must be able to hold enough memory to store multiple steps in a + * single read. For writing it changes the time step + * @param boxSteps {startStep, countStep} + */ + void SetStepSelection(const std::pair<size_t, size_t> &boxSteps); /** * Set the local dimension and global offset of the variable using a * selection * Only bounding boxes are allowed */ - void SetMemorySelection(const SelectionBoundingBox &selection); + void SetMemorySelection(const std::pair<Dims, Dims> &boxDims); - /** - * Set the steps for the variable to read from. The pointer passed at - * reading must be able to hold enough memory to store multiple steps in a - * single read. - * @param startStep The first step to read. Steps start from 0 - * @param countStep Number of consecutive steps to read at once. - * - */ - void SetStepSelection(const unsigned int startStep, - const unsigned int countStep); + size_t GetAvailableStepsStart(); + size_t GetAvailableStepsCount(); /** * Pushed a new transform to a sequence of transports @@ -120,28 +122,6 @@ public: /** Clears out the transform sequence defined by AddTransform */ void ClearTransforms() noexcept; - /** Apply current sequence of transforms defined by AddTransform */ - virtual void ApplyTransforms() = 0; - - /** Transforms metadata info */ - struct TransformInfo - { - /** reference to object derived from Transform class */ - Transform &Operator; - /** parameters from AddTransform */ - Params Parameters; - /** resulting sizes from transformation */ - Dims Sizes; - }; - - /** Registered transforms */ - std::vector<TransformInfo> m_TransformsInfo; - - /** Self-check dims according to type, called right after DefineVariable and - * SetSelection. - * @param hint extra debugging info for the exception */ - void CheckDimsCommon(const std::string hint) const; - /** Self-check dims according to type, called from Engine before Write * @param hint extra debugging info for the exception */ void CheckDimsBeforeWrite(const std::string hint) const; @@ -149,9 +129,23 @@ public: private: const bool m_DebugMode = false; + Dims m_MemoryStart; ///< offset of memory selection + Dims m_MemoryCount; ///< subset of m_Shape (e.g. remove ghost points) + + size_t m_StepStart = 0; + size_t m_StepCount = 1; + + size_t m_AvailableStepsCount = 1; + size_t m_AvailableStepsStart = 0; + void InitShapeType(); + + /** Self-check dims according to type, called right after DefineVariable and + * SetSelection. + * @param hint extra debugging info for the exception */ + void CheckDimsCommon(const std::string hint) const; }; -} // end namespace +} // end namespace adios2 #endif /* ADIOS2_CORE_VARIABLEBASE_H_ */ diff --git a/source/adios2/core/VariableCompound.cpp b/source/adios2/core/VariableCompound.cpp index 8fee9b54b27b93878ec858c3fab41717249bb6bc..4a5147d2c2322ec756b3510a07ee99e8c75e3a56 100644 --- a/source/adios2/core/VariableCompound.cpp +++ b/source/adios2/core/VariableCompound.cpp @@ -26,8 +26,6 @@ VariableCompound::VariableCompound(const std::string name, { } -void VariableCompound::ApplyTransforms() {} - #define declare_template_instantiation(T) \ template void VariableCompound::InsertMember<T>(const std::string, \ const size_t); diff --git a/source/adios2/core/VariableCompound.h b/source/adios2/core/VariableCompound.h index 70494e0e6968f6ee96dbfea8a41569510e31fc43..01b50db073ce06c0756e470dc61c305e766a8489 100644 --- a/source/adios2/core/VariableCompound.h +++ b/source/adios2/core/VariableCompound.h @@ -45,8 +45,6 @@ public: ~VariableCompound() = default; - void ApplyTransforms() final; - /** * Inserts an Element into the compound struct definition * @param name diff --git a/source/adios2/core/VariableCompound.tcc b/source/adios2/core/VariableCompound.tcc index e53385ef3e546aec68ed51e9278cc75abe2860bb..c7f63c52d1de3611fa9825c8115a6b9ec894efb9 100644 --- a/source/adios2/core/VariableCompound.tcc +++ b/source/adios2/core/VariableCompound.tcc @@ -24,6 +24,6 @@ void VariableCompound::InsertMember(const std::string name, const size_t offset) m_Elements.push_back(Element{name, GetType<T>(), offset}); } -} // end namespace +} // end namespace adios2 #endif /* ADIOS2_CORE_VARIABLECOMPOUND_TCC_ */ diff --git a/source/adios2/engine/adios1/ADIOS1Reader.cpp b/source/adios2/engine/adios1/ADIOS1Reader.cpp index ee2a068e1a09ad6c46e1a3c21a41199f9005838f..05ca115bb30db2369e9581a102d86dc07ce6fb18 100644 --- a/source/adios2/engine/adios1/ADIOS1Reader.cpp +++ b/source/adios2/engine/adios1/ADIOS1Reader.cpp @@ -9,6 +9,7 @@ */ #include "ADIOS1Reader.h" +#include "ADIOS1Reader.tcc" #include <adios_error.h> @@ -18,7 +19,7 @@ namespace adios2 { ADIOS1Reader::ADIOS1Reader(IO &io, const std::string &name, - const OpenMode openMode, MPI_Comm mpiComm) + const Mode openMode, MPI_Comm mpiComm) : Engine("ADIOS1Reader", io, name, openMode, mpiComm) { m_EndMessage = " in call to IO Open ADIOS1Reader " + m_Name + "\n"; @@ -39,137 +40,13 @@ ADIOS1Reader::ADIOS1Reader(IO &io, const std::string &name, ADIOS1Reader::~ADIOS1Reader() { if (m_fh != nullptr) + { adios_read_close(m_fh); + } adios_read_finalize_method(m_ReadMethod); } // PRIVATE -VariableBase * -ADIOS1Reader::InquireVariableUnknown(const std::string &variableName, - const bool readIn) -{ - return nullptr; // not yet implemented -} - -Variable<char> * -ADIOS1Reader::InquireVariableChar(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<char>(variableName, readIn); -} - -Variable<unsigned char> * -ADIOS1Reader::InquireVariableUChar(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<unsigned char>(variableName, readIn); -} - -Variable<short> * -ADIOS1Reader::InquireVariableShort(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<short>(variableName, readIn); -} - -Variable<unsigned short> * -ADIOS1Reader::InquireVariableUShort(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<unsigned short>(variableName, readIn); -} - -Variable<int> *ADIOS1Reader::InquireVariableInt(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<int>(variableName, readIn); -} - -Variable<unsigned int> * -ADIOS1Reader::InquireVariableUInt(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<unsigned int>(variableName, readIn); -} - -Variable<long int> * -ADIOS1Reader::InquireVariableLInt(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<long int>(variableName, readIn); -} - -Variable<unsigned long int> * -ADIOS1Reader::InquireVariableULInt(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<unsigned long int>(variableName, readIn); -} - -Variable<long long int> * -ADIOS1Reader::InquireVariableLLInt(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<long long int>(variableName, readIn); -} - -Variable<unsigned long long int> * -ADIOS1Reader::InquireVariableULLInt(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<unsigned long long int>(variableName, readIn); -} - -Variable<float> * -ADIOS1Reader::InquireVariableFloat(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<float>(variableName, readIn); -} - -Variable<double> * -ADIOS1Reader::InquireVariableDouble(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<double>(variableName, readIn); -} - -Variable<long double> * -ADIOS1Reader::InquireVariableLDouble(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<long double>(variableName, readIn); -} - -Variable<std::complex<float>> * -ADIOS1Reader::InquireVariableCFloat(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<std::complex<float>>(variableName, readIn); -} - -Variable<std::complex<double>> * -ADIOS1Reader::InquireVariableCDouble(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<std::complex<double>>(variableName, readIn); -} - -Variable<std::complex<long double>> * -ADIOS1Reader::InquireVariableCLDouble(const std::string &variableName, - const bool readIn) -{ - return InquireVariableCommon<std::complex<long double>>(variableName, - readIn); -} - -VariableCompound * -ADIOS1Reader::InquireVariableCompound(const std::string &variableName, - const bool readIn) -{ - return nullptr; -} - void ADIOS1Reader::ScheduleReadCommon(const std::string &name, const Dims &offs, const Dims &ldims, const int fromStep, const int nSteps, @@ -299,7 +176,7 @@ void ADIOS1Reader::Init() { if (m_DebugMode) { - if (m_OpenMode != OpenMode::Read) + if (m_OpenMode != Mode::Read) { throw std::invalid_argument( "ERROR: ADIOS1Reader only supports OpenMode::r (read) access " diff --git a/source/adios2/engine/adios1/ADIOS1Reader.h b/source/adios2/engine/adios1/ADIOS1Reader.h index cf6f4606f8c48beaf66ef4f1b6e519056a7f3cd4..db9dd1c315c534b2589a4f1b6d64f71a2b3412c4 100644 --- a/source/adios2/engine/adios1/ADIOS1Reader.h +++ b/source/adios2/engine/adios1/ADIOS1Reader.h @@ -13,8 +13,6 @@ #ifndef ADIOS2_ENGINE_ADIOS1_ADIOS1READER_H_ #define ADIOS2_ENGINE_ADIOS1_ADIOS1READER_H_ -#include <iostream> //this must go away - #include "adios2/ADIOSConfig.h" #include "adios2/core/ADIOS.h" #include "adios2/core/Engine.h" @@ -49,7 +47,7 @@ public: * @param debugMode * @param hostLanguage */ - ADIOS1Reader(IO &adios, const std::string &name, const OpenMode openMode, + ADIOS1Reader(IO &adios, const std::string &name, const Mode openMode, MPI_Comm mpiComm); ~ADIOS1Reader(); @@ -74,48 +72,19 @@ private: void InitParameters() final; void InitTransports() final; - VariableBase *InquireVariableUnknown(const std::string &name, - const bool readIn) final; - Variable<char> *InquireVariableChar(const std::string &name, - const bool readIn) final; - Variable<unsigned char> *InquireVariableUChar(const std::string &name, - const bool readIn) final; - Variable<short> *InquireVariableShort(const std::string &name, - const bool readIn) final; - Variable<unsigned short> *InquireVariableUShort(const std::string &name, - const bool readIn) final; - Variable<int> *InquireVariableInt(const std::string &name, - const bool readIn) final; - Variable<unsigned int> *InquireVariableUInt(const std::string &name, - const bool readIn) final; - Variable<long int> *InquireVariableLInt(const std::string &name, - const bool readIn) final; - Variable<unsigned long int> *InquireVariableULInt(const std::string &name, - const bool readIn) final; - Variable<long long int> *InquireVariableLLInt(const std::string &name, - const bool readIn) final; - Variable<unsigned long long int> * - InquireVariableULLInt(const std::string &name, const bool readIn) final; - - Variable<float> *InquireVariableFloat(const std::string &name, - const bool readIn) final; - Variable<double> *InquireVariableDouble(const std::string &name, - const bool readIn) final; - Variable<long double> *InquireVariableLDouble(const std::string &name, - const bool readIn) final; - Variable<cfloat> *InquireVariableCFloat(const std::string &name, - const bool readIn) final; - Variable<cdouble> *InquireVariableCDouble(const std::string &name, - const bool readIn) final; - Variable<cldouble> *InquireVariableCLDouble(const std::string &name, - const bool readIn) final; +#define declare(T, L) \ + virtual Variable<T> *DoInquireVariable##L(const std::string &variableName) \ + final; + + ADIOS2_FOREACH_TYPE_2ARGS(declare) +#undef declare + /** Not yet implemented */ VariableCompound *InquireVariableCompound(const std::string &name, const bool readIn); template <class T> - Variable<T> *InquireVariableCommon(const std::string &name, - const bool readIn); + Variable<T> *InquireVariableCommon(const std::string &name); #define declare_type(T) \ void DoScheduleRead(Variable<T> &variable, const T *values) final; \ diff --git a/source/adios2/engine/adios1/ADIOS1Reader.inl b/source/adios2/engine/adios1/ADIOS1Reader.inl index d89062cbc0c48d49d1527d4079e28e455199e31f..70fdc27d87bdfc94ac69e1febf325da95400b626 100644 --- a/source/adios2/engine/adios1/ADIOS1Reader.inl +++ b/source/adios2/engine/adios1/ADIOS1Reader.inl @@ -18,19 +18,20 @@ namespace adios2 { template <class T> -Variable<T> *ADIOS1Reader::InquireVariableCommon(const std::string &name, - const bool readIn) +Variable<T> * +ADIOS1Reader::InquireVariableCommon(const std::string &variableName) { // here read variable metadata (dimensions, type, etc.)...then create a // Variable like below: // Variable<T>& variable = m_ADIOS.DefineVariable<T>( m_Name + "/" + // name, ) // return &variable; //return address if success - ADIOS_VARINFO *vi = adios_inq_var(m_fh, name.c_str()); + ADIOS_VARINFO *vi = adios_inq_var(m_fh, variableName.c_str()); adios2::Variable<T> *var = nullptr; if (vi != nullptr) { - CheckADIOS1TypeCompatibility(name, GetType<T>(), vi->type); // throws + CheckADIOS1TypeCompatibility(variableName, GetType<T>(), + vi->type); // throws if (vi->ndim > 0) { @@ -72,7 +73,7 @@ Variable<T> *ADIOS1Reader::InquireVariableCommon(const std::string &name, } } } - var = &m_IO.DefineVariable<T>(name, gdims); + var = &m_IO.DefineVariable<T>(variableName, gdims); if (joinedread) { var->m_ReadAsJoined = true; @@ -81,7 +82,7 @@ Variable<T> *ADIOS1Reader::InquireVariableCommon(const std::string &name, else /* Scalars */ { /* scalar variable but global value or local value*/ - std::string aname = name + "/ReadAsArray"; + std::string aname = variableName + "/ReadAsArray"; bool isLocalValue = false; for (int i = 0; i < vi->nattrs; ++i) { @@ -102,19 +103,19 @@ Variable<T> *ADIOS1Reader::InquireVariableCommon(const std::string &name, } if (changingDims) { - var = &m_IO.DefineVariable<T>(name, {IrregularDim}); + var = &m_IO.DefineVariable<T>(variableName, {IrregularDim}); } else { var = &m_IO.DefineVariable<T>( - name, {(unsigned int)vi->nblocks[0]}); + variableName, {(unsigned int)vi->nblocks[0]}); } var->m_ReadAsLocalValue = true; } else { /* Global value: store only one value */ - var = &m_IO.DefineVariable<T>(name); + var = &m_IO.DefineVariable<T>(variableName); if (var) { var->m_Data = std::vector<T>(1); @@ -128,6 +129,6 @@ Variable<T> *ADIOS1Reader::InquireVariableCommon(const std::string &name, return var; } -} // end namespace adios +} // end namespace adios2 #endif /* ADIOS2_ENGINE_ADIOS1_ADIOS1READER_INL_ */ diff --git a/source/adios2/engine/adios1/ADIOS1Reader.tcc b/source/adios2/engine/adios1/ADIOS1Reader.tcc new file mode 100644 index 0000000000000000000000000000000000000000..64eca75dc10842d60bd9fa1665fec170d2d2a7aa --- /dev/null +++ b/source/adios2/engine/adios1/ADIOS1Reader.tcc @@ -0,0 +1,29 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * ADIOS1Reader.tcc + * + * Created on: Sep 20, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef ADIOS2_ENGINE_ADIOS1_ADIOS1READER_TCC_ +#define ADIOS2_ENGINE_ADIOS1_ADIOS1READER_TCC_ + +#include "ADIOS1Reader.h" + +namespace adios2 +{ + +#define declare(T, L) \ + Variable<T> *ADIOS1Reader::DoInquireVariable##L( \ + const std::string &variableName) \ + { \ + return InquireVariableCommon<T>(variableName); \ + } + +ADIOS2_FOREACH_TYPE_2ARGS(declare) +#undef declare + +} // end namespace adios2 diff --git a/source/adios2/engine/adios1/ADIOS1Writer.cpp b/source/adios2/engine/adios1/ADIOS1Writer.cpp index dd1470e7aa8bd27a04f44431e32f26dd560fb59d..b7ed3c3024f773ed83b5f00e01431a0c242115fe 100644 --- a/source/adios2/engine/adios1/ADIOS1Writer.cpp +++ b/source/adios2/engine/adios1/ADIOS1Writer.cpp @@ -23,7 +23,7 @@ namespace adios2 { ADIOS1Writer::ADIOS1Writer(IO &io, const std::string &name, - const OpenMode openMode, MPI_Comm mpiComm) + const Mode openMode, MPI_Comm mpiComm) : Engine("ADIOS1Writer", io, name, openMode, mpiComm), m_ADIOS1(io.m_Name, name, mpiComm, io.m_DebugMode) { diff --git a/source/adios2/engine/adios1/ADIOS1Writer.h b/source/adios2/engine/adios1/ADIOS1Writer.h index 7fd895a686f6bb0e7b2dab2c39d1544f18421453..9f4a8e30d86a2c761e222006b74cf73e0d67439e 100644 --- a/source/adios2/engine/adios1/ADIOS1Writer.h +++ b/source/adios2/engine/adios1/ADIOS1Writer.h @@ -32,7 +32,7 @@ public: * @param method * @param debugMode */ - ADIOS1Writer(IO &adios, const std::string &name, const OpenMode openMode, + ADIOS1Writer(IO &adios, const std::string &name, const Mode openMode, MPI_Comm mpiComm); ~ADIOS1Writer() = default; diff --git a/source/adios2/engine/bp/BPFileReader.cpp b/source/adios2/engine/bp/BPFileReader.cpp index 8d5897340aeeb4a321e4b5f1f6b3faa4dd47e5a9..d48e4ed631f7fe961bbdb560a6f9dce3766d41aa 100644 --- a/source/adios2/engine/bp/BPFileReader.cpp +++ b/source/adios2/engine/bp/BPFileReader.cpp @@ -9,15 +9,15 @@ */ #include "BPFileReader.h" - -#include "adios2/helper/adiosFunctions.h" // CSVToVector +#include "BPFileReader.tcc" namespace adios2 { -BPFileReader::BPFileReader(IO &io, const std::string &name, - const OpenMode openMode, MPI_Comm mpiComm) -: Engine("BPFileReader", io, name, openMode, mpiComm) +BPFileReader::BPFileReader(IO &io, const std::string &name, const Mode openMode, + MPI_Comm mpiComm) +: Engine("BPFileReader", io, name, openMode, mpiComm), + m_BP1Reader(mpiComm, m_DebugMode), m_FileManager(mpiComm, m_DebugMode) { Init(); } @@ -29,128 +29,43 @@ void BPFileReader::Init() { if (m_DebugMode) { - if (m_OpenMode != OpenMode::Read) + if (m_OpenMode != Mode::Read) { throw std::invalid_argument( - "ERROR: BPFileReader only supports OpenMode::r from" + m_Name + - " " + m_EndMessage); + "ERROR: BPFileReader only supports OpenMode::Read from" + + m_Name + " " + m_EndMessage); } } InitTransports(); + InitBuffers(); } -void BPFileReader::InitTransports() {} - -VariableBase *BPFileReader::InquireVariableUnknown(const std::string & /*name*/, - const bool /*readIn*/) -{ - // not yet implemented - return nullptr; -} - -Variable<char> *BPFileReader::InquireVariableChar(const std::string &name, - const bool readIn) -{ - return InquireVariableCommon<char>(name, readIn); -} - -Variable<unsigned char> * -BPFileReader::InquireVariableUChar(const std::string &name, const bool readIn) -{ - return InquireVariableCommon<unsigned char>(name, readIn); -} - -Variable<short> *BPFileReader::InquireVariableShort(const std::string &name, - const bool readIn) -{ - return InquireVariableCommon<short>(name, readIn); -} - -Variable<unsigned short> * -BPFileReader::InquireVariableUShort(const std::string &name, const bool readIn) -{ - return InquireVariableCommon<unsigned short>(name, readIn); -} - -Variable<int> *BPFileReader::InquireVariableInt(const std::string &name, - const bool readIn) -{ - return InquireVariableCommon<int>(name, readIn); -} - -Variable<unsigned int> * -BPFileReader::InquireVariableUInt(const std::string &name, const bool readIn) -{ - return InquireVariableCommon<unsigned int>(name, readIn); -} - -Variable<long int> *BPFileReader::InquireVariableLInt(const std::string &name, - const bool readIn) -{ - return InquireVariableCommon<long int>(name, readIn); -} - -Variable<unsigned long int> * -BPFileReader::InquireVariableULInt(const std::string &name, const bool readIn) -{ - return InquireVariableCommon<unsigned long int>(name, readIn); -} - -Variable<long long int> * -BPFileReader::InquireVariableLLInt(const std::string &name, const bool readIn) -{ - return InquireVariableCommon<long long int>(name, readIn); -} - -Variable<unsigned long long int> * -BPFileReader::InquireVariableULLInt(const std::string &name, const bool readIn) -{ - return InquireVariableCommon<unsigned long long int>(name, readIn); -} - -Variable<float> *BPFileReader::InquireVariableFloat(const std::string &name, - const bool readIn) -{ - return InquireVariableCommon<float>(name, readIn); -} - -Variable<double> *BPFileReader::InquireVariableDouble(const std::string &name, - const bool readIn) +void BPFileReader::InitTransports() { - return InquireVariableCommon<double>(name, readIn); + // for now just use the name + // const std::string + // metadataFile(m_BP1Reader.GetBPMetadataFileName(m_Name)); + // m_FileManager.OpenFileTransport(metadataFile, adios2::Mode::Read, + // Params(), + // true); } -Variable<long double> * -BPFileReader::InquireVariableLDouble(const std::string &name, const bool readIn) +void BPFileReader::InitBuffers() { - return InquireVariableCommon<long double>(name, readIn); + // here read indices + // pg index + // variables index + // attributes index } -Variable<std::complex<float>> * -BPFileReader::InquireVariableCFloat(const std::string &name, const bool readIn) -{ - return InquireVariableCommon<std::complex<float>>(name, readIn); -} - -Variable<std::complex<double>> * -BPFileReader::InquireVariableCDouble(const std::string &name, const bool readIn) -{ - return InquireVariableCommon<std::complex<double>>(name, readIn); -} - -Variable<std::complex<long double>> * -BPFileReader::InquireVariableCLDouble(const std::string &name, - const bool readIn) -{ - return InquireVariableCommon<std::complex<long double>>(name, readIn); -} - -VariableCompound * -BPFileReader::InquireVariableCompound(const std::string & /*name*/, - const bool /*readIn*/) -{ - return nullptr; -} +#define declare(T, L) \ + Variable<T> *BPFileReader::DoInquireVariable##L( \ + const std::string &variableName) \ + { \ + return InquireVariableCommon<T>(variableName); \ + } +ADIOS2_FOREACH_TYPE_2ARGS(declare) +#undef declare -} // end namespace adios +} // end namespace adios2 diff --git a/source/adios2/engine/bp/BPFileReader.h b/source/adios2/engine/bp/BPFileReader.h index e1942a5421dfba2b817df55772a1455ecd44c421..8cdc15827d3dc7d37281cb4bab2fc281876593c9 100644 --- a/source/adios2/engine/bp/BPFileReader.h +++ b/source/adios2/engine/bp/BPFileReader.h @@ -13,6 +13,8 @@ #include "adios2/ADIOSConfig.h" #include "adios2/core/Engine.h" +#include "adios2/toolkit/format/bp1/BP1.h" //format::BP1Reader +#include "adios2/toolkit/transportman/TransportMan.h" namespace adios2 { @@ -22,9 +24,13 @@ class BPFileReader : public Engine public: /** - * + * Unique constructor + * @param io + * @param name + * @param openMode only read + * @param mpiComm */ - BPFileReader(IO &io, const std::string &name, const OpenMode openMode, + BPFileReader(IO &io, const std::string &name, const Mode openMode, MPI_Comm mpiComm); virtual ~BPFileReader() = default; @@ -32,94 +38,23 @@ public: void Close(const int transportIndex = -1); private: - void Init(); ///< calls InitCapsules and InitTransports based on Method, - /// called from constructor - - void InitTransports(); ///< from Transports - - VariableBase *InquireVariableUnknown(const std::string &variableName, - const bool readIn = true); - - Variable<char> *InquireVariableChar(const std::string &variableName, - const bool readIn = true); - - Variable<unsigned char> * - InquireVariableUChar(const std::string &variableName, - const bool readIn = true); - - Variable<short> *InquireVariableShort(const std::string &variableName, - const bool readIn = true); - - Variable<unsigned short> * - InquireVariableUShort(const std::string &variableName, - const bool readIn = true); - - Variable<int> *InquireVariableInt(const std::string &variableName, - const bool readIn = true); - - Variable<unsigned int> *InquireVariableUInt(const std::string &variableName, - const bool readIn = true); - - Variable<long int> *InquireVariableLInt(const std::string &variableName, - const bool readIn = true); + format::BP1Reader m_BP1Reader; + transportman::TransportMan m_FileManager; - Variable<unsigned long int> * - InquireVariableULInt(const std::string &variableName, - const bool readIn = true); + void Init(); + void InitTransports(); + void InitBuffers(); - Variable<long long int> * - InquireVariableLLInt(const std::string &variableName, - const bool readIn = true); +#define declare(T, L) \ + Variable<T> *DoInquireVariable##L(const std::string &variableName) final; - Variable<unsigned long long int> * - InquireVariableULLInt(const std::string &variableName, - const bool readIn = true); - - Variable<float> *InquireVariableFloat(const std::string &variableName, - const bool readIn = true); - - Variable<double> *InquireVariableDouble(const std::string &variableName, - const bool readIn = true); - Variable<long double> * - InquireVariableLDouble(const std::string &variableName, - const bool readIn = true); - - Variable<std::complex<float>> * - InquireVariableCFloat(const std::string &variableName, - const bool readIn = true); - - Variable<std::complex<double>> * - InquireVariableCDouble(const std::string &variableName, - const bool readIn = true); - - Variable<std::complex<long double>> * - InquireVariableCLDouble(const std::string &variableName, - const bool readIn = true); - - /** - * Not implemented - * @param name - * @param readIn - * @return - */ - VariableCompound *InquireVariableCompound(const std::string &variableName, - const bool readIn = true); + ADIOS2_FOREACH_TYPE_2ARGS(declare) +#undef declare template <class T> - Variable<T> *InquireVariableCommon(const std::string &name, - const bool readIn) - { - std::cout << "Hello BPReaderCommon\n"; - - // here read variable metadata (dimensions, type, etc.)...then create a - // Variable like below: - // Variable<T>& variable = m_ADIOS.DefineVariable<T>( m_Name + "/" + - // name, ) - // return &variable; //return address if success - return nullptr; // on failure - } + Variable<T> *InquireVariableCommon(const std::string &variableName); }; -} // end namespace adios +} // end namespace adios2 #endif /* ADIOS2_ENGINE_BP_BPFILEREADER_H_ */ diff --git a/source/adios2/engine/bp/BPFileReader.tcc b/source/adios2/engine/bp/BPFileReader.tcc new file mode 100644 index 0000000000000000000000000000000000000000..e1a6f543e920601fb5e64f70cdcb7f406b34319d --- /dev/null +++ b/source/adios2/engine/bp/BPFileReader.tcc @@ -0,0 +1,28 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * BPFileReader.tcc + * + * Created on: Feb 27, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef ADIOS2_ENGINE_BP_BPFILEREADER_TCC_ +#define ADIOS2_ENGINE_BP_BPFILEREADER_TCC_ + +#include "BPFileReader.h" + +namespace adios2 +{ + +template <class T> +Variable<T> * +BPFileReader::InquireVariableCommon(const std::string &variableName) +{ + return nullptr; +} + +} // end namespace adios2 + +#endif /* ADIOS2_ENGINE_BP_BPFILEREADER_TCC_ */ diff --git a/source/adios2/engine/bp/BPFileWriter.cpp b/source/adios2/engine/bp/BPFileWriter.cpp index 175d9975645db538748c467d26635aaeeced01d5..1b87b84ec70c19ba89d112f6be9a4ea6316901ad 100644 --- a/source/adios2/engine/bp/BPFileWriter.cpp +++ b/source/adios2/engine/bp/BPFileWriter.cpp @@ -10,20 +10,23 @@ #include "BPFileWriter.h" #include "BPFileWriter.tcc" +#include <adios2/toolkit/transport/file/FileFStream.h> + +#include <iostream> #include "adios2/ADIOSMPI.h" #include "adios2/ADIOSMacros.h" #include "adios2/core/IO.h" #include "adios2/helper/adiosFunctions.h" //CheckIndexRange -#include "adios2/toolkit/transport/file/FileStream.h" namespace adios2 { -BPFileWriter::BPFileWriter(IO &io, const std::string &name, - const OpenMode openMode, MPI_Comm mpiComm) +BPFileWriter::BPFileWriter(IO &io, const std::string &name, const Mode openMode, + MPI_Comm mpiComm) : Engine("BPFileWriter", io, name, openMode, mpiComm), - m_BP1Writer(mpiComm, m_DebugMode), m_TransportsManager(mpiComm, m_DebugMode) + m_BP1BuffersWriter(mpiComm, m_DebugMode), + m_FileManager(mpiComm, m_DebugMode) { m_EndMessage = " in call to IO Open BPFileWriter " + m_Name + "\n"; Init(); @@ -48,16 +51,16 @@ ADIOS2_FOREACH_TYPE_1ARG(declare_type) void BPFileWriter::Advance(const float /*timeout_sec*/) { - m_BP1Writer.Advance(m_IO); + m_BP1BuffersWriter.Advance(m_IO); } void BPFileWriter::Close(const int transportIndex) { if (m_DebugMode) { - if (!m_TransportsManager.CheckTransportIndex(transportIndex)) + if (!m_FileManager.CheckTransportIndex(transportIndex)) { - auto transportsSize = m_TransportsManager.m_Transports.size(); + auto transportsSize = m_FileManager.m_Transports.size(); throw std::invalid_argument( "ERROR: transport index " + std::to_string(transportIndex) + " outside range, -1 (default) to " + @@ -65,26 +68,32 @@ void BPFileWriter::Close(const int transportIndex) } } - // close bp buffer by flattening data and metadata - m_BP1Writer.Close(m_IO); + // close bp buffer by serializing data and metadata + m_BP1BuffersWriter.Close(m_IO); // send data to corresponding transports - m_TransportsManager.WriteFiles(m_BP1Writer.m_HeapBuffer.GetData(), - m_BP1Writer.m_HeapBuffer.m_DataPosition, + m_FileManager.WriteFiles(m_BP1BuffersWriter.m_Data.m_Buffer.data(), + m_BP1BuffersWriter.m_Data.m_Position, transportIndex); - m_TransportsManager.CloseFiles(transportIndex); + m_FileManager.CloseFiles(transportIndex); - if (m_BP1Writer.m_Profiler.IsActive && - m_TransportsManager.AllTransportsClosed()) + if (m_BP1BuffersWriter.m_Profiler.IsActive && + m_FileManager.AllTransportsClosed()) { WriteProfilingJSONFile(); } + + if (m_BP1BuffersWriter.m_CollectiveMetadata && + m_FileManager.AllTransportsClosed()) + { + m_BP1BuffersWriter.AggregateCollectiveMetadata(); + } } // PRIVATE FUNCTIONS void BPFileWriter::InitParameters() { - m_BP1Writer.InitParameters(m_IO.m_Parameters); + m_BP1BuffersWriter.InitParameters(m_IO.m_Parameters); } void BPFileWriter::InitTransports() @@ -98,19 +107,19 @@ void BPFileWriter::InitTransports() } // Names are std::vector<std::string> - auto transportsNames = m_TransportsManager.GetFilesBaseNames( + auto transportsNames = m_FileManager.GetFilesBaseNames( m_Name, m_IO.m_TransportsParameters); - auto bpBaseNames = m_BP1Writer.GetBPBaseNames(transportsNames); - auto bpNames = m_BP1Writer.GetBPNames(transportsNames); + auto bpBaseNames = m_BP1BuffersWriter.GetBPBaseNames(transportsNames); + auto bpNames = m_BP1BuffersWriter.GetBPNames(transportsNames); - m_TransportsManager.OpenFiles(bpBaseNames, bpNames, m_OpenMode, + m_FileManager.OpenFiles(bpBaseNames, bpNames, m_OpenMode, m_IO.m_TransportsParameters, - m_BP1Writer.m_Profiler.IsActive); + m_BP1BuffersWriter.m_Profiler.IsActive); } void BPFileWriter::InitBPBuffer() { - if (m_OpenMode == OpenMode::Append) + if (m_OpenMode == Mode::Append) { throw std::invalid_argument( "ADIOS2: OpenMode Append hasn't been implemented, yet"); @@ -118,31 +127,32 @@ void BPFileWriter::InitBPBuffer() } else { - m_BP1Writer.WriteProcessGroupIndex( - m_IO.m_HostLanguage, m_TransportsManager.GetTransportsTypes()); + m_BP1BuffersWriter.WriteProcessGroupIndex( + m_IO.m_HostLanguage, m_FileManager.GetTransportsTypes()); } } void BPFileWriter::WriteProfilingJSONFile() { - auto transportTypes = m_TransportsManager.GetTransportsTypes(); - auto transportProfilers = m_TransportsManager.GetTransportsProfilers(); + auto transportTypes = m_FileManager.GetTransportsTypes(); + auto transportProfilers = m_FileManager.GetTransportsProfilers(); - const std::string lineJSON( - m_BP1Writer.GetRankProfilingJSON(transportTypes, transportProfilers)); + const std::string lineJSON(m_BP1BuffersWriter.GetRankProfilingJSON( + transportTypes, transportProfilers) + + ",\n"); - const std::string profilingJSON( - m_BP1Writer.AggregateProfilingJSON(lineJSON)); + const std::vector<char> profilingJSON( + m_BP1BuffersWriter.AggregateProfilingJSON(lineJSON)); - if (m_BP1Writer.m_BP1Aggregator.m_RankMPI == 0) + if (m_BP1BuffersWriter.m_BP1Aggregator.m_RankMPI == 0) { - transport::FileStream profilingJSONStream(m_MPIComm, m_DebugMode); - auto bpBaseNames = m_BP1Writer.GetBPBaseNames({m_Name}); + transport::FileFStream profilingJSONStream(m_MPIComm, m_DebugMode); + auto bpBaseNames = m_BP1BuffersWriter.GetBPBaseNames({m_Name}); profilingJSONStream.Open(bpBaseNames[0] + "/profiling.json", - OpenMode::Write); - profilingJSONStream.Write(profilingJSON.c_str(), profilingJSON.size()); + Mode::Write); + profilingJSONStream.Write(profilingJSON.data(), profilingJSON.size()); profilingJSONStream.Close(); } } -} // end namespace adios +} // end namespace adios2 diff --git a/source/adios2/engine/bp/BPFileWriter.h b/source/adios2/engine/bp/BPFileWriter.h index bb7d552650a6a70132522af22fc8d86595696211..38fddd63e26030b0b40d62d532afb3118fd075bd 100644 --- a/source/adios2/engine/bp/BPFileWriter.h +++ b/source/adios2/engine/bp/BPFileWriter.h @@ -29,7 +29,7 @@ public: * @param openMode w (supported), r, a from OpenMode in ADIOSTypes.h * @param mpiComm MPI communicator */ - BPFileWriter(IO &io, const std::string &name, const OpenMode openMode, + BPFileWriter(IO &io, const std::string &name, const Mode openMode, MPI_Comm mpiComm); ~BPFileWriter(); @@ -48,13 +48,10 @@ public: private: /** Single object controlling BP buffering */ - format::BP1Writer m_BP1Writer; + format::BP1Writer m_BP1BuffersWriter; - /** single object controlling a vector of Transports from IO AddTransport */ - transportman::TransportMan m_TransportsManager; - - /** true: due to buffer overflow, move to transports manager */ - bool m_DoTransportFlush = false; + /** Single object controlling a vector of Transports from IO AddTransport */ + transportman::TransportMan m_FileManager; void Init() final; @@ -62,7 +59,7 @@ private: void InitParameters() final; /** Parses transports and parameters from IO AddTransport */ void InitTransports() final; - + /** Allocates memory and starts a PG group */ void InitBPBuffer(); #define declare_type(T) \ @@ -83,6 +80,6 @@ private: void WriteProfilingJSONFile(); }; -} // end namespace adios +} // end namespace adios2 #endif /* ADIOS2_ENGINE_BP_BPFILEWRITER_H_ */ diff --git a/source/adios2/engine/bp/BPFileWriter.tcc b/source/adios2/engine/bp/BPFileWriter.tcc index d6ccde49cd61661e3bf1b5ec758e3306660c9292..7f012976a9795fdf6b872f708184ef8def88cfe2 100644 --- a/source/adios2/engine/bp/BPFileWriter.tcc +++ b/source/adios2/engine/bp/BPFileWriter.tcc @@ -7,6 +7,8 @@ * Created on: May 22, 2017 * Author: William F Godoy godoywf@ornl.gov */ +#ifndef ADIOS2_ENGINE_BP_BPFILEWRITER_TCC_ +#define ADIOS2_ENGINE_BP_BPFILEWRITER_TCC_ #include "BPFileWriter.h" @@ -21,40 +23,39 @@ void BPFileWriter::DoWriteCommon(Variable<T> &variable, const T *values) m_WrittenVariables.insert(variable.m_Name); // if first timestep Write create a new pg index - if (!m_BP1Writer.m_MetadataSet.DataPGIsOpen) + if (!m_BP1BuffersWriter.m_MetadataSet.DataPGIsOpen) { - m_BP1Writer.WriteProcessGroupIndex( - m_IO.m_HostLanguage, m_TransportsManager.GetTransportsTypes()); + m_BP1BuffersWriter.WriteProcessGroupIndex( + m_IO.m_HostLanguage, m_FileManager.GetTransportsTypes()); } - const size_t oldSize = m_BP1Writer.m_HeapBuffer.GetDataSize(); - format::BP1Base::ResizeResult resizeResult = - m_BP1Writer.ResizeBuffer(variable); - - const size_t newSize = m_BP1Writer.m_HeapBuffer.GetDataSize(); + m_BP1BuffersWriter.ResizeBuffer(variable); if (resizeResult == format::BP1Base::ResizeResult::Flush) { - m_BP1Writer.Flush(m_IO); - auto &heapBuffer = m_BP1Writer.m_HeapBuffer; + m_BP1BuffersWriter.Flush(m_IO); + auto &buffer = m_BP1BuffersWriter.m_Data.m_Buffer; + auto &position = m_BP1BuffersWriter.m_Data.m_Position; - m_TransportsManager.WriteFiles(heapBuffer.GetData(), - heapBuffer.m_DataPosition); + m_FileManager.WriteFiles(buffer.data(), position); // set relative position to zero - heapBuffer.m_DataPosition = 0; - // reset buffer to zero values - heapBuffer.m_Data.assign(heapBuffer.GetDataSize(), '\0'); + position = 0; + // reset buffer to zero values to current size + buffer.assign(buffer.size(), '\0'); - m_BP1Writer.WriteProcessGroupIndex( - m_IO.m_HostLanguage, m_TransportsManager.GetTransportsTypes()); + // new group index + m_BP1BuffersWriter.WriteProcessGroupIndex( + m_IO.m_HostLanguage, m_FileManager.GetTransportsTypes()); } // WRITE INDEX to data buffer and metadata structure (in memory)// - m_BP1Writer.WriteVariableMetadata(variable); - m_BP1Writer.WriteVariablePayload(variable); + m_BP1BuffersWriter.WriteVariableMetadata(variable); + m_BP1BuffersWriter.WriteVariablePayload(variable); variable.m_AppValues = nullptr; // not needed after write } -} // end namespace adios +} // end namespace adios2 + +#endif /* ADIOS2_ENGINE_BP_BPFILEWRITER_TCC_ */ diff --git a/source/adios2/engine/dataman/DataManReader.cpp b/source/adios2/engine/dataman/DataManReader.cpp index 2f7290e75d8c77a3818d6dc9b83d97a0f9437f91..65c0d99f7bb910c2b5b8cad7b14f37747468531c 100644 --- a/source/adios2/engine/dataman/DataManReader.cpp +++ b/source/adios2/engine/dataman/DataManReader.cpp @@ -16,7 +16,7 @@ namespace adios2 { DataManReader::DataManReader(IO &io, const std::string &name, - const OpenMode openMode, MPI_Comm mpiComm) + const Mode openMode, MPI_Comm mpiComm) : Engine("DataManReader", io, name, openMode, mpiComm) { m_EndMessage = " in call to IO Open DataManReader " + m_Name + "\n"; diff --git a/source/adios2/engine/dataman/DataManReader.h b/source/adios2/engine/dataman/DataManReader.h index 51b41e5ba2ad08291d66e10ec1e5448b1f1541fd..aa77895de25a2e37ff0e19472be31a5fffe73339 100644 --- a/source/adios2/engine/dataman/DataManReader.h +++ b/source/adios2/engine/dataman/DataManReader.h @@ -36,7 +36,7 @@ public: * @param nthreads */ using json = nlohmann::json; - DataManReader(IO &io, const std::string &name, const OpenMode openMode, + DataManReader(IO &io, const std::string &name, const Mode openMode, MPI_Comm mpiComm); virtual ~DataManReader() = default; diff --git a/source/adios2/engine/dataman/DataManWriter.cpp b/source/adios2/engine/dataman/DataManWriter.cpp index 34e61c34f65e2338c8f33b987a08d927771bb55a..2b23bd9f6615dcfe34f74e84883fb791907a75fa 100644 --- a/source/adios2/engine/dataman/DataManWriter.cpp +++ b/source/adios2/engine/dataman/DataManWriter.cpp @@ -19,7 +19,7 @@ namespace adios2 { DataManWriter::DataManWriter(IO &io, const std::string &name, - const OpenMode openMode, MPI_Comm mpiComm) + const Mode openMode, MPI_Comm mpiComm) : Engine("DataManWriter", io, name, openMode, mpiComm) { m_EndMessage = ", in call to Open DataManWriter\n"; diff --git a/source/adios2/engine/dataman/DataManWriter.h b/source/adios2/engine/dataman/DataManWriter.h index 2f829ec40beee06be296d1dc25ab189eaa308d87..a2357a35bb4e8e919d4dceef3bbea853958007d0 100644 --- a/source/adios2/engine/dataman/DataManWriter.h +++ b/source/adios2/engine/dataman/DataManWriter.h @@ -28,7 +28,7 @@ class DataManWriter : public Engine public: using json = nlohmann::json; - DataManWriter(IO &io, const std::string &name, const OpenMode openMode, + DataManWriter(IO &io, const std::string &name, const Mode openMode, MPI_Comm mpiComm); virtual ~DataManWriter() = default; diff --git a/source/adios2/engine/hdf5/HDF5ReaderP.cpp b/source/adios2/engine/hdf5/HDF5ReaderP.cpp index 985514e9bdc0a640dc631b974c06230fd87c790f..c210acafd2b4cb6ff908ca0a1efdb0899c95bd50 100644 --- a/source/adios2/engine/hdf5/HDF5ReaderP.cpp +++ b/source/adios2/engine/hdf5/HDF5ReaderP.cpp @@ -16,7 +16,7 @@ namespace adios2 { HDF5ReaderP::HDF5ReaderP(IO &io, const std::string &name, - const OpenMode openMode, MPI_Comm mpiComm) + const Mode openMode, MPI_Comm mpiComm) : Engine("HDF5Reader", io, name, openMode, mpiComm), m_H5File(io.m_DebugMode) { m_EndMessage = ", in call to IO HDF5Reader Open " + m_Name + "\n"; @@ -29,7 +29,7 @@ bool HDF5ReaderP::IsValid() { bool isValid = false; - if (m_OpenMode != OpenMode::Read) + if (m_OpenMode != Mode::Read) { return isValid; } @@ -41,7 +41,7 @@ bool HDF5ReaderP::IsValid() } void HDF5ReaderP::Init() { - if (m_OpenMode != OpenMode::Read) + if (m_OpenMode != Mode::Read) { throw std::invalid_argument( "ERROR: HDF5Reader only supports OpenMode::Read " diff --git a/source/adios2/engine/hdf5/HDF5ReaderP.h b/source/adios2/engine/hdf5/HDF5ReaderP.h index 28e16631f3cf53c23b2bf5c8a2c68186cee92263..3365185c5c545096a1816057cfbe1324bc34973c 100644 --- a/source/adios2/engine/hdf5/HDF5ReaderP.h +++ b/source/adios2/engine/hdf5/HDF5ReaderP.h @@ -29,7 +29,7 @@ public: * @param mpiComm * @param method */ - HDF5ReaderP(IO &adios, const std::string &name, const OpenMode openMode, + HDF5ReaderP(IO &adios, const std::string &name, const Mode openMode, MPI_Comm mpiComm); ~HDF5ReaderP(); diff --git a/source/adios2/engine/hdf5/HDF5WriterP.cpp b/source/adios2/engine/hdf5/HDF5WriterP.cpp index 9c3979477e423a016c4fd7a8c4e1f8597beed42b..e4948ba4958495554fe12317e09a5bc1694a4de1 100644 --- a/source/adios2/engine/hdf5/HDF5WriterP.cpp +++ b/source/adios2/engine/hdf5/HDF5WriterP.cpp @@ -17,7 +17,7 @@ namespace adios2 { HDF5WriterP::HDF5WriterP(IO &io, const std::string &name, - const OpenMode openMode, MPI_Comm mpiComm) + const Mode openMode, MPI_Comm mpiComm) : Engine("HDF5Writer", io, name, openMode, mpiComm), m_H5File(io.m_DebugMode) { m_EndMessage = ", in call to IO HDF5Writer Open " + m_Name + "\n"; @@ -29,7 +29,7 @@ HDF5WriterP::~HDF5WriterP() { Close(); } // PRIVATE void HDF5WriterP::Init() { - if (m_OpenMode != OpenMode::Write && m_OpenMode != OpenMode::Append) + if (m_OpenMode != Mode::Write && m_OpenMode != Mode::Append) { throw std::invalid_argument( "ERROR: HDF5Writer only support OpenMode::Write or " diff --git a/source/adios2/engine/hdf5/HDF5WriterP.h b/source/adios2/engine/hdf5/HDF5WriterP.h index 2bf07d4c9e2ac4fcc9bd5db4b87e028b9e35dd68..a573b24b052cf77c25e634bd0421d7360197310c 100644 --- a/source/adios2/engine/hdf5/HDF5WriterP.h +++ b/source/adios2/engine/hdf5/HDF5WriterP.h @@ -33,7 +33,7 @@ public: * @param mpiComm * @param method */ - HDF5WriterP(IO &io, const std::string &name, const OpenMode openMode, + HDF5WriterP(IO &io, const std::string &name, const Mode openMode, MPI_Comm mpiComm); ~HDF5WriterP(); diff --git a/source/adios2/engine/plugin/PluginEngine.cpp b/source/adios2/engine/plugin/PluginEngine.cpp index c81aa060fa61b6e8b135d801f9e1682f0b57eb6d..ee55eced0f36d20c1490248042aa7a16faf8056f 100644 --- a/source/adios2/engine/plugin/PluginEngine.cpp +++ b/source/adios2/engine/plugin/PluginEngine.cpp @@ -51,7 +51,7 @@ void PluginEngine::RegisterPlugin(const std::string pluginName, /******************************************************************************/ PluginEngine::PluginEngine(IO &io, const std::string &name, - const OpenMode openMode, MPI_Comm mpiComm) + const Mode openMode, MPI_Comm mpiComm) : Engine("Plugin", io, name, openMode, mpiComm), m_Impl(new Impl) { Init(); diff --git a/source/adios2/engine/plugin/PluginEngine.h b/source/adios2/engine/plugin/PluginEngine.h index 290f04efdab7b4d213ffb12dea2451e8b149f2b2..b4d74e368a531f683c3d68c6c9eacf7e2817f5cf 100644 --- a/source/adios2/engine/plugin/PluginEngine.h +++ b/source/adios2/engine/plugin/PluginEngine.h @@ -37,7 +37,7 @@ public: // Function pointers used for the plugin factory methods using EngineCreatePtr = std::add_pointer<PluginEngineInterface *( - IO &, const std::string &, const OpenMode, MPI_Comm)>::type; + IO &, const std::string &, const Mode, MPI_Comm)>::type; using EngineDestroyPtr = std::add_pointer<void(PluginEngineInterface *)>::type; using EngineCreateFun = @@ -62,7 +62,7 @@ public: static void RegisterPlugin(const std::string name); public: - PluginEngine(IO &io, const std::string &name, const OpenMode openMode, + PluginEngine(IO &io, const std::string &name, const Mode openMode, MPI_Comm mpiComm); virtual ~PluginEngine(); diff --git a/source/adios2/engine/plugin/PluginEngine.inl b/source/adios2/engine/plugin/PluginEngine.inl index e28cbd8b327c306a64cb57bc4b83bc830ee74653..f38cc97c5aa4261acf99eb88e0d42e980c8643c2 100644 --- a/source/adios2/engine/plugin/PluginEngine.inl +++ b/source/adios2/engine/plugin/PluginEngine.inl @@ -23,7 +23,7 @@ template <typename T> void PluginEngine::RegisterPlugin(const std::string name) { EngineCreateFun createFun = - [](IO &io, const std::string &name, const OpenMode openMode, + [](IO &io, const std::string &name, const Mode openMode, MPI_Comm mpiComm) -> PluginEngineInterface * { return new T(io, name, openMode, mpiComm); }; diff --git a/source/adios2/engine/plugin/PluginEngineInterface.cpp b/source/adios2/engine/plugin/PluginEngineInterface.cpp index a6e20d69668f2e31f41c4deabe0319c130abeed4..6cbc955e718f00fb83ab571bf2bc9d122a9c2d0f 100644 --- a/source/adios2/engine/plugin/PluginEngineInterface.cpp +++ b/source/adios2/engine/plugin/PluginEngineInterface.cpp @@ -14,7 +14,7 @@ namespace adios2 { PluginEngineInterface::PluginEngineInterface(IO &io, const std::string &name, - const OpenMode openMode, + const Mode openMode, MPI_Comm mpiComm) : Engine("PluginInterface", io, name, openMode, mpiComm) { diff --git a/source/adios2/engine/plugin/PluginEngineInterface.h b/source/adios2/engine/plugin/PluginEngineInterface.h index 20d9e9c144f6b348528cf142856826b66ce24623..b89846adb5274ae0bdd0516ea8a9e8e5e9c022ba 100644 --- a/source/adios2/engine/plugin/PluginEngineInterface.h +++ b/source/adios2/engine/plugin/PluginEngineInterface.h @@ -32,7 +32,7 @@ class PluginEngineInterface : public Engine public: PluginEngineInterface(IO &io, const std::string &name, - const OpenMode openMode, MPI_Comm mpiComm); + const Mode openMode, MPI_Comm mpiComm); virtual ~PluginEngineInterface() = default; }; diff --git a/source/adios2/helper/adiosMPIFunctions.cpp b/source/adios2/helper/adiosMPIFunctions.cpp index bd550b00ef5c2e1fb0f4baaa9f83a3a8da49cbd3..48696edfd11a6cca9d58aaa4feabe5ef9249f23b 100644 --- a/source/adios2/helper/adiosMPIFunctions.cpp +++ b/source/adios2/helper/adiosMPIFunctions.cpp @@ -8,6 +8,7 @@ * Author: William F Godoy godoywf@ornl.gov */ #include "adiosMPIFunctions.h" +#include "adiosMPIFunctions.tcc" #include "adios2/ADIOSMPI.h" #include "adios2/ADIOSTypes.h" @@ -15,32 +16,17 @@ namespace adios2 { -std::string BroadcastString(const std::string &input, MPI_Comm mpiComm, - const int rankSource) +std::vector<int> GetGathervDisplacements(const size_t *counts, + const size_t countsSize) { - int rank; - MPI_Comm_rank(mpiComm, &rank); - size_t length = 0; - std::string output; + std::vector<int> displacements(countsSize); + displacements[0] = 0; - if (rank == rankSource) + for (size_t i = 1; i < countsSize; ++i) { - length = input.size(); - MPI_Bcast(&length, 1, ADIOS2_MPI_SIZE_T, rankSource, mpiComm); - - MPI_Bcast(const_cast<char *>(input.data()), length, MPI_CHAR, - rankSource, mpiComm); - - return input; - } - else - { - MPI_Bcast(&length, 1, ADIOS2_MPI_SIZE_T, rankSource, mpiComm); - output.resize(length); - MPI_Bcast(const_cast<char *>(output.data()), length, MPI_CHAR, - rankSource, mpiComm); + displacements[i] = displacements[i - 1] + counts[i - 1]; } - return output; + return displacements; } } // end namespace adios2 diff --git a/source/adios2/helper/adiosMPIFunctions.h b/source/adios2/helper/adiosMPIFunctions.h index a79345d6af4b735a57f718887c6d21f38b8878bb..320ae41a8d320cd8b5207f7d2306034b1e28dacc 100644 --- a/source/adios2/helper/adiosMPIFunctions.h +++ b/source/adios2/helper/adiosMPIFunctions.h @@ -8,11 +8,12 @@ * Author: William F Godoy godoywf@ornl.gov */ -#ifndef ADIOS2_HELPER_ADIOMPIFUNCTIONS_H_ -#define ADIOS2_HELPER_ADIOMPIFUNCTIONS_H_ +#ifndef ADIOS2_HELPER_ADIOSMPIFUNCTIONS_H_ +#define ADIOS2_HELPER_ADIOSMPIFUNCTIONS_H_ /// \cond EXCLUDE_FROM_DOXYGEN #include <string> +#include <vector> /// \endcond #include "adios2/ADIOSMPICommOnly.h" @@ -20,17 +21,76 @@ namespace adios2 { +template <class T> +T BroadcastValue(const T &input, MPI_Comm mpiComm, const int rankSource = 0); + +template <class T> +std::vector<T> BroadcastVector(const std::vector<T> &input, MPI_Comm mpiComm, + const int rankSource = 0); + +template <class T> +T ReduceValues(const T source, MPI_Comm mpiComm, MPI_Op operation = MPI_SUM, + const int rankDestination = 0); + /** - * rankSource: owns a string and broadcast to all other ranks - * Others: receive std::vector<char> and copy to a string + * Gather a single source value from each ranks and forms a vector in + * rankDestination + * @param sourceSize input from each rank * @param mpiComm MPI communicator defining all ranks and size domain - * @param input string input from rankSource - * @param rankSource rank that broadcast the string, (default = 0) - * @return input contents for each rank + * @param rankDestination root, where all sizes are gathered in the returned + * vector + * @return in rankDestination: aggregated vector<T>, others: empty + */ +template <class T> +std::vector<T> GatherValues(const T source, MPI_Comm mpiComm, + const int rankDestination = 0); + +/** + * Gather equal size arrays + * @param source + * @param sourceCount + * @param destination + * @param mpiComm + * @param rankDestination + */ +template <class T> +void GatherArrays(const T *source, const size_t sourceCount, T *destination, + MPI_Comm mpiComm, const int rankDestination = 0); + +/** + * Gather arrays of the same type into a destination (must be pre-allocated) + * if countsSize == 1, calls MPI_Gather, otherwise calls MPI_Gatherv. + * This function must be specialized for each MPI_Type. + * @param source input from each rank + * @param counts counts for each source + * @param countsSize number of counts + * @param destination resulting gathered buffer in rankDestination, unchaged in + * others + * @param mpiComm communicator establishing the domain + * @param rankDestination rank in which arrays are gathered (root) */ -std::string BroadcastString(const std::string &input, MPI_Comm mpiComm, - const int rankSource = 0); +template <class T> +void GathervArrays(const T *source, const size_t sourceCount, + const size_t *counts, const size_t countsSize, + T *destination, MPI_Comm mpiComm, + const int rankDestination = 0); + +template <class T> +void GathervVectors(const std::vector<T> &in, std::vector<T> &out, + size_t &position, MPI_Comm mpiComm, + const int rankDestination = 0); + +/** + * Gets the displacements (offsets, start) for each + * @param counts + * @param countsSize + * @return + */ +std::vector<int> GetGathervDisplacements(const size_t *counts, + const size_t countsSize); } // end namespace adios2 +#include "adiosMPIFunctions.inl" + #endif /* ADIOS2_HELPER_ADIOMPIFUNCTIONS_H_ */ diff --git a/source/adios2/helper/adiosMPIFunctions.inl b/source/adios2/helper/adiosMPIFunctions.inl new file mode 100644 index 0000000000000000000000000000000000000000..cb0992549a677ed3101ad379179db45551ff3fea --- /dev/null +++ b/source/adios2/helper/adiosMPIFunctions.inl @@ -0,0 +1,70 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * adiosMPIFunctions.inl + * + * Created on: Sep 7, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef ADIOS2_HELPER_ADIOSMPIFUNCTIONS_INL_ +#define ADIOS2_HELPER_ADIOSMPIFUNCTIONS_INL_ +#ifndef ADIOS2_HELPER_ADIOSMPIFUNCTIONS_H_ +#error "Inline file should only be included from it's header, never on it's own" +#endif + +#include <numeric> //std::accumulate + +namespace adios2 +{ +// GatherValues specializations +template <class T> +std::vector<T> GatherValues(const T source, MPI_Comm mpiComm, + const int rankDestination) +{ + constexpr size_t count = 1; + int rank, size; + MPI_Comm_rank(mpiComm, &rank); + MPI_Comm_size(mpiComm, &size); + + std::vector<T> output; + + if (rank == rankDestination) // pre-allocate in destination rank + { + output.resize(size); + } + + T sourceCopy = source; // so we can have an address for rvalues + GatherArrays(&sourceCopy, 1, output.data(), mpiComm, rankDestination); + + return output; +} + +template <class T> +void GathervVectors(const std::vector<T> &in, std::vector<T> &out, + size_t &position, MPI_Comm mpiComm, + const int rankDestination) +{ + const size_t inSize = in.size(); + std::vector<size_t> counts = GatherValues(inSize, mpiComm, rankDestination); + + size_t gatheredSize = 0; + + int rank; + MPI_Comm_rank(mpiComm, &rank); + + if (rank == rankDestination) // pre-allocate vector + { + gatheredSize = std::accumulate(counts.begin(), counts.end(), 0); + out.resize(out.size() + gatheredSize); + position += gatheredSize; + } + + GathervArrays(in.data(), in.size(), counts.data(), counts.size(), + out.data(), mpiComm); +} + +} // end namespace adios2 + +#endif /* ADIOS2_HELPER_ADIOSMPIFUNCTIONS_INL_ */ diff --git a/source/adios2/helper/adiosMPIFunctions.tcc b/source/adios2/helper/adiosMPIFunctions.tcc new file mode 100644 index 0000000000000000000000000000000000000000..4f6eb6585b250a06afd8a892d2eeb1db735f0e4f --- /dev/null +++ b/source/adios2/helper/adiosMPIFunctions.tcc @@ -0,0 +1,253 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * adiosMPIFunctions.tcc : specialization of template functions defined in + * adiosMPIFunctions.h + * + * Created on: Aug 30, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef ADIOS2_HELPER_ADIOSMPIFUNCTIONS_TCC_ +#define ADIOS2_HELPER_ADIOSMPIFUNCTIONS_TCC_ + +#include "adiosMPIFunctions.h" + +#include <algorithm> //std::foreach +#include <iostream> //TODO: remove +#include <numeric> //std::accumulate + +#include "adios2/ADIOSMPI.h" +#include "adios2/ADIOSTypes.h" +#include "adios2/helper/adiosType.h" + +namespace adios2 +{ +// BroadcastValue specializations +template <> +size_t BroadcastValue(const size_t &input, MPI_Comm mpiComm, + const int rankSource) +{ + int rank; + MPI_Comm_rank(mpiComm, &rank); + size_t output = 0; + + if (rank == rankSource) + { + output = input; + } + + MPI_Bcast(&output, 1, ADIOS2_MPI_SIZE_T, rankSource, mpiComm); + + return output; +} + +template <> +std::string BroadcastValue(const std::string &input, MPI_Comm mpiComm, + const int rankSource) +{ + int rank; + MPI_Comm_rank(mpiComm, &rank); + const size_t inputSize = input.size(); + size_t length = BroadcastValue(inputSize, mpiComm, rankSource); + std::string output; + + if (rank == rankSource) + { + output = input; + } + else + { + output.resize(length); + } + + MPI_Bcast(const_cast<char *>(output.data()), length, MPI_CHAR, rankSource, + mpiComm); + + return output; +} + +// ReduceValue specializations +template <> +unsigned int ReduceValues(const unsigned int source, MPI_Comm mpiComm, + MPI_Op operation, const int rankDestination) +{ + const unsigned int sourceLocal = source; + unsigned int reduceValue = 0; + MPI_Reduce(&sourceLocal, &reduceValue, 1, MPI_UNSIGNED, operation, + rankDestination, mpiComm); + return reduceValue; +} + +template <> +unsigned long int ReduceValues(const unsigned long int source, MPI_Comm mpiComm, + MPI_Op operation, const int rankDestination) +{ + const unsigned long int sourceLocal = source; + unsigned long int reduceValue = 0; + MPI_Reduce(&sourceLocal, &reduceValue, 1, MPI_UNSIGNED_LONG, operation, + rankDestination, mpiComm); + return reduceValue; +} + +template <> +unsigned long long int ReduceValues(const unsigned long long int source, + MPI_Comm mpiComm, MPI_Op operation, + const int rankDestination) +{ + const unsigned long long int sourceLocal = source; + unsigned long long int reduceValue = 0; + MPI_Reduce(&sourceLocal, &reduceValue, 1, MPI_UNSIGNED_LONG_LONG, operation, + rankDestination, mpiComm); + return reduceValue; +} + +// BroadcastVector specializations +template <> +std::vector<char> BroadcastVector(const std::vector<char> &input, + MPI_Comm mpiComm, const int rankSource) +{ + // First Broadcast the size, then the contents + size_t inputSize = BroadcastValue(input.size(), mpiComm, rankSource); + int rank; + MPI_Comm_rank(mpiComm, &rank); + std::vector<char> output; + + if (rank == rankSource) + { + MPI_Bcast(const_cast<char *>(input.data()), static_cast<int>(inputSize), + MPI_CHAR, rankSource, mpiComm); + return input; // no copy + } + else + { + output.resize(inputSize); + MPI_Bcast(output.data(), static_cast<int>(inputSize), MPI_CHAR, + rankSource, mpiComm); + } + + return output; +} + +template <> +std::vector<size_t> BroadcastVector(const std::vector<size_t> &input, + MPI_Comm mpiComm, const int rankSource) +{ + // First Broadcast the size, then the contents + size_t inputSize = BroadcastValue(input.size(), mpiComm, rankSource); + int rank; + MPI_Comm_rank(mpiComm, &rank); + std::vector<size_t> output; + + if (rank == rankSource) + { + MPI_Bcast(const_cast<size_t *>(input.data()), + static_cast<int>(inputSize), ADIOS2_MPI_SIZE_T, rankSource, + mpiComm); + return input; // no copy in rankSource + } + else + { + output.resize(inputSize); + MPI_Bcast(output.data(), static_cast<int>(inputSize), ADIOS2_MPI_SIZE_T, + rankSource, mpiComm); + } + + return output; +} + +// GatherArrays specializations +template <> +void GatherArrays(const char *source, const size_t sourceCount, + char *destination, MPI_Comm mpiComm, + const int rankDestination) +{ + const int countsInt = static_cast<int>(sourceCount); + int result = MPI_Gather(source, countsInt, MPI_CHAR, destination, countsInt, + MPI_CHAR, rankDestination, mpiComm); + + if (result != MPI_SUCCESS) + { + throw std::runtime_error("ERROR: in ADIOS2 detected failure in MPI " + "Gather type MPI_CHAR function\n"); + } +} + +template <> +void GatherArrays(const size_t *source, const size_t sourceCount, + size_t *destination, MPI_Comm mpiComm, + const int rankDestination) +{ + const int countsInt = static_cast<int>(sourceCount); + int result = + MPI_Gather(source, countsInt, ADIOS2_MPI_SIZE_T, destination, countsInt, + ADIOS2_MPI_SIZE_T, rankDestination, mpiComm); + + if (result != MPI_SUCCESS) + { + throw std::runtime_error("ERROR: in ADIOS2 detected failure in MPI " + "Gather type size_t function\n"); + } +} + +// GathervArrays specializations +template <> +void GathervArrays(const char *source, const size_t sourceCount, + const size_t *counts, const size_t countsSize, + char *destination, MPI_Comm mpiComm, + const int rankDestination) +{ + int result = 0; + int rank; + MPI_Comm_rank(mpiComm, &rank); + + std::vector<int> countsInt, displacementsInt; + + if (rank == rankDestination) + { + countsInt = NewVectorTypeFromArray<size_t, int>(counts, countsSize); + displacementsInt = GetGathervDisplacements(counts, countsSize); + } + + result = MPI_Gatherv(source, static_cast<int>(sourceCount), MPI_CHAR, + destination, countsInt.data(), displacementsInt.data(), + MPI_CHAR, rankDestination, mpiComm); + + if (result != MPI_SUCCESS) + { + throw std::runtime_error("ERROR: in ADIOS2 detected failure in MPI " + "Gatherv type MPI_CHAR function\n"); + } +} + +template <> +void GathervArrays(const size_t *source, const size_t sourceCount, + const size_t *counts, const size_t countsSize, + size_t *destination, MPI_Comm mpiComm, + const int rankDestination) +{ + int result = 0; + int rank; + MPI_Comm_rank(mpiComm, &rank); + + std::vector<int> countsInt = + NewVectorTypeFromArray<size_t, int>(counts, countsSize); + + std::vector<int> displacementsInt = + GetGathervDisplacements(counts, countsSize); + + result = MPI_Gatherv(source, sourceCount, ADIOS2_MPI_SIZE_T, destination, + countsInt.data(), displacementsInt.data(), + ADIOS2_MPI_SIZE_T, rankDestination, mpiComm); + + if (result != MPI_SUCCESS) + { + throw std::runtime_error("ERROR: in ADIOS2 detected failure in MPI " + "Gather type size_t function\n"); + } +} + +} // end namespace adios2 + +#endif /* ADIOS2_HELPER_ADIOSMPIFUNCTIONS_TCC_ */ diff --git a/source/adios2/helper/adiosMemory.h b/source/adios2/helper/adiosMemory.h index ad5dd0116d123da9a885c99ca940efa1e825b969..8c67c7c8e565422d3047793f9f4618a3ca61eaa7 100644 --- a/source/adios2/helper/adiosMemory.h +++ b/source/adios2/helper/adiosMemory.h @@ -59,29 +59,16 @@ void CopyToBufferThreads(std::vector<char> &buffer, size_t &position, const unsigned int threads = 1) noexcept; /** - * Memcpy data to a specific location in the buffer updating position - * Does not update vec.size(). - * @param buffer data destination used in memcpy - * @param position starting position in buffer (in terms of T not bytes) - * @param source pointer to source data - * @param size number of bytes from source + * Copy memory from a buffer at a certain input position + * @param buffer data source + * @param position start position to copy from buffer, modified to final + * position + * @param destination pointer to destination + * @param elements number of elements of destination type */ template <class T> -void MemcpyToBuffer(std::vector<char> &buffer, size_t &position, - const T *source, size_t size) noexcept; - -/** - * Threaded version of MemcpyToBuffer - * @param buffer data destination used in memcpy - * @param position starting position in buffer (in terms of T not bytes) - * @param source pointer to source data - * @param size number of bytes from source - * @param threads number of threads sharing the memcpy load - */ -template <class T> -void MemcpyToBufferThreads(std::vector<char> &buffer, size_t &position, - const T *source, size_t size, - const unsigned int threads = 1); +void CopyFromBuffer(const std::vector<char> &buffer, size_t &position, + T *destination, const size_t elements = 1) noexcept; /** * Cast an element to uint64 and insert to a buffer @@ -91,7 +78,10 @@ void MemcpyToBufferThreads(std::vector<char> &buffer, size_t &position, template <class T> void InsertU64(std::vector<char> &buffer, const T element) noexcept; -} // end namespace adios +template <class T> +T ReadValue(const std::vector<char> &buffer, size_t &position) noexcept; + +} // end namespace adios2 #include "adiosMemory.inl" diff --git a/source/adios2/helper/adiosMemory.inl b/source/adios2/helper/adiosMemory.inl index 0eaa2662a765b1e8e5523c624d5ce853b3194a10..001b1be57c2a38374a7b66bc3b80454dabdb950a 100644 --- a/source/adios2/helper/adiosMemory.inl +++ b/source/adios2/helper/adiosMemory.inl @@ -99,8 +99,8 @@ void CopyToBufferThreads(std::vector<char> &buffer, size_t &position, } template <class T> -void CopyFromBuffer(T *destination, size_t elements, - const std::vector<char> &buffer, size_t &position) noexcept +void CopyFromBuffer(const std::vector<char> &buffer, size_t &position, + T *destination, size_t elements) noexcept { std::copy(buffer.begin() + position, buffer.begin() + position + sizeof(T) * elements, @@ -109,63 +109,20 @@ void CopyFromBuffer(T *destination, size_t elements, } template <class T> -void MemcpyToBuffer(std::vector<char> &buffer, size_t &position, - const T *source, size_t size) noexcept -{ - std::memcpy(&buffer[position], source, size); - position += size; -} - -template <class T> -void MemcpyToBufferThreads(std::vector<char> &buffer, size_t &position, - const T *source, size_t size, - const unsigned int threads) +void InsertU64(std::vector<char> &buffer, const T element) noexcept { - if (threads == 1) - { - std::memcpy(&buffer[position], source, size); - return; - } - - const size_t stride = size / threads; - const size_t remainder = size % threads; - const size_t last = stride + remainder; - - std::vector<std::thread> memcpyThreads; - memcpyThreads.reserve(threads); - - for (unsigned int t = 0; t < threads; ++t) - { - const size_t initialDestination = position + stride * t; - const size_t initialSource = stride * t / sizeof(T); - - if (t == threads - 1) - { - memcpyThreads.push_back(std::thread(std::memcpy, - &buffer[initialDestination], - &source[initialSource], last)); - } - else - { - memcpyThreads.push_back( - std::thread(std::memcpy, &buffer[initialDestination], - &source[initialSource], stride)); - } - } - - for (auto &thread : memcpyThreads) - { - thread.join(); - } + const uint64_t element64 = static_cast<const uint64_t>(element); + InsertToBuffer(buffer, &element64); } template <class T> -void InsertU64(std::vector<char> &buffer, const T element) noexcept +T ReadValue(const std::vector<char> &buffer, size_t &position) noexcept { - const uint64_t element64 = static_cast<const uint64_t>(element); - InsertToBuffer(buffer, &element64); + T value; + CopyFromBuffer(buffer, position, &value); + return value; } -} // end namespace +} // end namespace adios2 #endif /* ADIOS2_HELPER_ADIOSMEMORY_INL_ */ diff --git a/source/adios2/helper/adiosType.cpp b/source/adios2/helper/adiosType.cpp index 18d1b0c1c0723896b9dcdd7ec9155c5447bbe9ba..0df9afe85e7928ef82c79932ffb934d10c22f4df 100644 --- a/source/adios2/helper/adiosType.cpp +++ b/source/adios2/helper/adiosType.cpp @@ -93,14 +93,12 @@ std::vector<std::size_t> Uint64ArrayToSizetVector(const size_t nElements, return out; } -std::vector<std::size_t> +std::vector<size_t> Uint64VectorToSizetVector(const std::vector<uint64_t> &in) noexcept { std::vector<size_t> out(in.size()); - out.resize(in.size()); std::transform(in.begin(), in.end(), out.begin(), [](uint64_t value) { return static_cast<size_t>(value); }); - return out; } @@ -171,12 +169,12 @@ size_t BytesFactor(const std::string units, const bool debugMode) return factor; } -std::string OpenModeToString(const OpenMode openMode, +std::string OpenModeToString(const Mode openMode, const bool oneLetter) noexcept { std::string openModeString; - if (openMode == OpenMode::Write) + if (openMode == Mode::Write) { if (oneLetter) { @@ -187,7 +185,7 @@ std::string OpenModeToString(const OpenMode openMode, openModeString = "Write"; } } - else if (openMode == OpenMode::Append) + else if (openMode == Mode::Append) { if (oneLetter) { @@ -198,7 +196,7 @@ std::string OpenModeToString(const OpenMode openMode, openModeString = "Append"; } } - else if (openMode == OpenMode::Read) + else if (openMode == Mode::Read) { if (oneLetter) { diff --git a/source/adios2/helper/adiosType.h b/source/adios2/helper/adiosType.h index 529ab97eede1b1098f121ce83d7cb5c57f3761b0..1c1bddb0f203e8836c1dc51e8a46f4fa43f4d875 100644 --- a/source/adios2/helper/adiosType.h +++ b/source/adios2/helper/adiosType.h @@ -105,8 +105,14 @@ size_t BytesFactor(const std::string units, const bool debugMode); * @param oneLetter if true returns a one letter version ("w", "a" or "r") * @return string with open mode */ -std::string OpenModeToString(const OpenMode openMode, +std::string OpenModeToString(const Mode openMode, const bool oneLetter = false) noexcept; + +template <class T, class U> +std::vector<U> NewVectorType(const std::vector<T> &in); + +template <class T, class U> +std::vector<U> NewVectorTypeFromArray(const T *in, const size_t inSize); } #include "adiosType.inl" diff --git a/source/adios2/helper/adiosType.inl b/source/adios2/helper/adiosType.inl index b81bb598183f5f11080ef293a61f3ed396366718..c32f2d7546bee4a207b356769195672d5278d1e1 100644 --- a/source/adios2/helper/adiosType.inl +++ b/source/adios2/helper/adiosType.inl @@ -14,6 +14,8 @@ #error "Inline file should only be included from it's header, never on it's own" #endif +#include <algorithm> + namespace adios2 { @@ -139,6 +141,21 @@ bool IsTypeAlias( return isAlias; } -} // end namespace adios +template <class T, class U> +std::vector<U> NewVectorType(const std::vector<T> &in) +{ + return NewVectorTypeFromArray(in.data(), in.size()); +} + +template <class T, class U> +std::vector<U> NewVectorTypeFromArray(const T *in, const size_t inSize) +{ + std::vector<U> out(inSize); + std::transform(in, in + inSize, out.begin(), + [](T value) { return static_cast<U>(value); }); + return out; +} + +} // end namespace adios2 #endif /* ADIOS2_HELPER_ADIOSTYPE_INL_ */ diff --git a/source/adios2/helper/adiosXML.cpp b/source/adios2/helper/adiosXML.cpp index 25bae1343c05e09b5776f9ca7af4ecf07f3ae6ae..1ceabae14021da9c406f8196bbddb457c2b52597 100644 --- a/source/adios2/helper/adiosXML.cpp +++ b/source/adios2/helper/adiosXML.cpp @@ -162,7 +162,7 @@ void InitXML(const std::string configXML, MPI_Comm mpiComm, fileContents = FileToString(configXML); } - fileContents = BroadcastString(fileContents, mpiComm); + fileContents = BroadcastValue(fileContents, mpiComm); pugi::xml_document doc; auto parse_result = doc.load_buffer_inplace( diff --git a/source/adios2/mpidummy.cpp b/source/adios2/mpidummy.cpp index 51a5dcf881e3c516d90adaee0388da69b9ccee91..e595ec052fc1edb6d92a04eb3fbb84920b7503d2 100644 --- a/source/adios2/mpidummy.cpp +++ b/source/adios2/mpidummy.cpp @@ -121,9 +121,18 @@ int MPI_Gather(const void *sendbuf, int sendcnt, MPI_Datatype sendtype, switch (sendtype) { + case MPI_CHAR: + n = sizeof(char); + break; case MPI_INT: n = sizeof(int); break; + case MPI_UNSIGNED: + n = sizeof(unsigned int); + break; + case MPI_UNSIGNED_LONG: + n = sizeof(unsigned long); + break; default: return MPI_ERR_TYPE; } @@ -131,9 +140,18 @@ int MPI_Gather(const void *sendbuf, int sendcnt, MPI_Datatype sendtype, switch (recvtype) { + case MPI_CHAR: + nrecv = sizeof(char); + break; case MPI_INT: nrecv = sizeof(int); break; + case MPI_UNSIGNED: + nrecv = sizeof(unsigned int); + break; + case MPI_UNSIGNED_LONG: + nrecv = sizeof(unsigned long); + break; default: return MPI_ERR_TYPE; } @@ -382,5 +400,12 @@ int MPI_Get_processor_name(char *name, int *resultlen) return 0; } +int MPI_Reduce(const void *sendbuf, void *recvbuf, int count, + MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm) +{ + *recvbuf = *sendbuf; + return 0; +} + } // end namespace mpi } // end namespace adios diff --git a/source/adios2/mpidummy.h b/source/adios2/mpidummy.h index 1194d2a1f9d2714d10cf6d4cd5a8496809c9431e..12438b078aea5c47bf0f9d6f2ee88bcd66242268 100644 --- a/source/adios2/mpidummy.h +++ b/source/adios2/mpidummy.h @@ -27,6 +27,7 @@ typedef int MPI_Info; typedef int MPI_Datatype; /* Store the byte size of a type in such vars */ typedef long MPI_Offset; typedef int MPI_Fint; +typedef int MPI_Op; #define MPI_SUCCESS 0 #define MPI_ERR_BUFFER 1 /* Invalid buffer pointer */ @@ -125,6 +126,9 @@ int MPI_Get_processor_name(char *name, int *resultlen); double MPI_Wtime(); +int MPI_Reduce(const void *sendbuf, void *recvbuf, int count, + MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm); + } // end namespace mpi } // end namespace adios diff --git a/source/adios2/toolkit/capsule/Capsule.cpp b/source/adios2/toolkit/capsule/Capsule.cpp deleted file mode 100644 index b9e4a309e0094c65533a857bd94237fe9914946c..0000000000000000000000000000000000000000 --- a/source/adios2/toolkit/capsule/Capsule.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * Capsule.cpp - * - * Created on: Nov 11, 2016 - * Author: wfg - */ - -#include "Capsule.h" - -namespace adios2 -{ - -Capsule::Capsule(const std::string type, const bool debugMode) -: m_Type(type), m_DebugMode(debugMode) -{ -} - -size_t Capsule::GetAvailableDataSize() const -{ - return GetDataSize() - m_DataPosition; -} - -void Capsule::ResizeData(size_t /*size*/) {} - -void Capsule::ResizeMetadata(size_t /*size*/) {} - -} // end namespace adios diff --git a/source/adios2/toolkit/capsule/Capsule.h b/source/adios2/toolkit/capsule/Capsule.h deleted file mode 100644 index 0534e75ec69912a4b012befb0249048c9fad2a12..0000000000000000000000000000000000000000 --- a/source/adios2/toolkit/capsule/Capsule.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * Capsule.h - * - * Created on: Dec 7, 2016 - * Author: William F Godoy godoywf@ornl.gov - */ - -#ifndef ADIOS2_TOOLKIT_CAPSULE_CAPSULE_H_ -#define ADIOS2_TOOLKIT_CAPSULE_CAPSULE_H_ - -/// \cond EXCLUDE_FROM_DOXYGEN -#include <string> -/// \endcond - -#include "adios2/ADIOSConfig.h" -#include "adios2/ADIOSTypes.h" - -namespace adios2 -{ - -/** - * Base class that raw data and metadata buffers, used by Engine. - * Derived classes will allocate their own buffer in different memory spaces. - * e.g. locally (heap) or in shared memory (virtual memory) - */ -class Capsule -{ - -public: - /** Derived class ID */ - const std::string m_Type; - - /** position in current data buffer */ - size_t m_DataPosition = 0; - - /** position in current data buffer + bytes flushed in transports */ - size_t m_DataAbsolutePosition = 0; - - /** position in metadata buffer */ - size_t m_MetadataPosition = 0; - - /** - * Unique constructor - * @param type derived class - * @param debugMode true: extra exception checks - */ - Capsule(const std::string type, const bool debugMode); - - virtual ~Capsule() = default; - - /** pointer to the raw data buffer */ - virtual char *GetData() = 0; - /** pointer to the raw metadata buffer */ - virtual char *GetMetadata() = 0; - - virtual size_t GetDataSize() const = 0; ///< data buffer memory size - virtual size_t GetMetadataSize() const = 0; ///< metadata buffer memory size - - size_t GetAvailableDataSize() const; - - virtual void ResizeData(const size_t size); ///< resize data buffer - virtual void ResizeMetadata(const size_t size); ///< resize metadata buffer - -protected: - const bool m_DebugMode = false; ///< true: extra exception checks -}; - -} // end namespace - -#endif /* ADIOS2_TOOLKIT_CAPSULE_CAPSULE_H_ */ diff --git a/source/adios2/toolkit/capsule/heap/STLVector.cpp b/source/adios2/toolkit/capsule/heap/STLVector.cpp deleted file mode 100644 index 5221f00faa3245c66a14d3dd44708d34a40b1f81..0000000000000000000000000000000000000000 --- a/source/adios2/toolkit/capsule/heap/STLVector.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * STLVector.cpp - * - * Created on: Dec 22, 2016 - * Author: wfg - */ - -#include "STLVector.h" - -/// \cond EXCLUDE_FROM_DOXYGEN -#include <new> //std::bad_alloc -#include <stdexcept> //std::runtime_error -/// \endcond - -namespace adios2 -{ -namespace capsule -{ - -STLVector::STLVector(const bool debugMode) -: Capsule("heap/STLVector", debugMode) -{ -} - -char *STLVector::GetData() { return m_Data.data(); } - -char *STLVector::GetMetadata() { return m_Metadata.data(); } - -size_t STLVector::GetDataSize() const { return m_Data.size(); } - -size_t STLVector::GetMetadataSize() const { return m_Metadata.size(); } - -void STLVector::ResizeData(const size_t size) -{ - if (m_DebugMode) - { - try - { - m_Data.resize(size); - } - catch (...) - { - std::throw_with_nested( - std::runtime_error("ERROR: possible overflow when resizing " - "data buffer with size " + - std::to_string(size) + "\n")); - } - } - else - { - m_Data.resize(size); - } -} - -void STLVector::ResizeMetadata(const size_t size) -{ - if (m_DebugMode) - { - try - { - m_Metadata.resize(size); - } - catch (...) - { - std::throw_with_nested( - std::runtime_error("ERROR: possible overflow when resizing " - "metadata buffer with size " + - std::to_string(size) + "\n")); - } - } - else - { - m_Metadata.resize(size); - } -} - -} // end namespace capsule -} // end namespace adios diff --git a/source/adios2/toolkit/capsule/heap/STLVector.h b/source/adios2/toolkit/capsule/heap/STLVector.h deleted file mode 100644 index ffe091d8f260d99f65acd2ede07bba55e2470f82..0000000000000000000000000000000000000000 --- a/source/adios2/toolkit/capsule/heap/STLVector.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * Heap.h - * - * Created on: Dec 19, 2016 - * Author: wfg - */ - -#ifndef ADIOS2_TOOLKIT_CAPSULE_HEAP_STLVECTOR_H_ -#define ADIOS2_TOOLKIT_CAPSULE_HEAP_STLVECTOR_H_ - -/// \cond EXCLUDE_FROM_DOXYGEN -#include <vector> -/// \endcond - -#include "adios2/ADIOSConfig.h" -#include "adios2/toolkit/capsule/Capsule.h" - -namespace adios2 -{ -namespace capsule -{ - -/** - * Data and Metadata buffers are allocated in the Heap - */ -class STLVector : public Capsule -{ - -public: - /** data buffer allocated using the STL in heap */ - std::vector<char> m_Data; - /** might be used in cases other than files */ - std::vector<char> m_Metadata; - - /** - * Unique constructor - * @param debugMode true: exceptions checks - */ - STLVector(const bool debugMode = false); - - ~STLVector() = default; - - char *GetData(); - char *GetMetadata(); - - size_t GetDataSize() const; - size_t GetMetadataSize() const; - - void ResizeData(const size_t size); - void ResizeMetadata(const size_t size); -}; - -} // end namespace capsule -} // end namespace - -#endif /* ADIOS2_CAPSULE_HEAP_STLVECTOR_H_ */ diff --git a/source/adios2/toolkit/capsule/shmem/ShmSystemV.cpp b/source/adios2/toolkit/capsule/shmem/ShmSystemV.cpp deleted file mode 100644 index 21ba4efcd636c739cfa8a3517d03f4d7db9e14c5..0000000000000000000000000000000000000000 --- a/source/adios2/toolkit/capsule/shmem/ShmSystemV.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * ShmSystemV.cpp : implementation of ShmSystemV class - * - * Created on: Dec 22, 2016 - * Author: William F Godoy godoywf@ornl.gov - */ - -#include "ShmSystemV.h" - -#include <sys/shm.h> //shmget - -/// \cond EXCLUDE_FROM_DOXYGEN -#include <ios> //std::ios_base::failure -#include <utility> -/// \endcond - -namespace adios2 -{ - -ShmSystemV::ShmSystemV(const std::string &pathName, const int rankMPI, - const size_t dataSize, const size_t metadataSize, - const bool debugMode) -: Capsule("ShmSystemV", debugMode), m_DataSize(dataSize), - m_MetadataSize(metadataSize) -{ - // Data Shared memory sector - const std::string dataPath(pathName + "/adios.shm.data." + - std::to_string(rankMPI)); - - // 2nd field must be greater than zero and unique - m_DataKey = ftok(dataPath.c_str(), rankMPI + 1); - m_DataShmID = shmget(m_DataKey, m_DataSize, IPC_CREAT | 0666); - m_Data = static_cast<char *>(shmat(m_DataShmID, nullptr, 0)); - - // Metadata Shared memory sector - const std::string metadataPath(pathName + "/adios.shm.metadata." + - std::to_string(rankMPI)); - // 2nd field must be greater than zero and unique - m_MetadataKey = ftok(metadataPath.c_str(), rankMPI + 1); - m_MetadataShmID = shmget(m_MetadataKey, m_MetadataSize, IPC_CREAT | 0666); - m_Metadata = static_cast<char *>(shmat(m_MetadataShmID, nullptr, 0)); - - if (m_DebugMode) - { - CheckShm(); - } -} - -char *ShmSystemV::GetData() { return m_Data; } - -char *ShmSystemV::GetMetadata() { return m_Metadata; } - -size_t ShmSystemV::GetDataSize() const { return m_DataSize; } - -size_t ShmSystemV::GetMetadataSize() const { return m_MetadataSize; } - -// PRIVATE -void ShmSystemV::CheckShm() const -{ - if (m_DataShmID < 0) - { - throw std::ios_base::failure( - "ERROR: Failed to create data shm segment of size " + - std::to_string(m_DataSize) + - " from call to ShmSystemV constructor\n"); - } - - if (m_Data == nullptr) - { - throw std::ios_base::failure( - "ERROR: Failed to attach to data shm segment of size " + - std::to_string(m_DataSize) + " and id " + - std::to_string(m_DataShmID) + - ", from call to ShmSystemV constructor\n"); - } - - if (m_DataShmID < 0) - { - throw std::ios_base::failure( - "ERROR: Failed to create metadata shm segment of size " + - std::to_string(m_MetadataSize) + - " from call to ShmSystemV constructor\n"); - } - - if (m_Metadata == nullptr) - { - throw std::ios_base::failure( - "ERROR: Failed to attach to metadata shm segment of size " + - std::to_string(m_MetadataSize) + " and id " + - std::to_string(m_MetadataShmID) + - " from call to ShmSystemV constructor\n"); - } -} - -} // end namespace adios diff --git a/source/adios2/toolkit/capsule/shmem/ShmSystemV.h b/source/adios2/toolkit/capsule/shmem/ShmSystemV.h deleted file mode 100644 index b1bf0f48ea2c28a77c9571137c7e66d803b7eb09..0000000000000000000000000000000000000000 --- a/source/adios2/toolkit/capsule/shmem/ShmSystemV.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * ShmSystemV.h : ShmSystem class as a thin wrapper to a shared memory capsule - * using POSIX SystemV - * - * Created on: Dec 22, 2016 - * Author: William F Godoy godoywf@ornl.gov - */ - -#ifndef ADIOS2_TOOLKIT_CAPSULE_SHMEM_SHMSYSTEMV_H_ -#define ADIOS2_TOOLKIT_CAPSULE_SHMEM_SHMSYSTEMV_H_ - -#include <sys/ipc.h> -#include <sys/types.h> - -#include "adios2/ADIOSConfig.h" -#include "adios2/toolkit/capsule/Capsule.h" - -namespace adios2 -{ - -/** - * Buffer and Metadata are allocated in virtual memory using interprocess - * communication (IPC) of Unix's System V - */ -class ShmSystemV : public Capsule -{ - -public: - /** - * Create a Capsule in shared memory using System V shm API - * @param accessMode - * @param pathName used to create the key as a unique identifier - * @param dataSize size of allocated memory segment for data - * @param metadataSize size of allocated memory segment for metadata - * @param debugMode true: extra checks, slower - */ - ShmSystemV(const std::string &pathName, const int rankMPI, - const size_t dataSize, const size_t metadataSize, - const bool debugMode = false); - - ~ShmSystemV() = default; - - char *GetData(); ///< return the pointer to the raw data buffer - char *GetMetadata(); ///< return the pointer to the raw metadata buffer - - size_t GetDataSize() const; ///< get current data buffer size - size_t GetMetadataSize() const; ///< get current metadata buffer size - -private: - /** reference to a shared memory data buffer */ - char *m_Data = nullptr; - const size_t m_DataSize; ///< size of the allocated shared memory segment - key_t m_DataKey; ///< key associated with the data buffer, created with ftok - int m_DataShmID; ///< data shared memory buffer id - - /** reference to a shared memory metadata buffer created with shmget */ - char *m_Metadata = nullptr; - const size_t m_MetadataSize; ///< size of the allocated segment - key_t m_MetadataKey; ///< ftok metadata buffer key - int m_MetadataShmID; ///< metadata shared memory buffer id - - /** checks if all shared memory allocations are correct, throws - std::bad_alloc, called from constructor if debug mode is true */ - void CheckShm() const; -}; - -} // end namespace adios - -#endif /* ADIOS2_TOOLKIT_CAPSULE_SHMEM_SHMSYSTEMV_H_ */ diff --git a/source/adios2/toolkit/format/BufferSTL.cpp b/source/adios2/toolkit/format/BufferSTL.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b0d3c00bcade7b03372235c0b4d63ac3e824e125 --- /dev/null +++ b/source/adios2/toolkit/format/BufferSTL.cpp @@ -0,0 +1,35 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * BufferSTL.cpp + * + * Created on: Sep 26, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include "BufferSTL.h" + +namespace adios2 +{ + +void BufferSTL::Resize(const size_t size, const std::string hint) +{ + try + { + m_Buffer.resize(size, '\0'); + } + catch (...) + { + std::throw_with_nested(std::runtime_error( + "ERROR: buffer overflow when resizing to " + std::to_string(size) + + " bytes, " + hint + "\n")); + } +} + +size_t BufferSTL::GetAvailableSize() const +{ + return m_Buffer.size() - m_Position; +} + +} // end namespace adios2 diff --git a/source/adios2/toolkit/format/BufferSTL.h b/source/adios2/toolkit/format/BufferSTL.h new file mode 100644 index 0000000000000000000000000000000000000000..b7e7d9e02efb3704b0cf1ff3687610fb4c5a7f65 --- /dev/null +++ b/source/adios2/toolkit/format/BufferSTL.h @@ -0,0 +1,42 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * BufferSTL.h + * + * Created on: Sep 26, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef ADIOS2_TOOLKIT_FORMAT_BUFFERSTL_H_ +#define ADIOS2_TOOLKIT_FORMAT_BUFFERSTL_H_ + +#include <string> +#include <vector> + +#include "adios2/ADIOSTypes.h" + +namespace adios2 +{ + +class BufferSTL +{ +public: + std::vector<char> m_Buffer; + size_t m_Position = 0; + size_t m_AbsolutePosition = 0; + + BufferSTL() = default; + ~BufferSTL() = default; + + void Resize(const size_t size, const std::string hint); + + size_t GetAvailableSize() const; + +private: + const bool m_DebugMode = false; +}; + +} // end namespace adios2 + +#endif /* ADIOS2_TOOLKIT_FORMAT_STLBUFFER_H_ */ diff --git a/source/adios2/toolkit/format/bp1/BP1.h b/source/adios2/toolkit/format/bp1/BP1.h index d2221030dca686cacc0df648d38617db3b668c08..7994fd9a86df315c5941e5d8ccea3d97c609ba9d 100644 --- a/source/adios2/toolkit/format/bp1/BP1.h +++ b/source/adios2/toolkit/format/bp1/BP1.h @@ -11,7 +11,7 @@ #ifndef ADIOS2_TOOLKIT_FORMAT_BP1_BP1_H_ #define ADIOS2_TOOLKIT_FORMAT_BP1_BP1_H_ +#include "adios2/toolkit/format/bp1/BP1Reader.h" #include "adios2/toolkit/format/bp1/BP1Writer.h" -/** TODO #include "adios2/toolkit/format/bp1/BP1Reader.h" */ #endif /* ADIOS2_TOOLKIT_FORMAT_BP1_BP1_H_ */ diff --git a/source/adios2/toolkit/format/bp1/BP1Aggregator.cpp b/source/adios2/toolkit/format/bp1/BP1Aggregator.cpp index 4962e70071899aa8d0770106b5e71d0f7fe7a5ad..663da16ede1411401d7b4e97fe9e210354e5e7f7 100644 --- a/source/adios2/toolkit/format/bp1/BP1Aggregator.cpp +++ b/source/adios2/toolkit/format/bp1/BP1Aggregator.cpp @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * BP1Aggregator.cpp + * BP1Aggregator.cpp : * * Created on: Mar 21, 2017 * Author: William F Godoy godoywf@ornl.gov @@ -11,15 +11,12 @@ #include "BP1Aggregator.h" /// \cond EXCLUDE_FROM_DOXYGEN -#include <fstream> -#include <ios> -#include <stdexcept> -#include <vector> +#include <numeric> //std::accumulate +#include <unordered_set> /// \endcond -#include <iostream> - #include "adios2/ADIOSMPI.h" +#include "adios2/helper/adiosFunctions.h" namespace adios2 { @@ -33,81 +30,47 @@ BP1Aggregator::BP1Aggregator(MPI_Comm mpiComm, const bool debugMode) MPI_Comm_size(m_MPIComm, &m_SizeMPI); } -std::string BP1Aggregator::GetGlobalProfilingJSON(const std::string &rankLog) +std::vector<char> +BP1Aggregator::SetCollectiveProfilingJSON(const std::string &rankLog) const { - std::string profilingJSON; - - if (m_RankMPI == 0) + // Gather sizes + const size_t rankLogSize = rankLog.size(); + std::vector<size_t> rankLogsSizes = GatherValues(rankLogSize, m_MPIComm); + + // Gatherv JSON per rank + std::vector<char> profilingJSON(3); + const std::string header("[\n"); + const std::string footer("\n]\n"); + size_t gatheredSize = 0; + size_t position = 0; + + if (m_RankMPI == 0) // pre-allocate in destination { - const unsigned int sizeMPI = static_cast<const unsigned int>(m_SizeMPI); - std::vector<std::vector<char>> rankLogs(sizeMPI - 1); // other ranks - std::vector<int> rankLogsSizes(sizeMPI - 1, -1); // init with -1 - std::vector<MPI_Request> requests(sizeMPI); - std::vector<MPI_Status> statuses(sizeMPI); - - // first receive sizes - for (unsigned int i = 1; i < sizeMPI; ++i) - { - MPI_Irecv(&rankLogsSizes[i - 1], 1, MPI_INT, i, 0, m_MPIComm, - &requests[i]); - } + gatheredSize = + std::accumulate(rankLogsSizes.begin(), rankLogsSizes.end(), 0); - for (unsigned int i = 1; i < sizeMPI; ++i) - { - MPI_Wait(&requests[i], &statuses[i]); - if (m_DebugMode) - { - if (rankLogsSizes[i - 1] == -1) - throw std::runtime_error( - "ERROR: couldn't get size from rank " + - std::to_string(i) + - ", in ADIOS aggregator for Profiling.log\n"); - } - rankLogs[i - 1].resize(rankLogsSizes[i - 1]); // allocate with zeros - } - - // receive rankLog from other ranks - for (unsigned int i = 1; i < sizeMPI; ++i) - { - MPI_Irecv(rankLogs[i - 1].data(), rankLogsSizes[i - 1], MPI_CHAR, i, - 1, m_MPIComm, &requests[i]); - } - - for (unsigned int i = 1; i < sizeMPI; ++i) - { - MPI_Wait(&requests[i], &statuses[i]); - } + profilingJSON.resize(gatheredSize + header.size() + footer.size() - 2); + CopyToBuffer(profilingJSON, position, header.c_str(), header.size()); + } - // write global string - // key is to reserve memory first - profilingJSON.reserve(rankLog.size() * m_SizeMPI); + GathervArrays(rankLog.c_str(), rankLog.size(), rankLogsSizes.data(), + rankLogsSizes.size(), &profilingJSON[position], m_MPIComm); - profilingJSON += "[\n"; - profilingJSON += rankLog; - for (unsigned int i = 1; i < sizeMPI; ++i) - { - profilingJSON += ",\n"; - profilingJSON.append(rankLogs[i - 1].data(), - rankLogs[i - 1].size()); - } - profilingJSON += "\n]\n"; // close json - } - else + if (m_RankMPI == 0) // add footer to close JSON { - const int rankLogSize = static_cast<const int>(rankLog.size()); - MPI_Request requestSize; - MPI_Isend(const_cast<int *>(&rankLogSize), 1, MPI_INT, 0, 0, m_MPIComm, - &requestSize); - - MPI_Request requestRankLog; - MPI_Isend(const_cast<char *>(rankLog.c_str()), rankLogSize, MPI_CHAR, 0, - 1, m_MPIComm, &requestRankLog); + position += gatheredSize - 2; + CopyToBuffer(profilingJSON, position, footer.c_str(), footer.size()); } - MPI_Barrier(m_MPIComm); // Barrier here? - return profilingJSON; } +void BP1Aggregator::GathervBuffers(const std::vector<char> &bufferIn, + std::vector<char> &bufferOut, + size_t &position) const +{ + GathervVectors(bufferIn, bufferOut, position, m_MPIComm); +} + } // end namespace format -} // end namespace adios +} // end namespace adios2 diff --git a/source/adios2/toolkit/format/bp1/BP1Aggregator.h b/source/adios2/toolkit/format/bp1/BP1Aggregator.h index f18dcf47bd279d0c8895435098cef78cd9fb31d0..5d977b4b5366b54fe802b7995e15d4e1112e6fd7 100644 --- a/source/adios2/toolkit/format/bp1/BP1Aggregator.h +++ b/source/adios2/toolkit/format/bp1/BP1Aggregator.h @@ -2,7 +2,8 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * BP1Aggregator.h + * BP1Aggregator.h : defines an object that manages MPI aggregation tasks in BP1 + * format * * Created on: Mar 1, 2017 * Author: William F Godoy godoywf@ornl.gov @@ -13,6 +14,8 @@ /// \cond EXCLUDE_FROM_DOXYGEN #include <string> +#include <unordered_map> +#include <vector> /// \endcond #include "adios2/ADIOSConfig.h" @@ -36,6 +39,7 @@ public: /** * Unique constructor * @param mpiComm coming from engine + * @param debugMode true: extra exception checks */ BP1Aggregator(MPI_Comm mpiComm, const bool debugMode = false); @@ -46,13 +50,17 @@ public: * python dictionary format * @param rankLog contain rank profiling info to be aggregated */ - std::string GetGlobalProfilingJSON(const std::string &rankLog); + std::vector<char> + SetCollectiveProfilingJSON(const std::string &rankLog) const; + + void GathervBuffers(const std::vector<char> &bufferIn, + std::vector<char> &bufferOut, size_t &position) const; private: const bool m_DebugMode = false; }; } // end namespace format -} // end namespace adios +} // end namespace adios2 #endif /* ADIOS2_UTILITIES_FORMAT_BP1_BP1AGGREGATOR_H_ */ diff --git a/source/adios2/toolkit/format/bp1/BP1Base.cpp b/source/adios2/toolkit/format/bp1/BP1Base.cpp index 8d4e6a314d3e78031870d1f652c5da7cbc936f40..66515bdda6dfa23bc69b86062578c702da7f774e 100644 --- a/source/adios2/toolkit/format/bp1/BP1Base.cpp +++ b/source/adios2/toolkit/format/bp1/BP1Base.cpp @@ -12,7 +12,8 @@ #include "BP1Base.tcc" #include "adios2/ADIOSTypes.h" //PathSeparator -#include "adios2/helper/adiosFunctions.h" //CreateDirectory, StringToTimeUnit +#include "adios2/helper/adiosFunctions.h" //CreateDirectory, StringToTimeUnit, + // ReadValue namespace adios2 { @@ -20,8 +21,7 @@ namespace format { BP1Base::BP1Base(MPI_Comm mpiComm, const bool debugMode) -: m_HeapBuffer(debugMode), m_BP1Aggregator(mpiComm, debugMode), - m_DebugMode(debugMode) +: m_BP1Aggregator(mpiComm, debugMode), m_DebugMode(debugMode) { // default m_Profiler.IsActive = true; @@ -68,6 +68,10 @@ void BP1Base::InitParameters(const Params ¶meters) { InitParameterVerbose(value); } + else if (key == "CollectiveMetadata") + { + InitParameterCollectiveMetadata(value); + } } // default timer for buffering @@ -82,7 +86,8 @@ void BP1Base::InitParameters(const Params ¶meters) if (useDefaultInitialBufferSize) { - m_HeapBuffer.ResizeData(DefaultInitialBufferSize); + m_Data.Resize(DefaultInitialBufferSize, "in call to Open"); + // m_HeapBuffer.ResizeData(DefaultInitialBufferSize); } } @@ -105,6 +110,12 @@ BP1Base::GetBPBaseNames(const std::vector<std::string> &names) const noexcept return bpBaseNames; } +std::string BP1Base::GetBPMetadataFileName(const std::string &name) const + noexcept +{ + return AddExtension(name, ".bp"); +} + std::vector<std::string> BP1Base::GetBPNames(const std::vector<std::string> &baseNames) const noexcept { @@ -137,28 +148,33 @@ BP1Base::GetBPNames(const std::vector<std::string> &baseNames) const noexcept } // PROTECTED -void BP1Base::InitParameterProfile(const std::string value) +void BP1Base::InitOnOffParameter(const std::string value, bool ¶meter, + const std::string hint) { if (value == "off" || value == "Off") { - m_Profiler.IsActive = false; + parameter = false; } else if (value == "on" || value == "On") { - m_Profiler.IsActive = true; // default + parameter = true; } else { if (m_DebugMode) { throw std::invalid_argument("ERROR: IO SetParameters profile " - "invalid value, valid: " - "profile=on or " - "profile=off, in call to Open\n"); + "invalid value, " + + hint + " in call to Open\n"); } } } +void BP1Base::InitParameterProfile(const std::string value) +{ + InitOnOffParameter(value, m_Profiler.IsActive, "valid: Profile On or Off"); +} + void BP1Base::InitParameterProfileUnits(const std::string value) { TimeUnit timeUnit = StringToTimeUnit(value, m_DebugMode); @@ -195,7 +211,8 @@ void BP1Base::InitParameterBufferGrowth(const std::string value) { throw std::invalid_argument( "ERROR: BufferGrowthFactor value " - "can't be less or equal than 1 (default = 1.5), or couldn't " + "can't be less or equal than 1 (default = 1.5), or " + "couldn't " "convert number,\n additional description:" + description + "\n, in call to Open\n"); } @@ -213,9 +230,8 @@ void BP1Base::InitParameterInitBufferSize(const std::string value) if (value.size() < 2) { throw std::invalid_argument( - "ERROR: wrong value for InitialBufferSize, it must be larger " - "than " - "16Kb (minimum default), in call to Open\n"); + "ERROR: wrong value for InitialBufferSize, it must be " + "larger than 16Kb (minimum default), in call to Open\n"); } } @@ -242,7 +258,8 @@ void BP1Base::InitParameterInitBufferSize(const std::string value) if (!success || bufferSize < DefaultInitialBufferSize) // 16384b { throw std::invalid_argument( - "ERROR: wrong value for InitialBufferSize, it must be larger " + "ERROR: wrong value for InitialBufferSize, it must be " + "larger " "than " "16Kb (minimum default), additional description: " + description + " in call to Open\n"); @@ -253,7 +270,9 @@ void BP1Base::InitParameterInitBufferSize(const std::string value) bufferSize = static_cast<size_t>(std::stoul(number) * factor); } - m_HeapBuffer.ResizeData(bufferSize); + // m_HeapBuffer.ResizeData(bufferSize); + m_Data.Resize(bufferSize, "bufferSize " + std::to_string(bufferSize) + + ", in call to Open"); } void BP1Base::InitParameterMaxBufferSize(const std::string value) @@ -265,7 +284,8 @@ void BP1Base::InitParameterMaxBufferSize(const std::string value) throw std::invalid_argument( "ERROR: couldn't convert value of max_buffer_size IO " "SetParameter, valid syntax: MaxBufferSize=10Gb, " - "MaxBufferSize=1000Mb, MaxBufferSize=16Kb (minimum default), " + "MaxBufferSize=1000Mb, MaxBufferSize=16Kb (minimum " + "default), " " in call to Open"); } } @@ -294,7 +314,8 @@ void BP1Base::InitParameterMaxBufferSize(const std::string value) throw std::invalid_argument( "ERROR: couldn't convert value of max_buffer_size IO " "SetParameter, valid syntax: MaxBufferSize=10Gb, " - "MaxBufferSize=1000Mb, MaxBufferSize=16Kb (minimum default), " + "MaxBufferSize=1000Mb, MaxBufferSize=16Kb (minimum " + "default), " "\nadditional description: " + description + " in call to Open"); } @@ -363,7 +384,8 @@ void BP1Base::InitParameterVerbose(const std::string value) { throw std::invalid_argument( "ERROR: value in Verbose=value in IO SetParameters must be " - "an integer in the range [0,5], \nadditional description: " + + "an integer in the range [0,5], \nadditional " + "description: " + description + "\n, in call to Open\n"); } } @@ -375,6 +397,12 @@ void BP1Base::InitParameterVerbose(const std::string value) m_Verbosity = static_cast<unsigned int>(verbosity); } +void BP1Base::InitParameterCollectiveMetadata(const std::string value) +{ + InitOnOffParameter(value, m_CollectiveMetadata, + "valid: CollectiveMetadata On or Off"); +} + std::vector<uint8_t> BP1Base::GetTransportIDs(const std::vector<std::string> &transportsTypes) const noexcept @@ -425,9 +453,62 @@ size_t BP1Base::GetProcessGroupIndexSize(const std::string name, return pgSize; } +BP1Base::ElementIndexHeader +BP1Base::ReadElementIndexHeader(const std::vector<char> &buffer, + size_t &position) const noexcept +{ + ElementIndexHeader header; + header.Length = ReadValue<uint32_t>(buffer, position); + header.MemberID = ReadValue<uint32_t>(buffer, position); + header.GroupName = ReadBP1String(buffer, position); + header.Name = ReadBP1String(buffer, position); + header.Path = ReadBP1String(buffer, position); + header.DataType = ReadValue<int8_t>(buffer, position); + header.CharacteristicsSetsCount = ReadValue<uint64_t>(buffer, position); + + return header; +} + +std::string BP1Base::ReadBP1String(const std::vector<char> &buffer, + size_t &position) const noexcept +{ + const size_t size = + static_cast<size_t>(ReadValue<uint16_t>(buffer, position)); + + if (size == 0) + { + return std::string(); + } + + const std::string values(&buffer[position], size); + position += size; + return values; +} + +void BP1Base::ProfilerStart(const std::string process) +{ + if (m_Profiler.IsActive) + { + m_Profiler.Timers.at(process).Resume(); + } +} + +void BP1Base::ProfilerStop(const std::string process) +{ + if (m_Profiler.IsActive) + { + m_Profiler.Timers.at(process).Pause(); + } +} + #define declare_template_instantiation(T) \ template BP1Base::ResizeResult BP1Base::ResizeBuffer( \ - const Variable<T> &variable); + const Variable<T> &variable); \ + \ + template BP1Base::Characteristics<T> \ + BP1Base::ReadElementIndexCharacteristics(const std::vector<char> &buffer, \ + size_t &position, \ + const bool untilTimeStep) const; ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) #undef declare_template_instantiation diff --git a/source/adios2/toolkit/format/bp1/BP1Base.h b/source/adios2/toolkit/format/bp1/BP1Base.h index 083c3861ab20268ccfd283e07e389e3c96228bf6..92ac6b09e3e037d289c3fb63dba64db81e901f10 100644 --- a/source/adios2/toolkit/format/bp1/BP1Base.h +++ b/source/adios2/toolkit/format/bp1/BP1Base.h @@ -12,7 +12,7 @@ #define ADIOS2_TOOLKIT_FORMAT_BP1_BP1BASE_H_ /// \cond EXCLUDE_FROM_DOXYGEN -#include <memory> //std::shared_ptr +#include <string> #include <vector> /// \endcond @@ -21,9 +21,8 @@ #include "adios2/ADIOSMacros.h" #include "adios2/ADIOSTypes.h" #include "adios2/core/Variable.h" -#include "adios2/toolkit/capsule/heap/STLVector.h" +#include "adios2/toolkit/format/BufferSTL.h" #include "adios2/toolkit/format/bp1/BP1Aggregator.h" -#include "adios2/toolkit/format/bp1/BP1Structs.h" #include "adios2/toolkit/profiling/iochrono/IOChrono.h" namespace adios2 @@ -38,11 +37,70 @@ class BP1Base { public: + /** + * Metadata index used for Variables and Attributes, needed in a + * container for characteristic sets merge independently for each Variable + * or Attribute + */ + struct SerialElementIndex + { + /** buffer containing the metadata index, start with 500bytes */ + std::vector<char> Buffer; + /** number of characteristics sets (time and spatial aggregation) */ + uint64_t Count = 0; + /** unique ID assigned to each variable for counter */ + const uint32_t MemberID; + + SerialElementIndex(const uint32_t memberID, + const size_t bufferSize = 500) + : MemberID(memberID) + { + Buffer.reserve(bufferSize); + } + }; + + struct MetadataSet + { + /** + * updated with advance step, if append it will be updated to last, + * starts with one in ADIOS1 + */ + uint32_t TimeStep = 1; + + /** single buffer for PGIndex */ + SerialElementIndex PGIndex = SerialElementIndex(0); + + // no priority for now + /** @brief key: variable name, value: bp metadata variable index */ + std::unordered_map<std::string, SerialElementIndex> VarsIndices; + + /** @brief key: attribute name, value: bp metadata attribute index */ + std::unordered_map<std::string, SerialElementIndex> AttributesIndices; + + bool AreAttributesWritten = false; + + /** Fixed size for mini footer */ + const unsigned int MiniFooterSize = 28; + + /** number of current PGs */ + uint64_t DataPGCount = 0; + /** current PG initial ( relative ) position in data buffer */ + size_t DataPGLengthPosition = 0; + /** number of variables in current PG */ + uint32_t DataPGVarsCount = 0; + /** current PG variable count ( relative ) position */ + size_t DataPGVarsCountPosition = 0; + /** true: currently writing to a pg, false: no current pg */ + bool DataPGIsOpen = false; + }; + /** statistics verbosity, only 0 is supported */ unsigned int m_Verbosity = 0; /** contains data buffer and position */ - capsule::STLVector m_HeapBuffer; + // capsule::STLVector m_HeapBuffer; + BufferSTL m_Data; + BufferSTL m_Metadata; /** memory growth factor,s set by the user */ float m_GrowthFactor = DefaultBufferGrowthFactor; @@ -51,7 +109,7 @@ public: size_t m_MaxBufferSize = DefaultMaxBufferSize; /** contains bp1 format metadata indices*/ - BP1MetadataSet m_MetadataSet; + MetadataSet m_MetadataSet; /** object that takes care of all MPI aggregation tasks */ BP1Aggregator m_BP1Aggregator; @@ -63,6 +121,9 @@ public: /** buffering and MPI aggregation profiling info, set by user */ profiling::IOChrono m_Profiler; + /** Default: write collective metadata in Capsule metadata. */ + bool m_CollectiveMetadata = true; + /** * Unique constructor * @param mpiComm for m_BP1Aggregator @@ -90,6 +151,8 @@ public: std::vector<std::string> GetBPNames(const std::vector<std::string> &baseNames) const noexcept; + std::string GetBPMetadataFileName(const std::string &name) const noexcept; + /** Return type of the CheckAllocation function. */ enum class ResizeResult { @@ -193,7 +256,7 @@ protected: /** * Characteristic ID in variable metadata */ - enum VariableCharacteristicID + enum CharacteristicID { characteristic_value = 0, //!< characteristic_value characteristic_min = 1, //!< Used to read in older bp file format @@ -224,22 +287,46 @@ protected: template <class T> struct Stats { - T Min; - T Max; uint64_t Offset; uint64_t PayloadOffset; - uint32_t TimeIndex; + T Min; + T Max; + uint32_t TimeStep; + uint32_t FileIndex; uint32_t MemberID; + }; - // unsigned long int count; - // long double sum; - // long double sumSquare; - // unsigned long int histogram - // bool finite?? + template <class T> + struct Characteristics + { + Stats<T> Statistics; + std::vector<uint64_t> Dimensions; + uint32_t Length; + uint8_t Count; + }; + + struct ElementIndexHeader + { + uint64_t CharacteristicsSetsCount; + uint32_t Length; + uint32_t MemberID; + std::string GroupName; + std::string Name; + std::string Path; + uint8_t DataType; }; + /** + * Functions used for setting bool parameters of type On Off + * @param value + * @param parameter + * @param hint + */ + void InitOnOffParameter(const std::string value, bool ¶meter, + const std::string hint); + /** profile=on (default) generate profiling.log - * profile=off */ + * profile=off */ void InitParameterProfile(const std::string value); /** profile_units=s (default) (mus, ms, s,m,h) from ADIOSTypes.h TimeUnit */ @@ -259,9 +346,12 @@ protected: /** Set available number of threads for vector operations */ void InitParameterThreads(const std::string value); - /** verbose file level=0 (default) */ + /** verbose file level=0 (default), not active */ void InitParameterVerbose(const std::string value); + /** verbose file level=0 (default) */ + void InitParameterCollectiveMetadata(const std::string value); + /** * Returns data type index from enum Datatypes * @param variable input variable @@ -287,9 +377,40 @@ protected: const std::string timeStepName, const size_t transportsSize) const noexcept; + ElementIndexHeader ReadElementIndexHeader(const std::vector<char> &buffer, + size_t &position) const noexcept; + /** - * Returns the estimated variable index size - * @param variable + * Read variable characteristics. + * @param buffer + * @param position + * @param untilTimeStep, stop if time step characteristic is found + * @return + */ + template <class T> + Characteristics<T> + ReadElementIndexCharacteristics(const std::vector<char> &buffer, + size_t &position, + const bool untilTimeStep = false) const; + + /** + * Common function to extract a bp string, 2 bytes for length + contents + * @param buffer + * @param position + * @return + */ + std::string ReadBP1String(const std::vector<char> &buffer, + size_t &position) const noexcept; + + void ProfilerStart(const std::string process); + + void ProfilerStop(const std::string process); + +private: + /** + * Returns the estimated variable index size. Used by ResizeBuffer public + * function + * @param variable input */ template <class T> size_t GetVariableIndexSize(const Variable<T> &variable) const noexcept; @@ -297,7 +418,12 @@ protected: #define declare_template_instantiation(T) \ extern template BP1Base::ResizeResult BP1Base::ResizeBuffer( \ - const Variable<T> &variable); + const Variable<T> &variable); \ + \ + extern template BP1Base::Characteristics<T> \ + BP1Base::ReadElementIndexCharacteristics(const std::vector<char> &buffer, \ + size_t &position, \ + const bool untilTimeStep) const; ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) #undef declare_template_instantiation diff --git a/source/adios2/toolkit/format/bp1/BP1Base.tcc b/source/adios2/toolkit/format/bp1/BP1Base.tcc index 58b361b465d985fbfa27db2e416824c45ea7ca2b..fa1f4dda2e2a4c14d42d21a8533a4c71d1ef4e7f 100644 --- a/source/adios2/toolkit/format/bp1/BP1Base.tcc +++ b/source/adios2/toolkit/format/bp1/BP1Base.tcc @@ -15,169 +15,274 @@ #include <cmath> //std::min -#include "adios2/helper/adiosMath.h" //NextExponentialSize +#include "adios2/helper/adiosFunctions.h" //NextExponentialSize, CopyFromBuffer namespace adios2 { namespace format { +template <class T> +BP1Base::ResizeResult BP1Base::ResizeBuffer(const Variable<T> &variable) +{ + size_t currentCapacity = m_Data.m_Buffer.capacity(); + size_t variableData = + GetVariableIndexSize(variable) + variable.PayLoadSize(); + size_t requiredCapacity = variableData + m_Data.m_Position; + + ResizeResult result = ResizeResult::Unchanged; + + if (variableData > m_MaxBufferSize) + { + throw std::runtime_error( + "ERROR: variable " + variable.m_Name + " data size: " + + std::to_string(static_cast<float>(variableData) / (1024. * 1024.)) + + " Mb is too large for adios2 bp MaxBufferSize=" + + std::to_string(static_cast<float>(m_MaxBufferSize) / + (1024. * 1024.)) + + "Mb, try increasing MaxBufferSize in call to IO SetParameters, in " + "call to Write\n"); + } + + if (requiredCapacity <= currentCapacity) + { + // do nothing, unchanged is default + } + else if (requiredCapacity > m_MaxBufferSize) + { + if (currentCapacity < m_MaxBufferSize) + { + m_Data.Resize(m_MaxBufferSize, " when resizing buffer to " + + std::to_string(m_MaxBufferSize) + + "bytes, in call to variable " + + variable.m_Name + " Write"); + } + result = ResizeResult::Flush; + } + else // buffer must grow + { + if (currentCapacity < m_MaxBufferSize) + { + const size_t nextSize = + std::min(m_MaxBufferSize, + NextExponentialSize(requiredCapacity, currentCapacity, + m_GrowthFactor)); + m_Data.Resize(nextSize, " when resizing buffer to " + + std::to_string(nextSize) + + "bytes, in call to variable " + + variable.m_Name + " Write"); + result = ResizeResult::Success; + } + } + + return result; +} + +// PROTECTED template <> int8_t BP1Base::GetDataType<std::string>() const noexcept { - return type_string; + const int8_t type = static_cast<const int8_t>(type_string); + return type; } template <> int8_t BP1Base::GetDataType<char>() const noexcept { - return type_byte; + const int8_t type = static_cast<const int8_t>(type_byte); + return type; } template <> int8_t BP1Base::GetDataType<signed char>() const noexcept { - return type_byte; + const int8_t type = static_cast<const int8_t>(type_byte); + return type; } template <> int8_t BP1Base::GetDataType<short>() const noexcept { - return type_short; + const int8_t type = static_cast<const int8_t>(type_short); + return type; } template <> int8_t BP1Base::GetDataType<int>() const noexcept { - return type_integer; + const int8_t type = static_cast<const int8_t>(type_integer); + return type; } template <> int8_t BP1Base::GetDataType<long int>() const noexcept { - return type_long; + const int8_t type = static_cast<const int8_t>(type_long); + return type; } template <> int8_t BP1Base::GetDataType<long long int>() const noexcept { - return type_long; + const int8_t type = static_cast<const int8_t>(type_long); + return type; } template <> int8_t BP1Base::GetDataType<unsigned char>() const noexcept { - return type_unsigned_byte; + const int8_t type = static_cast<const int8_t>(type_unsigned_byte); + return type; } + template <> int8_t BP1Base::GetDataType<unsigned short>() const noexcept { - return type_unsigned_short; + const int8_t type = static_cast<const int8_t>(type_unsigned_short); + return type; } + template <> int8_t BP1Base::GetDataType<unsigned int>() const noexcept { - return type_unsigned_integer; + const int8_t type = static_cast<const int8_t>(type_unsigned_integer); + return type; } template <> int8_t BP1Base::GetDataType<unsigned long int>() const noexcept { - return type_unsigned_long; + const int8_t type = static_cast<const int8_t>(type_unsigned_long); + return type; } template <> int8_t BP1Base::GetDataType<unsigned long long int>() const noexcept { - return type_unsigned_long; + const int8_t type = static_cast<const int8_t>(type_unsigned_long); + return type; } template <> int8_t BP1Base::GetDataType<float>() const noexcept { - return type_real; + const int8_t type = static_cast<const int8_t>(type_real); + return type; } template <> int8_t BP1Base::GetDataType<double>() const noexcept { - return type_double; + const int8_t type = static_cast<const int8_t>(type_double); + return type; } template <> int8_t BP1Base::GetDataType<long double>() const noexcept { - return type_long_double; + const int8_t type = static_cast<const int8_t>(type_long_double); + return type; } template <> int8_t BP1Base::GetDataType<cfloat>() const noexcept { - return type_complex; + const int8_t type = static_cast<const int8_t>(type_complex); + return type; } template <> int8_t BP1Base::GetDataType<cdouble>() const noexcept { - return type_double_complex; + const int8_t type = static_cast<const int8_t>(type_double_complex); + return type; } template <> int8_t BP1Base::GetDataType<cldouble>() const noexcept { - return type_long_double_complex; + const int8_t type = static_cast<const int8_t>(type_long_double_complex); + return type; } template <class T> -BP1Base::ResizeResult BP1Base::ResizeBuffer(const Variable<T> &variable) +BP1Base::Characteristics<T> +BP1Base::ReadElementIndexCharacteristics(const std::vector<char> &buffer, + size_t &position, + const bool untilTimeStep) const { - size_t currentCapacity = m_HeapBuffer.m_Data.capacity(); - size_t variableData = - GetVariableIndexSize(variable) + variable.PayLoadSize(); - size_t requiredCapacity = variableData + m_HeapBuffer.m_DataPosition; + Characteristics<T> characteristics; + characteristics.Count = ReadValue<uint8_t>(buffer, position); + characteristics.Length = ReadValue<uint32_t>(buffer, position); - ResizeResult result = ResizeResult::Unchanged; + bool foundTimeStep = false; - if (variableData > m_MaxBufferSize) + while (position < characteristics.Length + 5) { - throw std::runtime_error( - "ERROR: variable " + variable.m_Name + " data size: " + - std::to_string(static_cast<float>(variableData) / (1024. * 1024.)) + - " Mb is too large for adios2 bp MaxBufferSize=" + - std::to_string(static_cast<float>(m_MaxBufferSize) / - (1024. * 1024.)) + - "Mb, try increasing MaxBufferSize in call to IO SetParameters, in " - "call to Write\n"); - } + const uint8_t id = ReadValue<uint8_t>(buffer, position); - if (requiredCapacity <= currentCapacity) - { - // do nothing, unchanged is default - } - else if (requiredCapacity > m_MaxBufferSize) - { - if (currentCapacity < m_MaxBufferSize) + switch (id) { - m_HeapBuffer.ResizeData(m_MaxBufferSize); + case (characteristic_time_index): + characteristics.Statistics.TimeStep = + ReadValue<uint32_t>(buffer, position); + foundTimeStep = true; + break; + + case (characteristic_file_index): + characteristics.Statistics.FileIndex = + ReadValue<uint32_t>(buffer, position); + break; + + case (characteristic_value): + // TODO make sure it's string or string array + characteristics.Statistics.Min = ReadValue<T>(buffer, position); + break; + + case (characteristic_min): + characteristics.Statistics.Min = ReadValue<T>(buffer, position); + break; + + case (characteristic_max): + characteristics.Statistics.Max = ReadValue<T>(buffer, position); + break; + + case (characteristic_offset): + characteristics.Statistics.Offset = + ReadValue<uint64_t>(buffer, position); + break; + + case (characteristic_payload_offset): + characteristics.Statistics.PayloadOffset = + ReadValue<uint64_t>(buffer, position); + break; + + case (characteristic_dimensions): + const uint8_t dimensionsCount = + ReadValue<uint8_t>(buffer, position); + characteristics.Dimensions.reserve(dimensionsCount * 3); + + ReadValue<uint16_t>(buffer, position); // length (not used) + + for (auto d = 0; d < dimensionsCount * 3; ++d) + { + characteristics.Dimensions.push_back( + ReadValue<uint64_t>(buffer, position)); + } + break; + // TODO: implement compression and BP1 Stats characteristics } - result = ResizeResult::Flush; - } - else // buffer must grow - { - if (currentCapacity < m_MaxBufferSize) + + if (untilTimeStep && foundTimeStep) { - const size_t nextSize = - std::min(m_MaxBufferSize, - NextExponentialSize(requiredCapacity, currentCapacity, - m_GrowthFactor)); - m_HeapBuffer.ResizeData(nextSize); - result = ResizeResult::Success; + break; } } - return result; + return characteristics; } +// PRIVATE template <class T> size_t BP1Base::GetVariableIndexSize(const Variable<T> &variable) const noexcept { @@ -215,6 +320,6 @@ size_t BP1Base::GetVariableIndexSize(const Variable<T> &variable) const noexcept } } // end namespace format -} // end namespace adios +} // end namespace adios2 #endif /* ADIOS2_TOOLKIT_FORMAT_BP1_BP1BASE_TCC_ */ diff --git a/source/adios2/toolkit/format/bp1/BP1Reader.cpp b/source/adios2/toolkit/format/bp1/BP1Reader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0401be9c3ad2e6911c71f5e0966d0d6f2b52d441 --- /dev/null +++ b/source/adios2/toolkit/format/bp1/BP1Reader.cpp @@ -0,0 +1,25 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * BP1Reader.cpp + * + * Created on: Sep 7, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include "BP1Reader.h" +#include "BP1Reader.tcc" + +namespace adios2 +{ +namespace format +{ + +BP1Reader::BP1Reader(MPI_Comm mpiComm, const bool debugMode) +: BP1Base(mpiComm, debugMode) +{ +} + +} // end namespace format +} // end namespace adios2 diff --git a/source/adios2/toolkit/format/bp1/BP1Reader.h b/source/adios2/toolkit/format/bp1/BP1Reader.h new file mode 100644 index 0000000000000000000000000000000000000000..5996af7135a7ad52683390830462264fa98d2b9d --- /dev/null +++ b/source/adios2/toolkit/format/bp1/BP1Reader.h @@ -0,0 +1,44 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * BP1Reader.h + * + * Created on: Sep 7, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef ADIOS2_TOOLKIT_FORMAT_BP1_BP1READER_H_ +#define ADIOS2_TOOLKIT_FORMAT_BP1_BP1READER_H_ + +/// \cond EXCLUDE_FROM_DOXYGEN +#include <vector> +/// \endcond + +#include "adios2/ADIOSConfig.h" +#include "adios2/ADIOSTypes.h" +#include "adios2/toolkit/format/bp1/BP1Base.h" + +namespace adios2 +{ +namespace format +{ + +class BP1Reader : BP1Base +{ + +public: + /** + * Unique constructor + * @param mpiComm + * @param debug true: extra checks + */ + BP1Reader(MPI_Comm mpiComm, const bool debugMode); + + ~BP1Reader() = default; +}; + +} // end namespace format +} // end namespace adios2 + +#endif /* ADIOS2_TOOLKIT_FORMAT_BP1_BP1READER_H_ */ diff --git a/source/adios2/toolkit/format/bp1/BP1Reader.tcc b/source/adios2/toolkit/format/bp1/BP1Reader.tcc new file mode 100644 index 0000000000000000000000000000000000000000..c9a63fe17940c9fca70cd4360c95ba1f23eb6767 --- /dev/null +++ b/source/adios2/toolkit/format/bp1/BP1Reader.tcc @@ -0,0 +1,24 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * BP1Reader.tcc + * + * Created on: Sep 7, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef ADIOS2_TOOLKIT_FORMAT_BP1_BP1READER_TCC_ +#define ADIOS2_TOOLKIT_FORMAT_BP1_BP1READER_TCC_ + +#include "BP1Reader.h" + +namespace adios2 +{ +namespace format +{ + +} // end namespace format +} // end namespace adios2 + +#endif /* ADIOS2_TOOLKIT_FORMAT_BP1_BP1READER_TCC_ */ diff --git a/source/adios2/toolkit/format/bp1/BP1Structs.h b/source/adios2/toolkit/format/bp1/BP1Structs.h deleted file mode 100644 index 9d1724c9f2210858fb063500ba5a1c3e03a26d57..0000000000000000000000000000000000000000 --- a/source/adios2/toolkit/format/bp1/BP1Structs.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * BP1Structs.h - * - * Created on: Apr 3, 2017 - * Author: William F Godoy godoywf@ornl.gov - */ - -#ifndef ADIOS2_TOOLKIT_FORMAT_BP1_BP1STRUCTS_H_ -#define ADIOS2_TOOLKIT_FORMAT_BP1_BP1STRUCTS_H_ - -/// \cond EXCLUDE_FROM_DOXYGEN -#include <cstdint> -#include <string> -#include <unordered_map> -#include <vector> - -/// \endcond - -#include "adios2/ADIOSConfig.h" -#include "adios2/ADIOSTypes.h" -#include "adios2/toolkit/profiling/iochrono/IOChrono.h" - -namespace adios2 -{ -namespace format -{ - -/** - * Metadata index used for Variables and Attributes, needed in a container for - * characteristic - * sets merge independently for each Variable or Attribute - */ -struct BP1Index -{ - std::vector<char> Buffer; ///< metadata variable index, start with 100Kb - /** number of characteristics sets (time and spatial aggregation) */ - uint64_t Count = 0; - /** unique ID assigned to each variable for counter */ - const uint32_t MemberID; - - BP1Index(const uint32_t memberID) : MemberID(memberID) - { - Buffer.reserve(500); - } -}; - -/** - * Single struct that tracks metadata indices in bp format - */ -struct BP1MetadataSet -{ - /** - * updated with advance step, if append it will be updated to last, - * starts with one in ADIOS1 - */ - uint32_t TimeStep = 1; - - /** single buffer for PGIndex */ - BP1Index PGIndex = BP1Index(0); - - // no priority for now - /** @brief key: variable name, value: bp metadata variable index */ - std::unordered_map<std::string, BP1Index> VarsIndices; - - /** @brief key: attribute name, value: bp metadata attribute index */ - std::unordered_map<std::string, BP1Index> AttributesIndices; - - bool AreAttributesWritten = false; - - /** Fixed size for mini footer */ - const unsigned int MiniFooterSize = 28; - - // PG (relative) positions in Data buffer, to be updated every advance step - // or init - /** number of current PGs */ - uint64_t DataPGCount = 0; - /** current PG initial ( relative ) position in data buffer */ - size_t DataPGLengthPosition = 0; - /** number of variables in current PG */ - uint32_t DataPGVarsCount = 0; - /** current PG variable count ( relative ) position */ - size_t DataPGVarsCountPosition = 0; - - /** true: currently writing to a pg, false: no current pg */ - bool DataPGIsOpen = false; -}; - -} // end namespace format -} // end namespace adios2 - -#endif /* ADIOS2_TOOLKIT_FORMAT_BP1_BP1STRUCTS_H_ */ diff --git a/source/adios2/toolkit/format/bp1/BP1Writer.cpp b/source/adios2/toolkit/format/bp1/BP1Writer.cpp index 103d56e03a0b944ccd2c0a9d1c3d83eec097055d..e0f0586f63b9b738f05252bce74dbff2c1c95141 100644 --- a/source/adios2/toolkit/format/bp1/BP1Writer.cpp +++ b/source/adios2/toolkit/format/bp1/BP1Writer.cpp @@ -11,16 +11,21 @@ #include "BP1Writer.h" #include "BP1Writer.tcc" +#include <chrono> +#include <future> #include <string> #include <vector> -#include "adios2/helper/adiosFunctions.h" //GetType<T> +#include "adios2/helper/adiosFunctions.h" //GetType<T>, ReadValue<T>, + // ReduceValue<T> namespace adios2 { namespace format { +std::mutex BP1Writer::m_Mutex; + BP1Writer::BP1Writer(MPI_Comm mpiComm, const bool debugMode) : BP1Base(mpiComm, debugMode) { @@ -30,15 +35,11 @@ void BP1Writer::WriteProcessGroupIndex( const std::string hostLanguage, const std::vector<std::string> &transportsTypes) noexcept { - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("buffering").Resume(); - } - + ProfilerStart("buffering"); std::vector<char> &metadataBuffer = m_MetadataSet.PGIndex.Buffer; - std::vector<char> &dataBuffer = m_HeapBuffer.m_Data; - size_t &dataPosition = m_HeapBuffer.m_DataPosition; + std::vector<char> &dataBuffer = m_Data.m_Buffer; + size_t &dataPosition = m_Data.m_Position; m_MetadataSet.DataPGLengthPosition = dataPosition; dataPosition += 8; // skip pg length (8) @@ -74,7 +75,7 @@ void BP1Writer::WriteProcessGroupIndex( CopyToBuffer(dataBuffer, dataPosition, &m_MetadataSet.TimeStep); // offset to pg in data in metadata which is the current absolute position - InsertU64(metadataBuffer, m_HeapBuffer.m_DataAbsolutePosition); + InsertU64(metadataBuffer, m_Data.m_AbsolutePosition); // Back to writing metadata pg index length (length of group) const uint16_t metadataPGIndexLength = static_cast<const uint16_t>( @@ -101,88 +102,61 @@ void BP1Writer::WriteProcessGroupIndex( } // update absolute position - m_HeapBuffer.m_DataAbsolutePosition += + m_Data.m_AbsolutePosition += dataPosition - m_MetadataSet.DataPGLengthPosition; // pg vars count and position m_MetadataSet.DataPGVarsCount = 0; m_MetadataSet.DataPGVarsCountPosition = dataPosition; // add vars count and length dataPosition += 12; - m_HeapBuffer.m_DataAbsolutePosition += 12; // add vars count and length + m_Data.m_AbsolutePosition += 12; // add vars count and length ++m_MetadataSet.DataPGCount; m_MetadataSet.DataPGIsOpen = true; - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("buffering").Pause(); - } + ProfilerStop("buffering"); } void BP1Writer::Advance(IO &io) { - // enforce memory policy here to restrict buffer size for each timestep - // this is flushing - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("buffering").Resume(); - } + ProfilerStart("buffering"); if (m_MaxBufferSize == DefaultMaxBufferSize) { - // current position + 1Kb chunk tolerance - m_MaxBufferSize = m_HeapBuffer.m_DataPosition + 64; + m_MaxBufferSize = m_Data.m_Position + 64; } - FlattenData(io); + SerializeData(io); ++m_MetadataSet.TimeStep; - - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("buffering").Pause(); - } + ProfilerStop("buffering"); } void BP1Writer::Flush(IO &io) { - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("buffering").Resume(); - } - - FlattenData(io); - - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("buffering").Pause(); - } + ProfilerStart("buffering"); + SerializeData(io); + ProfilerStop("buffering"); } void BP1Writer::Close(IO &io) noexcept { - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("buffering").Resume(); - } + ProfilerStart("buffering"); if (!m_IsClosed) { if (m_MetadataSet.DataPGIsOpen) { - FlattenData(io); + SerializeData(io); } - FlattenMetadata(); + SerializeMetadataInData(); - m_Profiler.Bytes.at("buffering") += m_HeapBuffer.m_DataAbsolutePosition; + m_Profiler.Bytes.at("buffering") += m_Data.m_AbsolutePosition; m_IsClosed = true; } - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("buffering").Pause(); - } + ProfilerStop("buffering"); } std::string BP1Writer::GetRankProfilingJSON( @@ -242,10 +216,17 @@ std::string BP1Writer::GetRankProfilingJSON( return rankLog; } -std::string -BP1Writer::AggregateProfilingJSON(const std::string &rankProfilingLog) noexcept +std::vector<char> +BP1Writer::AggregateProfilingJSON(const std::string &rankProfilingLog) +{ + return m_BP1Aggregator.SetCollectiveProfilingJSON(rankProfilingLog); +} + +void BP1Writer::AggregateCollectiveMetadata() { - return m_BP1Aggregator.GetGlobalProfilingJSON(rankProfilingLog); + AggregateIndex(m_MetadataSet.PGIndex, m_MetadataSet.DataPGCount); + AggregateMergeIndex(m_MetadataSet.VarsIndices); + AggregateMergeIndex(m_MetadataSet.AttributesIndices); } // PRIVATE FUNCTIONS @@ -253,8 +234,9 @@ void BP1Writer::WriteAttributes(IO &io) { const auto attributesDataMap = io.GetAttributesDataMap(); - auto &buffer = m_HeapBuffer.m_Data; - auto &position = m_HeapBuffer.m_DataPosition; + auto &buffer = m_Data.m_Buffer; + auto &position = m_Data.m_Position; + auto &absolutePosition = m_Data.m_AbsolutePosition; // used only to update m_HeapBuffer.m_DataAbsolutePosition; const size_t attributesCountPosition = position; @@ -268,7 +250,7 @@ void BP1Writer::WriteAttributes(IO &io) const size_t attributesLengthPosition = position; position += 8; // skip attributes length - m_HeapBuffer.m_DataAbsolutePosition += position - attributesCountPosition; + absolutePosition += position - attributesCountPosition; uint32_t memberID = 0; @@ -284,7 +266,7 @@ void BP1Writer::WriteAttributes(IO &io) else if (type == GetType<T>()) \ { \ Stats<T> stats; \ - stats.Offset = m_HeapBuffer.m_DataAbsolutePosition; \ + stats.Offset = absolutePosition; \ stats.MemberID = memberID; \ Attribute<T> &attribute = io.GetAttribute<T>(name); \ WriteAttributeInData(attribute, stats); \ @@ -395,15 +377,15 @@ void BP1Writer::WriteNameRecord(const std::string name, CopyToBuffer(buffer, position, name.c_str(), length); } -BP1Index & -BP1Writer::GetBP1Index(const std::string name, - std::unordered_map<std::string, BP1Index> &indices, - bool &isNew) const noexcept +BP1Writer::SerialElementIndex &BP1Writer::GetSerialElementIndex( + const std::string &name, + std::unordered_map<std::string, SerialElementIndex> &indices, + bool &isNew) const noexcept { auto itName = indices.find(name); if (itName == indices.end()) { - indices.emplace(name, BP1Index(indices.size())); + indices.emplace(name, SerialElementIndex(indices.size())); isNew = true; return indices.at(name); } @@ -412,10 +394,11 @@ BP1Writer::GetBP1Index(const std::string name, return itName->second; } -void BP1Writer::FlattenData(IO &io) noexcept +void BP1Writer::SerializeData(IO &io) noexcept { - auto &buffer = m_HeapBuffer.m_Data; - auto &position = m_HeapBuffer.m_DataPosition; + auto &buffer = m_Data.m_Buffer; + auto &position = m_Data.m_Position; + auto &absolutePosition = m_Data.m_AbsolutePosition; // vars count and Length (only for PG) CopyToBuffer(buffer, m_MetadataSet.DataPGVarsCountPosition, @@ -434,7 +417,7 @@ void BP1Writer::FlattenData(IO &io) noexcept else { position += 12; - m_HeapBuffer.m_DataAbsolutePosition += 12; + absolutePosition += 12; } // Finish writing pg group length without record itself @@ -445,11 +428,11 @@ void BP1Writer::FlattenData(IO &io) noexcept m_MetadataSet.DataPGIsOpen = false; } -void BP1Writer::FlattenMetadata() noexcept +void BP1Writer::SerializeMetadataInData() noexcept { auto lf_SetIndexCountLength = - [](std::unordered_map<std::string, BP1Index> &indices, uint32_t &count, - uint64_t &length) { + [](std::unordered_map<std::string, SerialElementIndex> &indices, + uint32_t &count, uint64_t &length) { count = indices.size(); length = 0; @@ -466,7 +449,7 @@ void BP1Writer::FlattenMetadata() noexcept auto lf_FlattenIndices = [](const uint32_t count, const uint64_t length, - const std::unordered_map<std::string, BP1Index> &indices, + const std::unordered_map<std::string, SerialElementIndex> &indices, std::vector<char> &buffer, size_t &position) { CopyToBuffer(buffer, position, &count); @@ -500,12 +483,14 @@ void BP1Writer::FlattenMetadata() noexcept (pgLength + 16) + (varsLength + 12) + (attributesLength + 12) + m_MetadataSet.MiniFooterSize); - auto &buffer = m_HeapBuffer.m_Data; - auto &position = m_HeapBuffer.m_DataPosition; + auto &buffer = m_Data.m_Buffer; + auto &position = m_Data.m_Position; + auto &absolutePosition = m_Data.m_AbsolutePosition; // reserve data to fit metadata, // must replace with growth buffer strategy? - m_HeapBuffer.ResizeData(position + footerSize); + m_Data.Resize(position + footerSize, + " when writing metadata in bp data buffer"); // write pg index CopyToBuffer(buffer, position, &pgCount); @@ -522,7 +507,7 @@ void BP1Writer::FlattenMetadata() noexcept // getting absolute offsets, minifooter is 28 bytes for now const uint64_t offsetPGIndex = - static_cast<const uint64_t>(m_HeapBuffer.m_DataAbsolutePosition); + static_cast<const uint64_t>(absolutePosition); const uint64_t offsetVarsIndex = static_cast<const uint64_t>(offsetPGIndex + (pgLength + 16)); const uint64_t offsetAttributeIndex = @@ -544,12 +529,498 @@ void BP1Writer::FlattenMetadata() noexcept { } - m_HeapBuffer.m_DataAbsolutePosition += footerSize; + absolutePosition += footerSize; if (m_Profiler.IsActive) { - m_Profiler.Bytes.emplace("buffering", - m_HeapBuffer.m_DataAbsolutePosition); + m_Profiler.Bytes.emplace("buffering", absolutePosition); + } +} + +void BP1Writer::AggregateIndex(const SerialElementIndex &index, + const size_t count) +{ + auto &buffer = m_Metadata.m_Buffer; + auto &position = m_Metadata.m_Position; + + size_t countPosition = position; + const size_t totalCount = + ReduceValues<size_t>(count, m_BP1Aggregator.m_MPIComm); + + if (m_BP1Aggregator.m_RankMPI == 0) + { + // Write count + position += 16; + m_Metadata.Resize(position, " in call to AggregateIndex bp1 metadata"); + const uint64_t totalCountU64 = static_cast<const uint64_t>(totalCount); + CopyToBuffer(buffer, countPosition, &totalCountU64); + } + + // write contents + GathervVectors(index.Buffer, buffer, position, m_BP1Aggregator.m_MPIComm); + + // get total length and write it after count and before index + if (m_BP1Aggregator.m_RankMPI == 0) + { + const uint64_t totalLengthU64 = + static_cast<const uint64_t>(position - countPosition - 8); + CopyToBuffer(buffer, countPosition, &totalLengthU64); + } +} + +void BP1Writer::AggregateMergeIndex( + const std::unordered_map<std::string, SerialElementIndex> &indices) noexcept +{ + // first serialize index + std::vector<char> serializedIndices = SerializeIndices(indices); + // gather in rank 0 + std::vector<char> gatheredSerialIndices; + size_t gatheredSerialIndicesPosition = 0; + + GathervVectors(serializedIndices, gatheredSerialIndices, + gatheredSerialIndicesPosition, m_BP1Aggregator.m_MPIComm); + + // deallocate local serialized Indices + std::vector<char>().swap(serializedIndices); + + // deserialize in [name][rank] order + const std::unordered_map<std::string, std::vector<SerialElementIndex>> + nameRankIndices = + DeserializeIndicesPerRankThreads(gatheredSerialIndices); + + // deallocate gathered serial indices (full in rank 0 only) + std::vector<char>().swap(gatheredSerialIndices); + + // to write count and length + auto &buffer = m_Metadata.m_Buffer; + auto &position = m_Metadata.m_Position; + + size_t countPosition = position; + + if (m_BP1Aggregator.m_RankMPI == 0) + { + // Write count + position += 12; + m_Metadata.Resize(position, + ", in call to AggregateMergeIndex bp1 metadata"); + const uint64_t totalCountU64 = + static_cast<const uint64_t>(nameRankIndices.size()); + CopyToBuffer(buffer, countPosition, &totalCountU64); + } + + MergeSerializeIndices(nameRankIndices); + + if (m_BP1Aggregator.m_RankMPI == 0) + { + // Write length + const uint64_t totalLengthU64 = + static_cast<const uint64_t>(position - countPosition - 8); + CopyToBuffer(buffer, countPosition, &totalLengthU64); + } +} + +std::vector<char> BP1Writer::SerializeIndices( + const std::unordered_map<std::string, SerialElementIndex> &indices) const + noexcept +{ + std::vector<char> serializedIndices; + + for (const auto &indexPair : indices) + { + const SerialElementIndex &index = indexPair.second; + + // add rank at the beginning + const uint32_t rankSource = + static_cast<const uint32_t>(m_BP1Aggregator.m_RankMPI); + InsertToBuffer(serializedIndices, &rankSource); + + // insert buffer + InsertToBuffer(serializedIndices, index.Buffer.data(), + index.Buffer.size()); + } + + return serializedIndices; +} + +std::unordered_map<std::string, std::vector<BP1Base::SerialElementIndex>> +BP1Writer::DeserializeIndicesPerRankThreads( + const std::vector<char> &serialized) const noexcept +{ + auto lf_Deserialize = [&]( + const int rankSource, const std::vector<char> &serialized, + const size_t serializedPosition, + std::unordered_map<std::string, std::vector<SerialElementIndex>> + &deserialized) { + + size_t localPosition = serializedPosition; + ElementIndexHeader header = + ReadElementIndexHeader(serialized, localPosition); + + // mutex portion + { + std::lock_guard<std::mutex> lock(m_Mutex); + // inside mutex to avoid race condition + if (deserialized.count(header.Name) == 0) + { + deserialized[header.Name] = std::vector<SerialElementIndex>( + m_BP1Aggregator.m_SizeMPI, + SerialElementIndex(header.MemberID, 0)); + } + } + + const size_t bufferSize = static_cast<const size_t>(header.Length) + 4; + SerialElementIndex &index = deserialized[header.Name][rankSource]; + InsertToBuffer(index.Buffer, &serialized[serializedPosition], + bufferSize); + }; + + // BODY OF FUNCTION starts here + std::unordered_map<std::string, std::vector<SerialElementIndex>> + deserialized; + const size_t serializedSize = serialized.size(); + + if (m_BP1Aggregator.m_RankMPI != 0 || serializedSize < 8) + { + return deserialized; + } + + size_t serializedPosition = 0; + + std::vector<std::future<void>> asyncs(m_Threads); + std::vector<size_t> asyncPositions(m_Threads); + std::vector<int> asyncRankSources(m_Threads); + + bool launched = false; + + while (serializedPosition < serializedSize) + { + // extract rank and index buffer size + for (unsigned int t = 0; t < m_Threads; ++t) + { + const int rankSource = static_cast<const int>( + ReadValue<uint32_t>(serialized, serializedPosition)); + asyncRankSources[t] = rankSource; + asyncPositions[t] = serializedPosition; + + const size_t bufferSize = static_cast<const size_t>( + ReadValue<uint32_t>(serialized, serializedPosition)); + serializedPosition += bufferSize; + + if (launched) + { + asyncs[t].get(); + } + + if (serializedPosition <= serializedSize) + { + asyncs[t] = + std::async(std::launch::async, lf_Deserialize, + asyncRankSources[t], std::ref(serialized), + asyncPositions[t], std::ref(deserialized)); + } + } + + launched = true; + } + + for (auto &async : asyncs) + { + if (async.valid()) + { + async.wait(); + } + } + + return deserialized; +} + +void BP1Writer::MergeSerializeIndices( + const std::unordered_map<std::string, std::vector<SerialElementIndex>> + &nameRankIndices) noexcept +{ + auto lf_GetCharacteristics = [&](const std::vector<char> &buffer, + size_t &position, const uint8_t dataType, + uint8_t &count, uint32_t &length, + uint32_t &timeStep) + + { + switch (dataType) + { + + case (type_byte): + { + const auto characteristics = + ReadElementIndexCharacteristics<char>(buffer, position, true); + count = characteristics.Count; + length = characteristics.Length; + timeStep = characteristics.Statistics.TimeStep; + break; + } + + case (type_short): + { + const auto characteristics = + ReadElementIndexCharacteristics<short>(buffer, position, true); + count = characteristics.Count; + length = characteristics.Length; + timeStep = characteristics.Statistics.TimeStep; + break; + } + + case (type_integer): + { + const auto characteristics = + ReadElementIndexCharacteristics<int>(buffer, position, true); + count = characteristics.Count; + length = characteristics.Length; + timeStep = characteristics.Statistics.TimeStep; + break; + } + + case (type_long): + { + const auto characteristics = + ReadElementIndexCharacteristics<long int>(buffer, position, + true); + count = characteristics.Count; + length = characteristics.Length; + timeStep = characteristics.Statistics.TimeStep; + break; + } + + case (type_unsigned_byte): + { + const auto characteristics = + ReadElementIndexCharacteristics<unsigned char>(buffer, position, + true); + count = characteristics.Count; + length = characteristics.Length; + timeStep = characteristics.Statistics.TimeStep; + break; + } + + case (type_unsigned_short): + { + const auto characteristics = + ReadElementIndexCharacteristics<unsigned short>(buffer, + position, true); + count = characteristics.Count; + length = characteristics.Length; + timeStep = characteristics.Statistics.TimeStep; + break; + } + + case (type_unsigned_integer): + { + const auto characteristics = + ReadElementIndexCharacteristics<unsigned int>(buffer, position, + true); + count = characteristics.Count; + length = characteristics.Length; + timeStep = characteristics.Statistics.TimeStep; + break; + } + + case (type_unsigned_long): + { + auto characteristics = + ReadElementIndexCharacteristics<unsigned long int>( + buffer, position, true); + count = characteristics.Count; + length = characteristics.Length; + timeStep = characteristics.Statistics.TimeStep; + break; + } + + case (type_real): + { + auto characteristics = + ReadElementIndexCharacteristics<float>(buffer, position, true); + count = characteristics.Count; + length = characteristics.Length; + timeStep = characteristics.Statistics.TimeStep; + break; + } + + case (type_double): + { + auto characteristics = + ReadElementIndexCharacteristics<double>(buffer, position, true); + count = characteristics.Count; + length = characteristics.Length; + timeStep = characteristics.Statistics.TimeStep; + break; + } + // TODO: complex, string, string array, long double + } + + }; + + auto lf_MergeRank = [&](const std::vector<SerialElementIndex> &indices) { + + // extract header + ElementIndexHeader header; + // index non-empty buffer + size_t firstRank = 0; + // index positions per rank + std::vector<size_t> positions(indices.size(), 0); + // merge index length + uint32_t entryLength = 0; + size_t headerSize = 0; + + for (size_t r = 0; r < indices.size(); ++r) + { + const auto &buffer = indices[r].Buffer; + if (buffer.empty()) + { + continue; + } + size_t &position = positions[r]; + + header = ReadElementIndexHeader(buffer, position); + firstRank = r; + entryLength += position; + headerSize += position; + break; + } + + uint64_t setsCount = 0; + unsigned int currentTimeStep = 1; + bool marching = true; + std::vector<char> sorted; + + while (marching) + { + marching = false; + + for (size_t r = firstRank; r < indices.size(); ++r) + { + const auto &buffer = indices[r].Buffer; + if (buffer.empty()) + { + continue; + } + + auto &position = positions[r]; + if (position < buffer.size()) + { + marching = true; + } + else + { + continue; + } + + uint8_t count = 0; + uint32_t length = 0; + uint32_t timeStep = static_cast<uint32_t>(currentTimeStep); + + while (timeStep == currentTimeStep) + { + size_t localPosition = position; + lf_GetCharacteristics(buffer, localPosition, + header.DataType, count, length, + timeStep); + + if (timeStep != currentTimeStep) + { + break; + } + + entryLength += length + 5; + ++setsCount; + + // here copy to sorted buffer + InsertToBuffer(sorted, &buffer[position], length + 5); + position += length + 5; + + if (position >= buffer.size()) + { + break; + } + } + } + ++currentTimeStep; + } + + // Copy header to metadata buffer, need mutex here + { + std::lock_guard<std::mutex> lock(m_Mutex); + auto &buffer = m_Metadata.m_Buffer; + auto &position = m_Metadata.m_Position; + + m_Metadata.Resize(buffer.size() + headerSize + sorted.size(), + "in call to MergeSerializeIndices bp1 metadata"); + + CopyToBuffer(buffer, position, indices[firstRank].Buffer.data(), + headerSize); + + CopyToBuffer(buffer, position, sorted.data(), sorted.size()); + } + }; + + auto lf_MergeRankRange = [&]( + const std::unordered_map<std::string, std::vector<SerialElementIndex>> + &nameRankIndices, + const std::vector<std::string> &names, const size_t start, + const size_t end) + + { + for (size_t i = start; i < end; ++i) + { + auto itIndex = nameRankIndices.find(names[i]); + lf_MergeRank(itIndex->second); + } + }; + // BODY OF FUNCTION STARTS HERE + if (m_Threads == 1) // serial version + { + for (const auto &rankIndices : nameRankIndices) + { + lf_MergeRank(rankIndices.second); + } + return; + } + + // if threaded + const size_t elements = nameRankIndices.size(); + const size_t stride = elements / m_Threads; // elements per thread + const size_t last = stride + elements % m_Threads; // remainder to last + + std::vector<std::thread> threads; + threads.reserve(m_Threads); + + // copy names in order to use threads + std::vector<std::string> names; + names.reserve(nameRankIndices.size()); + + for (const auto &nameRankIndexPair : nameRankIndices) + { + names.push_back(nameRankIndexPair.first); + } + + for (unsigned int t = 0; t < m_Threads; ++t) + { + const size_t start = stride * t; + size_t end; + + if (t == m_Threads - 1) + { + end = start + stride; + } + else + { + end = start + last; + } + + threads.push_back(std::thread(lf_MergeRankRange, + std::ref(nameRankIndices), + std::ref(names), start, end)); + } + + for (auto &thread : threads) + { + thread.join(); } } @@ -569,4 +1040,4 @@ ADIOS2_FOREACH_TYPE_1ARG(declare_template_instantiation) //------------------------------------------------------------------------------ } // end namespace format -} // end namespace adios +} // end namespace adios2 diff --git a/source/adios2/toolkit/format/bp1/BP1Writer.h b/source/adios2/toolkit/format/bp1/BP1Writer.h index 5ba3fed6f527dbba902cfb4c9bfed640370319e7..7fec25cdb282c10ab9d98d45cbbcdc18266b9bb7 100644 --- a/source/adios2/toolkit/format/bp1/BP1Writer.h +++ b/source/adios2/toolkit/format/bp1/BP1Writer.h @@ -11,11 +11,7 @@ #ifndef ADIOS2_TOOLKIT_FORMAT_BP1_BP1WRITER_H_ #define ADIOS2_TOOLKIT_FORMAT_BP1_BP1WRITER_H_ -/// \cond EXCLUDE_FROM_DOXYGEN -#include <algorithm> //std::count, std::copy, std::for_each -#include <cmath> //std::ceil -#include <cstring> //std::memcpy -/// \endcond +#include <mutex> #include "adios2/ADIOSConfig.h" #include "adios2/ADIOSMacros.h" @@ -23,9 +19,7 @@ #include "adios2/core/Attribute.h" #include "adios2/core/IO.h" #include "adios2/core/Variable.h" -#include "adios2/toolkit/capsule/heap/STLVector.h" #include "adios2/toolkit/format/bp1/BP1Base.h" -#include "adios2/toolkit/format/bp1/BP1Structs.h" namespace adios2 { @@ -97,13 +91,21 @@ public: * @param rankProfilingJSON * @return profiling.json */ - std::string - AggregateProfilingJSON(const std::string &rankProfilingJSON) noexcept; + std::vector<char> + AggregateProfilingJSON(const std::string &rankProfilingJSON); + + /** + * Creates the final collective Metadata buffer in m_HeapBuffer.m_Metadata + * from all ranks + */ + void AggregateCollectiveMetadata(); private: /** BP format version */ const uint8_t m_Version = 3; + static std::mutex m_Mutex; + /** * Writes in BP buffer all attributes defined in an IO object. * Called by FlattenData function @@ -181,7 +183,7 @@ private: void WriteVariableMetadataInIndex( const Variable<T> &variable, const Stats<typename TypeInfo<T>::ValueType> &stats, const bool isNew, - BP1Index &index) noexcept; + SerialElementIndex &index) noexcept; template <class T> void WriteVariableCharacteristics( @@ -269,7 +271,7 @@ private: size_t &position) noexcept; /** - * Returns corresponding index of type BP1Index, if doesn't exists creates a + * Returns corresponding serial index, if doesn't exists creates a * new one. Used for variables and attributes * @param name variable or attribute name to look for index * @param indices look up hash table of indices @@ -277,24 +279,67 @@ private: * indices * @return reference to BP1Index in indices */ - BP1Index &GetBP1Index(const std::string name, - std::unordered_map<std::string, BP1Index> &indices, - bool &isNew) const noexcept; + SerialElementIndex &GetSerialElementIndex( + const std::string &name, + std::unordered_map<std::string, SerialElementIndex> &indices, + bool &isNew) const noexcept; /** - * Flattens the data and fills the pg length, vars count, vars length and - * attributes - * @param metadataSet - * @param buffer + * Wraps up the data buffer serialization in m_HeapBuffer and fills the pg + * length, vars count, vars + * length and attributes count and attributes length + * @param io object containing all attributes */ - void FlattenData(IO &io) noexcept; + void SerializeData(IO &io) noexcept; /** - * Flattens the metadata indices into a single metadata buffer in capsule - * @param metadataSet - * @param buffer + * Serializes the metadata indices appending it into the data buffer inside + * m_HeapBuffer + */ + void SerializeMetadataInData() noexcept; + + /** + * Used for PG index, aggregates without merging + * @param index input + * @param count total number of indices + */ + void AggregateIndex(const SerialElementIndex &index, const size_t count); + + /** + * Collective operation to aggregate and merge (sort) indices (variables and + * attributes) + * @param indices + */ + void AggregateMergeIndex( + const std::unordered_map<std::string, SerialElementIndex> + &indices) noexcept; + + /** + * Returns a serialized buffer with all indices with format: + * Rank (4 bytes), Buffer + * @param indices input of all indices to be serialized + * @return buffer with serialized indices + */ + std::vector<char> SerializeIndices( + const std::unordered_map<std::string, SerialElementIndex> &indices) + const noexcept; + + /** + * In rank=0, deserialize gathered indices + * @param serializedIndices input gathered indices + * @return hash[name][rank] = bp index buffer + */ + std::unordered_map<std::string, std::vector<SerialElementIndex>> + DeserializeIndicesPerRankThreads( + const std::vector<char> &serializedIndices) const noexcept; + + /** + * Merge indices by time step (default) and write to m_HeapBuffer.m_Metadata + * @param nameRankIndices */ - void FlattenMetadata() noexcept; + void MergeSerializeIndices( + const std::unordered_map<std::string, std::vector<SerialElementIndex>> + &nameRankIndices) noexcept; }; #define declare_template_instantiation(T) \ diff --git a/source/adios2/toolkit/format/bp1/BP1Writer.tcc b/source/adios2/toolkit/format/bp1/BP1Writer.tcc index 321edf743638cd0e293f5f64dd90e6bd6a1d36b6..ef8fa3f1cb6d680dbd9c09784108d9e8fefde309 100644 --- a/source/adios2/toolkit/format/bp1/BP1Writer.tcc +++ b/source/adios2/toolkit/format/bp1/BP1Writer.tcc @@ -7,6 +7,7 @@ * Created on: Apr 11, 2017 * Author: William F Godoy godoywf@ornl.gov */ + #ifndef ADIOS2_TOOLKIT_FORMAT_BP1_BP1WRITER_TCC_ #define ADIOS2_TOOLKIT_FORMAT_BP1_BP1WRITER_TCC_ @@ -22,53 +23,43 @@ namespace format template <class T> void BP1Writer::WriteVariableMetadata(const Variable<T> &variable) noexcept { - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("buffering").Resume(); - } + ProfilerStart("buffering"); Stats<typename TypeInfo<T>::ValueType> stats = GetStats(variable); - stats.TimeIndex = m_MetadataSet.TimeStep; // Get new Index or point to existing index bool isNew = true; // flag to check if variable is new - BP1Index &variableIndex = - GetBP1Index(variable.m_Name, m_MetadataSet.VarsIndices, isNew); + SerialElementIndex &variableIndex = GetSerialElementIndex( + variable.m_Name, m_MetadataSet.VarsIndices, isNew); stats.MemberID = variableIndex.MemberID; + auto &absolutePosition = m_Data.m_AbsolutePosition; + // write metadata header in data and extract offsets - stats.Offset = static_cast<uint64_t>(m_HeapBuffer.m_DataAbsolutePosition); + stats.Offset = static_cast<uint64_t>(absolutePosition); WriteVariableMetadataInData(variable, stats); - stats.PayloadOffset = m_HeapBuffer.m_DataAbsolutePosition; + stats.PayloadOffset = absolutePosition; // write to metadata index WriteVariableMetadataInIndex(variable, stats, isNew, variableIndex); - ++m_MetadataSet.DataPGVarsCount; - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("buffering").Pause(); - } + ProfilerStop("buffering"); } template <class T> void BP1Writer::WriteVariablePayload(const Variable<T> &variable) noexcept { - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("buffering").Resume(); - } + ProfilerStart("buffering"); + auto &buffer = m_Data.m_Buffer; + auto &position = m_Data.m_Position; + CopyToBufferThreads(buffer, position, variable.m_AppValues, + variable.TotalSize(), m_Threads); - CopyToBufferThreads(m_HeapBuffer.m_Data, m_HeapBuffer.m_DataPosition, - variable.m_AppValues, variable.TotalSize(), m_Threads); + auto &absolutePosition = m_Data.m_AbsolutePosition; + absolutePosition += variable.PayLoadSize(); - m_HeapBuffer.m_DataAbsolutePosition += variable.PayLoadSize(); - - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("buffering").Pause(); - } + ProfilerStop("buffering"); } // PRIVATE @@ -76,8 +67,8 @@ template <class T> size_t BP1Writer::WriteAttributeHeaderInData(const Attribute<T> &attribute, Stats<T> &stats) noexcept { - auto &buffer = m_HeapBuffer.m_Data; - auto &position = m_HeapBuffer.m_DataPosition; + auto &buffer = m_Data.m_Buffer; + auto &position = m_Data.m_Position; // will go back to write length const size_t attributeLengthPosition = position; @@ -99,8 +90,9 @@ void BP1Writer::WriteAttributeLengthInData( const Attribute<T> &attribute, Stats<T> &stats, const size_t attributeLengthPosition) noexcept { - auto &buffer = m_HeapBuffer.m_Data; - auto &position = m_HeapBuffer.m_DataPosition; + auto &buffer = m_Data.m_Buffer; + auto &position = m_Data.m_Position; + auto &absolutePosition = m_Data.m_AbsolutePosition; // back to attribute length const uint32_t attributeLength = @@ -108,7 +100,7 @@ void BP1Writer::WriteAttributeLengthInData( size_t backPosition = attributeLengthPosition; CopyToBuffer(buffer, backPosition, &attributeLengthPosition); - m_HeapBuffer.m_DataAbsolutePosition += position - attributeLengthPosition; + absolutePosition += position - attributeLengthPosition; } template <> @@ -119,8 +111,9 @@ BP1Writer::WriteAttributeInData(const Attribute<std::string> &attribute, const size_t attributeLengthPosition = WriteAttributeHeaderInData(attribute, stats); - auto &buffer = m_HeapBuffer.m_Data; - auto &position = m_HeapBuffer.m_DataPosition; + auto &buffer = m_Data.m_Buffer; + auto &position = m_Data.m_Position; + auto &absolutePosition = m_Data.m_AbsolutePosition; uint8_t dataType = GetDataType<std::string>(); if (!attribute.m_IsSingleValue) @@ -130,8 +123,7 @@ BP1Writer::WriteAttributeInData(const Attribute<std::string> &attribute, CopyToBuffer(buffer, position, &dataType); // here record payload offset - stats.PayloadOffset = m_HeapBuffer.m_DataAbsolutePosition + position - - attributeLengthPosition; + stats.PayloadOffset = absolutePosition + position - attributeLengthPosition; if (dataType == type_string) { @@ -170,15 +162,15 @@ void BP1Writer::WriteAttributeInData(const Attribute<T> &attribute, const size_t attributeLengthPosition = WriteAttributeHeaderInData(attribute, stats); - auto &buffer = m_HeapBuffer.m_Data; - auto &position = m_HeapBuffer.m_DataPosition; + auto &buffer = m_Data.m_Buffer; + auto &position = m_Data.m_Position; + auto &absolutePosition = m_Data.m_AbsolutePosition; uint8_t dataType = GetDataType<T>(); CopyToBuffer(buffer, position, &dataType); // here record payload offset - stats.PayloadOffset = m_HeapBuffer.m_DataAbsolutePosition + position - - attributeLengthPosition; + stats.PayloadOffset = absolutePosition + position - attributeLengthPosition; const uint32_t dataSize = attribute.m_Elements * sizeof(T); CopyToBuffer(buffer, position, &dataSize); @@ -201,7 +193,8 @@ inline void BP1Writer::WriteAttributeCharacteristicValueInIndex( uint8_t &characteristicsCounter, const Attribute<std::string> &attribute, std::vector<char> &buffer) noexcept { - uint8_t characteristicID = characteristic_value; + const uint8_t characteristicID = + static_cast<const uint8_t>(CharacteristicID::characteristic_value); InsertToBuffer(buffer, &characteristicID); @@ -235,7 +228,7 @@ void BP1Writer::WriteAttributeCharacteristicValueInIndex( uint8_t &characteristicsCounter, const Attribute<T> &attribute, std::vector<char> &buffer) noexcept { - uint8_t characteristicID = characteristic_value; + const uint8_t characteristicID = CharacteristicID::characteristic_value; InsertToBuffer(buffer, &characteristicID); @@ -255,7 +248,7 @@ template <class T> void BP1Writer::WriteAttributeInIndex(const Attribute<T> &attribute, const Stats<T> &stats) noexcept { - BP1Index index(stats.MemberID); + SerialElementIndex index(stats.MemberID); auto &buffer = index.Buffer; buffer.insert(buffer.end(), 4, '\0'); // skip attribute length (4) @@ -299,12 +292,10 @@ void BP1Writer::WriteAttributeInIndex(const Attribute<T> &attribute, // TIME Index WriteCharacteristicRecord(characteristic_time_index, characteristicsCounter, - stats.TimeIndex, buffer); + stats.TimeStep, buffer); - const uint32_t rankU32 = - static_cast<const uint32_t>(m_BP1Aggregator.m_RankMPI); WriteCharacteristicRecord(characteristic_file_index, characteristicsCounter, - rankU32, buffer); + stats.FileIndex, buffer); WriteCharacteristicRecord(characteristic_offset, characteristicsCounter, stats.Offset, buffer); @@ -340,6 +331,9 @@ BP1Writer::GetStats(const Variable<T> &variable) const noexcept GetMinMaxThreads(variable.m_AppValues, valuesSize, stats.Min, stats.Max, m_Threads); } + + stats.TimeStep = m_MetadataSet.TimeStep; + stats.FileIndex = static_cast<uint32_t>(m_BP1Aggregator.m_RankMPI); return stats; } @@ -348,8 +342,9 @@ void BP1Writer::WriteVariableMetadataInData( const Variable<T> &variable, const Stats<typename TypeInfo<T>::ValueType> &stats) noexcept { - auto &buffer = m_HeapBuffer.m_Data; - auto &position = m_HeapBuffer.m_DataPosition; + auto &buffer = m_Data.m_Buffer; + auto &position = m_Data.m_Position; + auto &absolutePosition = m_Data.m_AbsolutePosition; // for writing length at the end const size_t varLengthPosition = position; @@ -389,14 +384,14 @@ void BP1Writer::WriteVariableMetadataInData( size_t backPosition = varLengthPosition; CopyToBuffer(buffer, backPosition, &varLength); - m_HeapBuffer.m_DataAbsolutePosition += position - varLengthPosition; + absolutePosition += position - varLengthPosition; } template <class T> void BP1Writer::WriteVariableMetadataInIndex( const Variable<T> &variable, const Stats<typename TypeInfo<T>::ValueType> &stats, const bool isNew, - BP1Index &index) noexcept + SerialElementIndex &index) noexcept { auto &buffer = index.Buffer; @@ -420,6 +415,7 @@ void BP1Writer::WriteVariableMetadataInIndex( if (m_Verbosity == 0) { ++index.Count; + // fixed since group and path are not printed size_t setsCountPosition = 15 + variable.m_Name.size(); CopyToBuffer(buffer, setsCountPosition, &index.Count); } @@ -435,7 +431,6 @@ void BP1Writer::WriteBoundsRecord(const bool isScalar, const Stats<T> &stats, { if (isScalar) { - // stats.min = stats.max = value, need to test WriteCharacteristicRecord(characteristic_value, characteristicsCounter, stats.Min, buffer); } @@ -517,6 +512,15 @@ void BP1Writer::WriteVariableCharacteristics( uint8_t characteristicsCounter = 0; // DIMENSIONS + WriteCharacteristicRecord(characteristic_time_index, characteristicsCounter, + stats.TimeStep, buffer); + + WriteCharacteristicRecord(characteristic_file_index, characteristicsCounter, + stats.FileIndex, buffer); + + WriteBoundsRecord(variable.m_SingleValue, stats, characteristicsCounter, + buffer); + uint8_t characteristicID = characteristic_dimensions; InsertToBuffer(buffer, &characteristicID); const uint8_t dimensions = @@ -529,17 +533,6 @@ void BP1Writer::WriteVariableCharacteristics( buffer); ++characteristicsCounter; - WriteBoundsRecord(variable.m_SingleValue, stats, characteristicsCounter, - buffer); - - WriteCharacteristicRecord(characteristic_time_index, characteristicsCounter, - stats.TimeIndex, buffer); - - const uint32_t rankU32 = - static_cast<const uint32_t>(m_BP1Aggregator.m_RankMPI); - WriteCharacteristicRecord(characteristic_file_index, characteristicsCounter, - rankU32, buffer); - WriteCharacteristicRecord(characteristic_offset, characteristicsCounter, stats.Offset, buffer); diff --git a/source/adios2/toolkit/interop/adios1/ADIOS1Common.cpp b/source/adios2/toolkit/interop/adios1/ADIOS1Common.cpp index b28ca77e78ff8c2810a7c08ae21163261ed0ef3b..c3937148753e138103d6438f6ab96da90f94bdfb 100644 --- a/source/adios2/toolkit/interop/adios1/ADIOS1Common.cpp +++ b/source/adios2/toolkit/interop/adios1/ADIOS1Common.cpp @@ -125,7 +125,7 @@ void ADIOS1Common::InitTransports( } } -bool ADIOS1Common::Open(const OpenMode openMode) +bool ADIOS1Common::Open(const Mode openMode) { adios_open(&m_ADIOSFile, m_GroupName.c_str(), m_FileName.c_str(), OpenModeToString(openMode, true).c_str(), m_MPIComm); diff --git a/source/adios2/toolkit/interop/adios1/ADIOS1Common.h b/source/adios2/toolkit/interop/adios1/ADIOS1Common.h index 0473c896b10954f2d7d0bb4b2878184cba25d9a0..bc60faf91ca40615264e5b4824c8e7f8134d3d68 100644 --- a/source/adios2/toolkit/interop/adios1/ADIOS1Common.h +++ b/source/adios2/toolkit/interop/adios1/ADIOS1Common.h @@ -60,7 +60,7 @@ public: void InitParameters(const Params ¶meters); void InitTransports(const std::vector<Params> &transportsParameters); - bool Open(const OpenMode openMode); // return true if file is opened + bool Open(const Mode openMode); // return true if file is opened bool ReOpenAsNeeded(); // return true if file is open or reopened template <class T> diff --git a/source/adios2/toolkit/transport/Transport.cpp b/source/adios2/toolkit/transport/Transport.cpp index ab945b1bae5b8b0cd28cf2ea027c9d6e2cba71bd..a1a8ae762e26ea43c155c7f7342aab4ab2930172 100644 --- a/source/adios2/toolkit/transport/Transport.cpp +++ b/source/adios2/toolkit/transport/Transport.cpp @@ -23,27 +23,27 @@ Transport::Transport(const std::string type, const std::string library, MPI_Comm_size(m_MPIComm, &m_SizeMPI); } -void Transport::InitProfiler(const OpenMode openMode, const TimeUnit timeUnit) +void Transport::InitProfiler(const Mode openMode, const TimeUnit timeUnit) { m_Profiler.IsActive = true; m_Profiler.Timers.emplace(std::make_pair( "open", profiling::Timer("open", TimeUnit::Microseconds, m_DebugMode))); - if (openMode == OpenMode::Write) + if (openMode == Mode::Write) { m_Profiler.Timers.emplace( "write", profiling::Timer("write", timeUnit, m_DebugMode)); m_Profiler.Bytes.emplace("write", 0); } - else if (openMode == OpenMode::Append) + else if (openMode == Mode::Append) { m_Profiler.Timers.emplace( "append", profiling::Timer("append", timeUnit, m_DebugMode)); m_Profiler.Bytes.emplace("append", 0); } - else if (openMode == OpenMode::Read) + else if (openMode == Mode::Read) { m_Profiler.Timers.emplace( "read", profiling::Timer("read", timeUnit, m_DebugMode)); @@ -65,4 +65,39 @@ void Transport::SetBuffer(char * /*buffer*/, size_t /*size*/) } } -} // end namespace adios +void Transport::Flush() +{ + if (m_DebugMode) + { + std::invalid_argument("ERROR: " + m_Name + " transport type " + m_Type + + " using library " + m_Library + + " doesn't implement the Flush function\n"); + } +} + +void Transport::ProfilerStart(const std::string process) noexcept +{ + if (m_Profiler.IsActive) + { + m_Profiler.Timers.at(process).Resume(); + } +} + +void Transport::ProfilerStop(const std::string process) noexcept +{ + if (m_Profiler.IsActive) + { + m_Profiler.Timers.at(process).Pause(); + } +} + +void Transport::CheckName() const +{ + if (m_DebugMode && m_Name.empty()) + { + throw std::invalid_argument("ERROR: name can't be empty for " + + m_Library + " transport \n"); + } +} + +} // end namespace adios2 diff --git a/source/adios2/toolkit/transport/Transport.h b/source/adios2/toolkit/transport/Transport.h index cfca583afcf3167196edd1888803971270473c24..9c1dbb176b5949eb1997f0250590b2a75a4c3812 100644 --- a/source/adios2/toolkit/transport/Transport.h +++ b/source/adios2/toolkit/transport/Transport.h @@ -31,7 +31,7 @@ public: const std::string m_Type; ///< transport type from derived class const std::string m_Library; ///< library implementation (POSIX, Mdtm, etc.) std::string m_Name; ///< from Open, unique identifier (e.g. filename) - OpenMode m_OpenMode = OpenMode::Undefined; ///< at Open from ADIOSTypes.h + Mode m_OpenMode = Mode::Undefined; ///< at Open from ADIOSTypes.h bool m_IsOpen = false; ///< true: open for communication, false: unreachable MPI_Comm m_MPIComm; ///< current MPI communicator int m_RankMPI = 0; ///< from MPI_Comm_Rank @@ -49,14 +49,14 @@ public: virtual ~Transport() = default; - void InitProfiler(const OpenMode openMode, const TimeUnit timeUnit); + void InitProfiler(const Mode openMode, const TimeUnit timeUnit); /** * Opens transport, required before SetBuffer, Write, Read, Flush, Close * @param name * @param openMode */ - virtual void Open(const std::string &name, const OpenMode openMode) = 0; + virtual void Open(const std::string &name, const Mode openMode) = 0; /** * If OS buffered (FILE* or fstream), sets the buffer size @@ -66,14 +66,30 @@ public: virtual void SetBuffer(char *buffer, size_t size); /** - * Writes to file stream - * @param buffer raw data to be written to file stream - * @param size number of bytes to be written to file stream + * Writes to transport. Note that size is non-const due to the nature of + * underlying transport libraries + * @param buffer raw data to be written + * @param size number of bytes to be written + * @param start starting position for writing (to allow rewind), if not + * passed then start at current stream position */ - virtual void Write(const char *buffer, size_t size) = 0; + virtual void Write(const char *buffer, size_t size, + size_t start = MaxSizeT) = 0; + + /** + * Reads from transport "size" bytes from a certain position. Note that size + * and position and non-const due to the nature of underlying transport + * libraries + * @param buffer raw data pointer to put the read bytes (must be + * preallocated) + * @param size number of bytes to be read + * @param start starting position for read, if not passed then start at + * current stream position + */ + virtual void Read(char *buffer, size_t size, size_t start = MaxSizeT) = 0; /** flushes current contents to physical medium without closing */ - virtual void Flush() = 0; + virtual void Flush(); /** closes current file, after this file becomes unreachable */ virtual void Close() = 0; @@ -81,8 +97,14 @@ public: protected: /** true: turn on exceptions */ const bool m_DebugMode = false; + + void ProfilerStart(const std::string process) noexcept; + + void ProfilerStop(const std::string process) noexcept; + + void CheckName() const; }; -} // end namespace adios +} // end namespace adios2 #endif /* ADIOS2_TOOLKIT_TRANSPORT_TRANSPORT_H_ */ diff --git a/source/adios2/toolkit/transport/file/FileDescriptor.cpp b/source/adios2/toolkit/transport/file/FileDescriptor.cpp deleted file mode 100644 index 879ca2b702f71392d3137a73f16f6b45c9101778..0000000000000000000000000000000000000000 --- a/source/adios2/toolkit/transport/file/FileDescriptor.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * FileDescriptor.cpp file I/O using POSIX I/O library - * - * Created on: Oct 6, 2016 - * Author: William F Godoy godoywf@ornl.gov - */ - -#include "FileDescriptor.h" - -#include <fcntl.h> // open -#include <stddef.h> // write output -#include <sys/stat.h> // open -#include <sys/types.h> // open -#include <unistd.h> // write, close - -/// \cond EXCLUDE_FROM_DOXYGEN -#include <ios> //std::ios_base::failure -#include <iostream> -/// \endcond - -namespace adios2 -{ -namespace transport -{ - -FileDescriptor::FileDescriptor(MPI_Comm mpiComm, const bool debugMode) -: Transport("File", "POSIX", mpiComm, debugMode) -{ -} - -FileDescriptor::~FileDescriptor() -{ - if (m_IsOpen) - { - close(m_FileDescriptor); - } -} - -void FileDescriptor::Open(const std::string &name, const OpenMode openMode) -{ - if (m_DebugMode) - { - if (name.empty()) - { - throw std::invalid_argument( - "ERROR: file name is empty, in call to FilePointer Open\n"); - } - } - - m_Name = name; - m_OpenMode = openMode; - - if (openMode == OpenMode::Write) - { - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("open").Resume(); - } - - m_FileDescriptor = open(m_Name.c_str(), O_WRONLY | O_CREAT, 0777); - - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("open").Pause(); - } - } - else if (openMode == OpenMode::Append) - { - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("open").Resume(); - } - - // TODO we need to change this to read/write - m_FileDescriptor = open(m_Name.c_str(), O_WRONLY | O_APPEND); - - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("open").Pause(); - } - } - else if (openMode == OpenMode::Read) - { - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("open").Resume(); - } - - m_FileDescriptor = open(m_Name.c_str(), O_RDONLY); - - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("open").Pause(); - } - } - - if (m_DebugMode) - { - if (m_FileDescriptor == -1) - { - throw std::ios_base::failure("ERROR: couldn't open file " + m_Name + - ", check permissions or existence, in " - "call to FileDescriptor Open\n"); - } - } - - m_IsOpen = true; -} - -void FileDescriptor::Write(const char *buffer, size_t size) -{ - auto lf_Write = [&](const char *buffer, size_t size) { - - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("write").Resume(); - } - auto writtenSize = write(m_FileDescriptor, buffer, size); - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("write").Pause(); - } - - if (writtenSize == -1) - { - throw std::ios_base::failure("ERROR: couldn't write to file " + - m_Name + - ", in call to FileDescriptor Write\n"); - } - - if (static_cast<size_t>(writtenSize) != size) - { - throw std::ios_base::failure( - "ERROR: written size + " + std::to_string(writtenSize) + - " is not equal to intended size " + std::to_string(size) + - " in file " + m_Name + ", in call to FileDescriptor Write\n"); - } - }; - - if (size > DefaultMaxFileBatchSize) - { - const size_t batches = size / DefaultMaxFileBatchSize; - const size_t remainder = size % DefaultMaxFileBatchSize; - - size_t position = 0; - for (size_t b = 0; b < batches; ++b) - { - lf_Write(&buffer[position], DefaultMaxFileBatchSize); - position += DefaultMaxFileBatchSize; - } - lf_Write(&buffer[position], remainder); - } - else - { - lf_Write(buffer, size); - } -} - -void FileDescriptor::Flush() {} - -void FileDescriptor::Close() -{ - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("close").Resume(); - } - - const int status = close(m_FileDescriptor); - - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("close").Pause(); - } - - if (status == -1) - { - throw std::ios_base::failure("ERROR: couldn't close file " + m_Name + - ", in call to FileDescriptor Close\n"); - } - - m_IsOpen = false; -} - -} // end namespace transport -} // end namespace adios diff --git a/source/adios2/toolkit/transport/file/FileFStream.cpp b/source/adios2/toolkit/transport/file/FileFStream.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fbfa5cccac620553fade45a9fc43294fe22a838a --- /dev/null +++ b/source/adios2/toolkit/transport/file/FileFStream.cpp @@ -0,0 +1,169 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * FileStream.cpp + * + * Created on: Oct 24, 2016 + * Author: William F Godoy godoywf@ornl.gov + */ +#include "FileFStream.h" + +/// \cond EXCLUDE_FROM_DOXYGEN +#include <ios> // std::ios_base::failure +/// \endcond + +namespace adios2 +{ +namespace transport +{ + +FileFStream::FileFStream(MPI_Comm mpiComm, const bool debugMode) +: Transport("File", "fstream", mpiComm, debugMode) +{ +} + +void FileFStream::Open(const std::string &name, const Mode openMode) +{ + m_Name = name; + CheckName(); + m_OpenMode = openMode; + + switch (m_OpenMode) + { + case (Mode::Write): + ProfilerStart("open"); + m_FileStream.open(name, std::fstream::out | std::fstream::binary); + ProfilerStop("open"); + break; + + case (Mode::Append): + ProfilerStart("open"); + m_FileStream.open(name, std::fstream::in | std::fstream::out | + std::fstream::binary); + ProfilerStop("open"); + break; + + case (Mode::Read): + ProfilerStart("open"); + m_FileStream.open(name, std::fstream::in | std::fstream::binary); + ProfilerStop("open"); + break; + + default: + CheckFile("unknown open mode for file " + m_Name + + ", in call to stream open"); + } + + CheckFile("couldn't open file " + m_Name + + ", check permissions or path existence, in call to fstream open"); + m_IsOpen = true; +} + +void FileFStream::SetBuffer(char *buffer, size_t size) +{ + m_FileStream.rdbuf()->pubsetbuf(buffer, size); + CheckFile("couldn't set buffer in file " + m_Name + + ", in call to fstream rdbuf()->pubsetbuf"); +} + +void FileFStream::Write(const char *buffer, size_t size, size_t start) +{ + auto lf_Write = [&](const char *buffer, size_t size) { + + ProfilerStart("write"); + m_FileStream.write(buffer, static_cast<std::streamsize>(size)); + ProfilerStop("write"); + CheckFile("couldn't write from file " + m_Name + + ", in call to fstream write"); + }; + + if (start != MaxSizeT) + { + m_FileStream.seekp(start); + CheckFile("couldn't move to start position " + std::to_string(start) + + " in file " + m_Name + ", in call to fstream seekp"); + } + + if (size > DefaultMaxFileBatchSize) + { + const size_t batches = size / DefaultMaxFileBatchSize; + const size_t remainder = size % DefaultMaxFileBatchSize; + + size_t position = 0; + for (size_t b = 0; b < batches; ++b) + { + lf_Write(&buffer[position], DefaultMaxFileBatchSize); + position += DefaultMaxFileBatchSize; + } + lf_Write(&buffer[position], remainder); + } + else + { + lf_Write(buffer, size); + } +} + +void FileFStream::Read(char *buffer, size_t size, size_t start) +{ + auto lf_Read = [&](char *buffer, size_t size) { + ProfilerStart("read"); + m_FileStream.read(buffer, static_cast<std::streamsize>(size)); + ProfilerStop("read"); + CheckFile("couldn't read from file " + m_Name + + ", in call to fstream read"); + }; + + if (start != MaxSizeT) + { + m_FileStream.seekg(start); + CheckFile("couldn't move to start position " + std::to_string(start) + + " in file " + m_Name + ", in call to fstream seekg"); + } + + if (size > DefaultMaxFileBatchSize) + { + const size_t batches = size / DefaultMaxFileBatchSize; + const size_t remainder = size % DefaultMaxFileBatchSize; + + size_t position = 0; + for (size_t b = 0; b < batches; ++b) + { + lf_Read(&buffer[position], DefaultMaxFileBatchSize); + position += DefaultMaxFileBatchSize; + } + lf_Read(&buffer[position], remainder); + } + else + { + lf_Read(buffer, size); + } +} + +void FileFStream::Flush() +{ + m_FileStream.flush(); + CheckFile("couldn't flush to file " + m_Name + + ", in call to fstream flush"); +} + +void FileFStream::Close() +{ + ProfilerStart("close"); + m_FileStream.close(); + ProfilerStop("close"); + + CheckFile("couldn't close file " + m_Name + ", in call to fstream close"); + m_IsOpen = false; +} + +void FileFStream::CheckFile(const std::string hint) const +{ + if (!m_FileStream) + { + throw std::ios_base::failure("ERROR: " + hint + "\n"); + } +} + +} // end namespace transport +} // end namespace adios2 diff --git a/source/adios2/toolkit/transport/file/FileStream.h b/source/adios2/toolkit/transport/file/FileFStream.h similarity index 57% rename from source/adios2/toolkit/transport/file/FileStream.h rename to source/adios2/toolkit/transport/file/FileFStream.h index 21df05a7241511128bd107db6799945155ac143c..2bd628bf8436afe7d507089b5c31a345536daedd 100644 --- a/source/adios2/toolkit/transport/file/FileStream.h +++ b/source/adios2/toolkit/transport/file/FileFStream.h @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * FileStream.h wrapper of C++ fstream for file I/O + * FileFStream.h wrapper of C++ fstream for file I/O * * Created on: Oct 18, 2016 * Author: William F Godoy godoywf@ornl.gov @@ -22,19 +22,21 @@ namespace transport { /** File stream transport using C++ fstream */ -class FileStream : public Transport +class FileFStream : public Transport { public: - FileStream(MPI_Comm mpiComm, const bool debugMode); + FileFStream(MPI_Comm mpiComm, const bool debugMode); - ~FileStream() = default; + ~FileFStream() = default; - void Open(const std::string &name, const OpenMode openMode) final; + void Open(const std::string &name, const Mode openMode) final; void SetBuffer(char *buffer, size_t size) final; - void Write(const char *buffer, size_t size) final; + void Write(const char *buffer, size_t size, size_t start = MaxSizeT) final; + + void Read(char *buffer, size_t size, size_t start = MaxSizeT) final; void Flush() final; @@ -43,9 +45,15 @@ public: private: /** file stream using fstream library */ std::fstream m_FileStream; + + /** + * Check if m_FileStream is false after an operation + * @param hint exception message + */ + void CheckFile(const std::string hint) const; }; } // end namespace transport -} // end namespace adios +} // end namespace adios2 #endif /* ADIOS2_TOOLKIT_TRANSPORT_FILE_FILEPOINTER_H_ */ diff --git a/source/adios2/toolkit/transport/file/FilePOSIX.cpp b/source/adios2/toolkit/transport/file/FilePOSIX.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a792ab3e4f02aa39ae7a0f5c83e26785f1503a45 --- /dev/null +++ b/source/adios2/toolkit/transport/file/FilePOSIX.cpp @@ -0,0 +1,216 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * FileDescriptor.cpp file I/O using POSIX I/O library + * + * Created on: Oct 6, 2016 + * Author: William F Godoy godoywf@ornl.gov + */ +#include "FilePOSIX.h" + +#include <fcntl.h> // open +#include <stddef.h> // write output +#include <sys/stat.h> // open +#include <sys/types.h> // open +#include <unistd.h> // write, close + +/// \cond EXCLUDE_FROM_DOXYGEN +#include <ios> //std::ios_base::failure +/// \endcond + +namespace adios2 +{ +namespace transport +{ + +FilePOSIX::FilePOSIX(MPI_Comm mpiComm, const bool debugMode) +: Transport("File", "POSIX", mpiComm, debugMode) +{ +} + +FilePOSIX::~FilePOSIX() +{ + if (m_IsOpen) + { + close(m_FileDescriptor); + } +} + +void FilePOSIX::Open(const std::string &name, const Mode openMode) +{ + m_Name = name; + CheckName(); + m_OpenMode = openMode; + + switch (m_OpenMode) + { + + case (Mode::Write): + ProfilerStart("open"); + m_FileDescriptor = open(m_Name.c_str(), O_WRONLY | O_CREAT, 0777); + ProfilerStop("open"); + break; + + case (Mode::Append): + ProfilerStart("open"); + m_FileDescriptor = open(m_Name.c_str(), O_RDWR | O_CREAT, 0777); + ProfilerStop("open"); + break; + + case (Mode::Read): + ProfilerStart("open"); + m_FileDescriptor = open(m_Name.c_str(), O_RDONLY | O_CREAT, 0777); + ProfilerStop("open"); + break; + + default: + CheckFile("unknown open mode for file " + m_Name + + ", in call to POSIX open"); + } + + CheckFile("couldn't open file " + m_Name + + ", check permissions or path existence, in call to POSIX open"); + + m_IsOpen = true; +} + +void FilePOSIX::Write(const char *buffer, size_t size, size_t start) +{ + auto lf_Write = [&](const char *buffer, size_t size) { + + ProfilerStart("write"); + const auto writtenSize = write(m_FileDescriptor, buffer, size); + ProfilerStop("write"); + + if (writtenSize == -1) + { + throw std::ios_base::failure("ERROR: couldn't write to file " + + m_Name + + ", in call to FileDescriptor Write\n"); + } + + if (static_cast<size_t>(writtenSize) != size) + { + throw std::ios_base::failure( + "ERROR: written size + " + std::to_string(writtenSize) + + " is not equal to intended size " + std::to_string(size) + + " in file " + m_Name + ", in call to FileDescriptor Write\n"); + } + }; + + if (start != MaxSizeT) + { + const auto newPosition = lseek(m_FileDescriptor, start, SEEK_SET); + + if (static_cast<size_t>(newPosition) != start) + { + throw std::ios_base::failure( + "ERROR: couldn't move to start position " + + std::to_string(start) + " in file " + m_Name + + ", in call to POSIX lseek\n"); + } + } + + if (size > DefaultMaxFileBatchSize) + { + const size_t batches = size / DefaultMaxFileBatchSize; + const size_t remainder = size % DefaultMaxFileBatchSize; + + size_t position = 0; + for (size_t b = 0; b < batches; ++b) + { + lf_Write(&buffer[position], DefaultMaxFileBatchSize); + position += DefaultMaxFileBatchSize; + } + lf_Write(&buffer[position], remainder); + } + else + { + lf_Write(buffer, size); + } +} + +void FilePOSIX::Read(char *buffer, size_t size, size_t start) +{ + auto lf_Read = [&](char *buffer, size_t size) { + + ProfilerStart("read"); + const auto readSize = read(m_FileDescriptor, buffer, size); + ProfilerStop("read"); + + if (readSize == -1) + { + throw std::ios_base::failure("ERROR: couldn't read from file " + + m_Name + + ", in call to POSIX IO read\n"); + } + + if (static_cast<size_t>(readSize) != size) + { + throw std::ios_base::failure( + "ERROR: read size + " + std::to_string(readSize) + + " is not equal to intended size " + std::to_string(size) + + " in file " + m_Name + ", in call to POSIX IO read\n"); + } + }; + + if (start != MaxSizeT) + { + const auto newPosition = lseek(m_FileDescriptor, start, SEEK_SET); + + if (static_cast<size_t>(newPosition) != start) + { + throw std::ios_base::failure( + "ERROR: couldn't move to start position " + + std::to_string(start) + " in file " + m_Name + + ", in call to POSIX lseek\n"); + } + } + + if (size > DefaultMaxFileBatchSize) + { + const size_t batches = size / DefaultMaxFileBatchSize; + const size_t remainder = size % DefaultMaxFileBatchSize; + + size_t position = 0; + for (size_t b = 0; b < batches; ++b) + { + lf_Read(&buffer[position], DefaultMaxFileBatchSize); + position += DefaultMaxFileBatchSize; + } + lf_Read(&buffer[position], remainder); + } + else + { + lf_Read(buffer, size); + } +} + +void FilePOSIX::Flush() {} + +void FilePOSIX::Close() +{ + ProfilerStart("close"); + const int status = close(m_FileDescriptor); + ProfilerStop("close"); + + if (status == -1) + { + throw std::ios_base::failure("ERROR: couldn't close file " + m_Name + + ", in call to POSIX IO close\n"); + } + + m_IsOpen = false; +} + +void FilePOSIX::CheckFile(const std::string hint) const +{ + if (m_FileDescriptor == -1) + { + throw std::ios_base::failure("ERROR: " + hint + "\n"); + } +} + +} // end namespace transport +} // end namespace adios2 diff --git a/source/adios2/toolkit/transport/file/FileDescriptor.h b/source/adios2/toolkit/transport/file/FilePOSIX.h similarity index 58% rename from source/adios2/toolkit/transport/file/FileDescriptor.h rename to source/adios2/toolkit/transport/file/FilePOSIX.h index fe010c6e3516e553da9f5fbb8f8793666191d176..ffc212067d117123893612049bdbfd2b148af4cc 100644 --- a/source/adios2/toolkit/transport/file/FileDescriptor.h +++ b/source/adios2/toolkit/transport/file/FilePOSIX.h @@ -19,18 +19,20 @@ namespace adios2 namespace transport { -/** File descriptor transport using the POSIX library */ -class FileDescriptor : public Transport +/** File descriptor transport using the POSIX IO library */ +class FilePOSIX : public Transport { public: - FileDescriptor(MPI_Comm mpiComm, const bool debugMode); + FilePOSIX(MPI_Comm mpiComm, const bool debugMode); - ~FileDescriptor(); + ~FilePOSIX(); - void Open(const std::string &name, const OpenMode openMode) final; + void Open(const std::string &name, const Mode openMode) final; - void Write(const char *buffer, size_t size) final; + void Write(const char *buffer, size_t size, size_t start = MaxSizeT) final; + + void Read(char *buffer, size_t size, size_t start = MaxSizeT) final; /** Does nothing, each write is supposed to flush */ void Flush() final; @@ -40,8 +42,15 @@ public: private: /** POSIX file handle returned by Open */ int m_FileDescriptor = -1; + + /** + * Check if m_FileDescriptor is -1 after an operation + * @param hint exception message + */ + void CheckFile(const std::string hint) const; }; } // end namespace transport -} // end namespace +} // end namespace adios2 + #endif /* ADIOS2_TRANSPORT_FILE_FILEDESCRIPTOR_H_ */ diff --git a/source/adios2/toolkit/transport/file/FilePointer.cpp b/source/adios2/toolkit/transport/file/FilePointer.cpp deleted file mode 100644 index e11c4f9fb9dc17a6118f4cec5d8fc6f933061eb8..0000000000000000000000000000000000000000 --- a/source/adios2/toolkit/transport/file/FilePointer.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * FilePointer.cpp - * - * Created on: Jan 6, 2017 - * Author: William F Godoy godoywf@ornl.gov - */ - -#include "FilePointer.h" - -/// \cond EXCLUDE_FROM_DOXYGEN -#include <ios> //std::ios_base::failure -/// \endcond - -// removes fopen warning on Windows -#ifdef _WIN32 -#pragma warning(disable : 4996) // fopen -#endif - -namespace adios2 -{ -namespace transport -{ - -FilePointer::FilePointer(MPI_Comm mpiComm, const bool debugMode) -: Transport("File", "stdio", mpiComm, debugMode) -{ -} - -FilePointer::~FilePointer() -{ - if (m_IsOpen) - { - std::fclose(m_File); - } -} - -void FilePointer::Open(const std::string &name, const OpenMode openMode) -{ - if (m_DebugMode) - { - if (name.empty()) - { - throw std::invalid_argument( - "ERROR: file name is empty, in call to FilePointer Open\n"); - } - } - - m_Name = name; - m_OpenMode = openMode; - - if (m_OpenMode == OpenMode::Write) - { - m_File = std::fopen(name.c_str(), "wb"); - } - else if (m_OpenMode == OpenMode::Append) - { - // need to change when implemented - m_File = std::fopen(name.c_str(), "ab"); - } - else if (m_OpenMode == OpenMode::Read) - { - m_File = std::fopen(name.c_str(), "rb"); - } - - if (ferror(m_File)) - { - throw std::ios_base::failure("ERROR: couldn't open file " + name + - ", " - "in call to FilePointer Open\n"); - } - - m_IsOpen = true; -} - -void FilePointer::SetBuffer(char *buffer, size_t size) -{ - const int status = std::setvbuf(m_File, buffer, _IOFBF, size); - - if (!status) - { - throw std::ios_base::failure( - "ERROR: could not set FILE* buffer in file " + m_Name + - ", in call to FilePointer SetBuffer\n"); - } -} - -void FilePointer::Write(const char *buffer, size_t size) -{ - auto lf_Write = [&](const char *buffer, size_t size) { - - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("write").Resume(); - } - auto writtenSize = std::fwrite(buffer, sizeof(char), size, m_File); - - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("write").Pause(); - } - - if (std::ferror(m_File)) - { - throw std::ios_base::failure("ERROR: couldn't write to file " + - m_Name + ", in call to FILE* Write\n"); - } - - if (writtenSize != size) - { - throw std::ios_base::failure( - "ERROR: written size + " + std::to_string(writtenSize) + - " is not equal to intended size " + std::to_string(size) + - " in file " + m_Name + ", in call to FilePointer Write\n"); - } - }; - - if (size > DefaultMaxFileBatchSize) - { - const size_t batches = size / DefaultMaxFileBatchSize; - const size_t remainder = size % DefaultMaxFileBatchSize; - - size_t position = 0; - for (size_t b = 0; b < batches; ++b) - { - lf_Write(&buffer[position], DefaultMaxFileBatchSize); - position += DefaultMaxFileBatchSize; - } - lf_Write(&buffer[position], remainder); - } - else - { - lf_Write(buffer, size); - } -} - -void FilePointer::Flush() -{ - const int status = std::fflush(m_File); - - if (status == EOF) - { - throw std::ios_base::failure("ERROR: couldn't flush file " + m_Name + - ", in call to FilePointer Flush\n"); - } -} - -void FilePointer::Close() -{ - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("close").Resume(); - } - - const int status = std::fclose(m_File); - - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("close").Pause(); - } - - if (status == EOF) - { - throw std::ios_base::failure("ERROR: couldn't close file " + m_Name + - ", in call to FilePointer Write\n"); - } - - m_IsOpen = false; -} - -} // end namespace transport -} // end namespace adios diff --git a/source/adios2/toolkit/transport/file/FileStdio.cpp b/source/adios2/toolkit/transport/file/FileStdio.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0e283735e66337538afe5476ff0e11ceac91a832 --- /dev/null +++ b/source/adios2/toolkit/transport/file/FileStdio.cpp @@ -0,0 +1,206 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * FileStdio.cpp + * + * Created on: Jan 6, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include "FileStdio.h" + +/// \cond EXCLUDE_FROM_DOXYGEN +#include <ios> //std::ios_base::failure +/// \endcond + +// removes fopen warning on Windows +#ifdef _WIN32 +#pragma warning(disable : 4996) // fopen +#endif + +namespace adios2 +{ +namespace transport +{ + +FileStdio::FileStdio(MPI_Comm mpiComm, const bool debugMode) +: Transport("File", "stdio", mpiComm, debugMode) +{ +} + +FileStdio::~FileStdio() +{ + if (m_IsOpen) + { + std::fclose(m_File); + } +} + +void FileStdio::Open(const std::string &name, const Mode openMode) +{ + m_Name = name; + CheckName(); + m_OpenMode = openMode; + + switch (m_OpenMode) + { + case (Mode::Write): + m_File = std::fopen(name.c_str(), "wb"); + break; + case (Mode::Append): + m_File = std::fopen(name.c_str(), "rwb"); + break; + case (Mode::Read): + m_File = std::fopen(name.c_str(), "rb"); + break; + default: + CheckFile("unknown open mode for file " + m_Name + + ", in call to stdio fopen"); + } + + CheckFile("couldn't open file " + m_Name + + ", check permissions or path existence, in call to stdio open"); + m_IsOpen = true; +} + +void FileStdio::SetBuffer(char *buffer, size_t size) +{ + const int status = std::setvbuf(m_File, buffer, _IOFBF, size); + + if (!status) + { + throw std::ios_base::failure( + "ERROR: could not set FILE* buffer in file " + m_Name + + ", in call to stdio setvbuf\n"); + } +} + +void FileStdio::Write(const char *buffer, size_t size, size_t start) +{ + auto lf_Write = [&](const char *buffer, size_t size) { + + ProfilerStart("write"); + auto writtenSize = std::fwrite(buffer, sizeof(char), size, m_File); + ProfilerStop("write"); + + CheckFile("couldn't write to file " + m_Name + + ", in call to stdio fwrite"); + + if (writtenSize != size) + { + throw std::ios_base::failure( + "ERROR: written size + " + std::to_string(writtenSize) + + " is not equal to intended size " + std::to_string(size) + + " in file " + m_Name + ", in call to stdio fwrite\n"); + } + }; + + if (start != MaxSizeT) + { + std::fseek(m_File, static_cast<long int>(start), SEEK_SET); + CheckFile("couldn't move to start position " + std::to_string(start) + + " in file " + m_Name + ", in call to stdio fseek at write "); + } + + if (size > DefaultMaxFileBatchSize) + { + const size_t batches = size / DefaultMaxFileBatchSize; + const size_t remainder = size % DefaultMaxFileBatchSize; + + size_t position = 0; + for (size_t b = 0; b < batches; ++b) + { + lf_Write(&buffer[position], DefaultMaxFileBatchSize); + position += DefaultMaxFileBatchSize; + } + lf_Write(&buffer[position], remainder); + } + else + { + lf_Write(buffer, size); + } +} + +void FileStdio::Read(char *buffer, size_t size, size_t start) +{ + auto lf_Read = [&](char *buffer, size_t size) { + + ProfilerStart("read"); + auto readSize = std::fread(buffer, sizeof(char), size, m_File); + ProfilerStop("read"); + + CheckFile("couldn't read to file " + m_Name + + ", in call to stdio fread"); + + if (readSize != size) + { + throw std::ios_base::failure( + "ERROR: read size + " + std::to_string(readSize) + + " is not equal to intended size " + std::to_string(size) + + " in file " + m_Name + ", in call to stdio fread\n"); + } + }; + + if (start != MaxSizeT) + { + std::fseek(m_File, static_cast<long int>(start), SEEK_SET); + CheckFile("couldn't move to start position " + std::to_string(start) + + " in file " + m_Name + ", in call to stdio fseek for read"); + } + + if (size > DefaultMaxFileBatchSize) + { + const size_t batches = size / DefaultMaxFileBatchSize; + const size_t remainder = size % DefaultMaxFileBatchSize; + + size_t position = 0; + for (size_t b = 0; b < batches; ++b) + { + lf_Read(&buffer[position], DefaultMaxFileBatchSize); + position += DefaultMaxFileBatchSize; + } + lf_Read(&buffer[position], remainder); + } + else + { + lf_Read(buffer, size); + } +} + +void FileStdio::Flush() +{ + const int status = std::fflush(m_File); + + if (status == EOF) + { + throw std::ios_base::failure("ERROR: couldn't flush file " + m_Name + + ", in call to stdio fflush\n"); + } +} + +void FileStdio::Close() +{ + ProfilerStart("close"); + const int status = std::fclose(m_File); + ProfilerStop("close"); + + if (status == EOF) + { + throw std::ios_base::failure("ERROR: couldn't close file " + m_Name + + ", in call to stdio fclose\n"); + } + + m_IsOpen = false; +} + +void FileStdio::CheckFile(const std::string hint) const +{ + if (std::ferror(m_File)) + { + throw std::ios_base::failure("ERROR: " + hint + "\n"); + } +} + +} // end namespace transport +} // end namespace adios2 diff --git a/source/adios2/toolkit/transport/file/FilePointer.h b/source/adios2/toolkit/transport/file/FileStdio.h similarity index 51% rename from source/adios2/toolkit/transport/file/FilePointer.h rename to source/adios2/toolkit/transport/file/FileStdio.h index 6d1521a3d5d99fff26f00806871194f9461fa5a8..75dac7a6766e833fd26dcbec5ab5d836673ae90d 100644 --- a/source/adios2/toolkit/transport/file/FilePointer.h +++ b/source/adios2/toolkit/transport/file/FileStdio.h @@ -2,7 +2,7 @@ * Distributed under the OSI-approved Apache License, Version 2.0. See * accompanying file Copyright.txt for details. * - * FilePointer.h wrapper of C/C++ stdio.h for file I/O + * FileStdio.h wrapper of C/C++ stdio.h for file I/O * * Created on: Jan 6, 2017 * Author: William F Godoy godoywf@ornl.gov @@ -20,24 +20,22 @@ namespace adios2 namespace transport { -/** - * Class that defines a transport method using C file pointer (FP) to - * streams - * FILE* - */ -class FilePointer : public Transport +/** File transport using C stdio FILE* */ +class FileStdio : public Transport { public: - FilePointer(MPI_Comm mpiComm, const bool debugMode); + FileStdio(MPI_Comm mpiComm, const bool debugMode); - ~FilePointer(); + ~FileStdio(); - void Open(const std::string &name, const OpenMode openMode) final; + void Open(const std::string &name, const Mode openMode) final; void SetBuffer(char *buffer, size_t size) final; - void Write(const char *buffer, size_t size) final; + void Write(const char *buffer, size_t size, size_t start = MaxSizeT) final; + + void Read(char *buffer, size_t size, size_t start = MaxSizeT) final; void Flush() final; @@ -45,10 +43,16 @@ public: private: /** C File pointer */ - FILE *m_File = nullptr; // NULL or nullptr? + FILE *m_File = nullptr; + + /** + * Check for std::ferror and throw an exception if true + * @param hint exception message + */ + void CheckFile(const std::string hint) const; }; } // end namespace transport -} // end namespace +} // end namespace adios2 #endif /* ADIOS2_TOOLKIT_TRANSPORT_FILE_FILEPOINTER_H_ */ diff --git a/source/adios2/toolkit/transport/file/FileStream.cpp b/source/adios2/toolkit/transport/file/FileStream.cpp deleted file mode 100644 index 3609394539420b2a3c3333bc31506f45b05b76a7..0000000000000000000000000000000000000000 --- a/source/adios2/toolkit/transport/file/FileStream.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Distributed under the OSI-approved Apache License, Version 2.0. See - * accompanying file Copyright.txt for details. - * - * FileStream.cpp - * - * Created on: Oct 24, 2016 - * Author: William F Godoy godoywf@ornl.gov - */ - -#include "FileStream.h" - -/// \cond EXCLUDE_FROM_DOXYGEN -#include <ios> // std::ios_base::failure -/// \endcond - -namespace adios2 -{ -namespace transport -{ - -FileStream::FileStream(MPI_Comm mpiComm, const bool debugMode) -: Transport("File", "fstream", mpiComm, debugMode) -{ -} - -void FileStream::Open(const std::string &name, const OpenMode openMode) -{ - if (m_DebugMode) - { - if (name.empty()) - { - throw std::invalid_argument( - "ERROR: file name is empty, in call to FilePointer Open\n"); - } - } - - m_Name = name; - m_OpenMode = openMode; - - if (m_OpenMode == OpenMode::Write) - { - m_FileStream.open(name, std::fstream::out | std::fstream::binary); - } - else if (m_OpenMode == OpenMode::Append) - { - // to be changed to rw? - m_FileStream.open(name, std::fstream::out | std::fstream::app | - std::fstream::binary); - } - else if (m_OpenMode == OpenMode::Read) - { - m_FileStream.open(name, std::fstream::in | std::fstream::binary); - } - - if (!m_FileStream) - { - throw std::ios_base::failure("ERROR: couldn't open file " + m_Name + - ", in call to FileStream Open\n"); - } - - m_IsOpen = true; -} - -void FileStream::SetBuffer(char *buffer, size_t size) -{ - m_FileStream.rdbuf()->pubsetbuf(buffer, size); - - if (!m_FileStream) - { - throw std::ios_base::failure("ERROR: couldn't set buffer in file " + - m_Name + - ", in call to FileStream SetBuffer\n"); - } -} - -void FileStream::Write(const char *buffer, size_t size) -{ - auto lf_Write = [&](const char *buffer, size_t size) { - - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("write").Resume(); - } - m_FileStream.write(buffer, static_cast<std::streamsize>(size)); - - if (m_Profiler.IsActive) - { - m_Profiler.Timers.at("write").Pause(); - } - - if (!m_FileStream) - { - throw std::ios_base::failure("ERROR: couldn't write to file " + - m_Name + ", in call to FILE* Write\n"); - } - }; - - if (size > DefaultMaxFileBatchSize) - { - const size_t batches = size / DefaultMaxFileBatchSize; - const size_t remainder = size % DefaultMaxFileBatchSize; - - size_t position = 0; - for (size_t b = 0; b < batches; ++b) - { - lf_Write(&buffer[position], DefaultMaxFileBatchSize); - position += DefaultMaxFileBatchSize; - } - lf_Write(&buffer[position], remainder); - } - else - { - lf_Write(buffer, size); - } -} - -void FileStream::Flush() -{ - m_FileStream.flush(); - if (!m_FileStream) - { - throw std::ios_base::failure("ERROR: couldn't flush to file " + m_Name + - ", in call to FileStream Flush\n"); - } -} - -void FileStream::Close() -{ - m_FileStream.close(); - if (!m_FileStream) - { - throw std::ios_base::failure("ERROR: couldn't close file " + m_Name + - ", in call to FileStream Close\n"); - } - - m_IsOpen = false; -} - -} // end namespace transport -} // end namespace adios diff --git a/source/adios2/toolkit/transport/shm/ShmSystemV.cpp b/source/adios2/toolkit/transport/shm/ShmSystemV.cpp new file mode 100644 index 0000000000000000000000000000000000000000..77043f75c197659b62a7c08f29f5d74836d129ed --- /dev/null +++ b/source/adios2/toolkit/transport/shm/ShmSystemV.cpp @@ -0,0 +1,174 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * ShmSystemV.cpp + * + * Created on: Sep 26, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#include "ShmSystemV.h" + +#include <cstring> //std::memcpy + +#include <sys/ipc.h> //ftok +#include <sys/shm.h> //shmget, shmmat +#include <sys/types.h> //key_t + +namespace adios2 +{ +namespace transport +{ + +ShmSystemV::ShmSystemV(const unsigned int projectID, const size_t size, + MPI_Comm mpiComm, const bool debugMode, + const bool removeAtClose) +: Transport("Shm", "SystemV", mpiComm, debugMode), m_ProjectID(projectID), + m_Size(size), m_RemoveAtClose(removeAtClose) +{ + if (m_DebugMode && projectID == 0) + { + throw std::invalid_argument( + "ERROR: projectID can't be zero, in shared memory segment\n"); + } +} + +ShmSystemV::~ShmSystemV() // this might not be correct +{ + if (m_IsOpen) + { + shmdt(m_Buffer); + + if (m_RemoveAtClose) + { + shmctl(m_ShmID, IPC_RMID, NULL); + } + } +} + +void ShmSystemV::Open(const std::string &name, const Mode openMode) +{ + m_Name = name; + CheckName(); + m_OpenMode = openMode; + + // not using const + key_t key = ftok(m_Name.c_str(), static_cast<int>(m_ProjectID)); + + switch (m_OpenMode) + { + case (Mode::Write): + ProfilerStart("open"); + m_ShmID = shmget(key, m_Size, IPC_CREAT | 0666); + ProfilerStop("open"); + break; + + case (Mode::Append): + ProfilerStart("open"); + m_ShmID = shmget(key, m_Size, 0); + ProfilerStop("open"); + break; + + case (Mode::Read): + ProfilerStart("open"); + m_ShmID = shmget(key, m_Size, 0); + ProfilerStop("open"); + break; + + default: + throw std::invalid_argument( + "ERROR: unknown open mode for shared memory segment " + m_Name + + ", in call to SystemV Open"); + } + + CheckShmID("in call to ShmSystemV shmget at Open"); + + m_Buffer = static_cast<char *>(shmat(m_ShmID, nullptr, 0)); + CheckBuffer("in call to SystemV shmat at Open"); + m_IsOpen = false; +} + +void ShmSystemV::Write(const char *buffer, size_t size, size_t start) +{ + CheckSizes(size, start, "in call to Write"); + ProfilerStart("write"); + std::memcpy(&m_Buffer[start], buffer, size); + ProfilerStop("write"); +} + +void ShmSystemV::Read(char *buffer, size_t size, size_t start) +{ + CheckSizes(size, start, "in call to Read"); + ProfilerStart("read"); + std::memcpy(buffer, &m_Buffer[start], size); + ProfilerStop("read"); +} + +void ShmSystemV::Close() +{ + ProfilerStart("close"); + int result = shmdt(m_Buffer); + ProfilerStop("close"); + if (result < 1) + { + throw std::ios_base::failure( + "ERROR: failed to detach shared memory segment of size " + + std::to_string(m_Size) + " and name " + m_Name + + ", in call to SystemV shmdt Close\n"); + } + + if (m_RemoveAtClose) + { + ProfilerStart("close"); + int remove = shmctl(m_ShmID, IPC_RMID, NULL); + ProfilerStop("close"); + if (result < 1) + { + throw std::ios_base::failure( + "ERROR: failed to remove shared memory segment of size " + + std::to_string(m_Size) + " and name " + m_Name + + ", in call to SystemV shmctl Close\n"); + } + } + + m_IsOpen = false; +} + +// PRIVATE +void ShmSystemV::CheckShmID(const std::string hint) const +{ + if (m_ShmID < 0) + { + throw std::ios_base::failure( + "ERROR: Failed shared memory segment of size " + + std::to_string(m_Size) + " and name " + m_Name + ", " + hint + + "\n"); + } +} + +void ShmSystemV::CheckBuffer(const std::string hint) const +{ + if (m_Buffer == nullptr) + { + throw std::ios_base::failure( + "ERROR: nullptr shared memory segment of size " + + std::to_string(m_Size) + " and name " + m_Name + " " + hint + "\n"); + } +} + +void ShmSystemV::CheckSizes(const size_t start, const size_t size, + const std::string hint) const +{ + if (m_DebugMode && start + size > m_Size) + { + throw std::invalid_argument( + "ERROR: final position (start + size) = (" + std::to_string(start) + + " + " + std::to_string(size) + + " ) exceeding shared memory pre-allocated size:" + + std::to_string(m_Size) + "," + hint + "\n"); + } +} + +} // end namespace transport +} // end namespace adios2 diff --git a/source/adios2/toolkit/transport/shm/ShmSystemV.h b/source/adios2/toolkit/transport/shm/ShmSystemV.h new file mode 100644 index 0000000000000000000000000000000000000000..b16751d39b426d99c25753e7c54cb82b65105496 --- /dev/null +++ b/source/adios2/toolkit/transport/shm/ShmSystemV.h @@ -0,0 +1,79 @@ +/* + * Distributed under the OSI-approved Apache License, Version 2.0. See + * accompanying file Copyright.txt for details. + * + * ShmSystemV.h + * + * Created on: Sep 26, 2017 + * Author: William F Godoy godoywf@ornl.gov + */ + +#ifndef ADIOS2_TOOLKIT_TRANSPORT_SHMEM_SHMEMSYSTEMV_H_ +#define ADIOS2_TOOLKIT_TRANSPORT_SHMEM_SHMEMSYSTEMV_H_ + +#include "adios2/toolkit/transport/Transport.h" + +namespace adios2 +{ +namespace transport +{ + +class ShmSystemV : public Transport +{ + +public: + /** + * Unique constructor + * @param pathName ftok input to create unique shared-memory key + * @param projectID ftok input to create unique shared-memory key. Must be + * greater than zero. + * @param size shared-memory pre-allocated data size + * @param debugMode true: extra checks + */ + ShmSystemV(const unsigned int projectID, const size_t size, + MPI_Comm mpiComm, const bool debugMode = false, + const bool removeAtClose = false); + + ~ShmSystemV(); + + void Open(const std::string &name, const Mode openMode) final; + + void Write(const char *buffer, size_t size, size_t start = MaxSizeT) final; + + void Read(char *buffer, size_t size, size_t start = MaxSizeT) final; + + void Close() final; + +private: + /** 1st argument of ftok to create shared memory segment key, from Open */ + std::string m_PathName; + + /** 2nd argument of ftok to create shared memory segment key, must be + * greater than zero, from constructor */ + const unsigned int m_ProjectID; + + /** shared memory segment ID from shmget */ + int m_ShmID = -1; + + /** reference to a shared memory data buffer */ + char *m_Buffer = nullptr; + + /** size of the pre-allocated shared memory segment, non-const due to + * SystemV API */ + size_t m_Size; + + /** remove shared-memory segment at close (will be manually cleaned later)*/ + const bool m_RemoveAtClose = false; + + void CheckShmID(const std::string hint) const; + + void CheckBuffer(const std::string hint) const; + + void CheckSizes(const size_t start, const size_t size, + const std::string hint) const; +}; + +} // end namespace transport +} // end namespace adios2 + +#endif /* ADIOS2_TOOLKIT_TRANSPORT_SHMEM_SHMEMSYSTEMV_H_ */ diff --git a/source/adios2/toolkit/transport/wan/WANZmq.cpp b/source/adios2/toolkit/transport/wan/WANZmq.cpp index 6627a6372c42ddebaab36572825787cabbfa29e2..c3292b8c6870662447e78baf2f685fe625f5d2a5 100644 --- a/source/adios2/toolkit/transport/wan/WANZmq.cpp +++ b/source/adios2/toolkit/transport/wan/WANZmq.cpp @@ -37,12 +37,12 @@ WANZmq::~WANZmq() } } -void WANZmq::Open(const std::string &name, const OpenMode openMode) +void WANZmq::Open(const std::string &name, const Mode openMode) { m_Name = name; m_OpenMode = openMode; - if (m_OpenMode == OpenMode::Write) + if (m_OpenMode == Mode::Write) { if (m_Profiler.IsActive) { @@ -58,7 +58,7 @@ void WANZmq::Open(const std::string &name, const OpenMode openMode) m_Profiler.Timers.at("open").Pause(); } } - else if (m_OpenMode == OpenMode::Append) + else if (m_OpenMode == Mode::Append) { if (m_DebugMode) { @@ -69,7 +69,7 @@ void WANZmq::Open(const std::string &name, const OpenMode openMode) "OpenMode:r (read/receiver), in call to Open\n"); } } - else if (m_OpenMode == OpenMode::Read) + else if (m_OpenMode == Mode::Read) { if (m_Profiler.IsActive) { diff --git a/source/adios2/toolkit/transport/wan/WANZmq.h b/source/adios2/toolkit/transport/wan/WANZmq.h index 7249f963cc31d0fd464c4c9d92c594c2ee600408..e303e4cc3fcc570d12a025dc1623234c1415fecc 100644 --- a/source/adios2/toolkit/transport/wan/WANZmq.h +++ b/source/adios2/toolkit/transport/wan/WANZmq.h @@ -34,7 +34,7 @@ public: ~WANZmq(); - void Open(const std::string &name, const OpenMode openMode) final; + void Open(const std::string &name, const Mode openMode) final; void SetBuffer(char *buffer, size_t size) final; diff --git a/source/adios2/toolkit/transportman/TransportMan.cpp b/source/adios2/toolkit/transportman/TransportMan.cpp index efbd4f21dab25948c18477b01b30eeb776312370..b368e3259976310445bc8f1dc90624b7f75a703b 100644 --- a/source/adios2/toolkit/transportman/TransportMan.cpp +++ b/source/adios2/toolkit/transportman/TransportMan.cpp @@ -15,13 +15,15 @@ /// \endcond #include "adios2/helper/adiosFunctions.h" //CreateDirectory -#include "adios2/toolkit/transport/file/FilePointer.h" -#include "adios2/toolkit/transport/file/FileStream.h" +/// transports #ifndef _WIN32 -#include "adios2/toolkit/transport/file/FileDescriptor.h" +#include "adios2/toolkit/transport/file/FilePOSIX.h" #endif +#include "adios2/toolkit/transport/file/FileFStream.h" +#include "adios2/toolkit/transport/file/FileStdio.h" + namespace adios2 { namespace transportman @@ -34,7 +36,7 @@ TransportMan::TransportMan(MPI_Comm mpiComm, const bool debugMode) void TransportMan::OpenFiles(const std::vector<std::string> &baseNames, const std::vector<std::string> &names, - const OpenMode openMode, + const Mode openMode, const std::vector<Params> ¶metersVector, const bool profile) { @@ -47,7 +49,10 @@ void TransportMan::OpenFiles(const std::vector<std::string> &baseNames, if (type == "File" || type == "file") // need to create directory { - CreateDirectory(baseNames[i]); + if (openMode == Mode::Write || openMode == Mode::Append) + { + CreateDirectory(baseNames[i]); + } OpenFileTransport(names[i], openMode, parameters, profile); } } @@ -201,7 +206,7 @@ bool TransportMan::AllTransportsClosed() const noexcept // PRIVATE void TransportMan::OpenFileTransport(const std::string &fileName, - const OpenMode openMode, + const Mode openMode, const Params ¶meters, const bool profile) { @@ -209,19 +214,19 @@ void TransportMan::OpenFileTransport(const std::string &fileName, std::shared_ptr<Transport> &transport) { if (library == "stdio") { - transport = std::make_shared<transport::FilePointer>(m_MPIComm, - m_DebugMode); + transport = + std::make_shared<transport::FileStdio>(m_MPIComm, m_DebugMode); } else if (library == "fstream") { - transport = - std::make_shared<transport::FileStream>(m_MPIComm, m_DebugMode); + transport = std::make_shared<transport::FileFStream>(m_MPIComm, + m_DebugMode); } #ifndef _WIN32 else if (library == "POSIX") { - transport = std::make_shared<transport::FileDescriptor>( - m_MPIComm, m_DebugMode); + transport = + std::make_shared<transport::FilePOSIX>(m_MPIComm, m_DebugMode); } #endif else diff --git a/source/adios2/toolkit/transportman/TransportMan.h b/source/adios2/toolkit/transportman/TransportMan.h index 07efcdbfc9daec7b44d701d25a47e9a36531244e..99252a3e084313dcebccd644425baafc9aee7640 100644 --- a/source/adios2/toolkit/transportman/TransportMan.h +++ b/source/adios2/toolkit/transportman/TransportMan.h @@ -57,7 +57,7 @@ public: */ void OpenFiles(const std::vector<std::string> &baseNames, const std::vector<std::string> &names, - const OpenMode openMode, + const Mode openMode, const std::vector<Params> ¶metersVector, const bool profile); @@ -103,6 +103,16 @@ public: void WriteFiles(const char *buffer, const size_t size, const int transportIndex = -1); + /** + * Read contents from a single file and assign it to buffer + * @param buffer + * @param size + * @param start + * @param transportIndex + */ + void ReadFile(char *buffer, const size_t size, const size_t start, + const int transportIndex); + /** * Close file or files depending on transport index. Throws an exception * if transport is not a file when transportIndex > -1. @@ -117,7 +127,7 @@ protected: MPI_Comm m_MPIComm; const bool m_DebugMode = false; - void OpenFileTransport(const std::string &fileName, const OpenMode openMode, + void OpenFileTransport(const std::string &fileName, const Mode openMode, const Params ¶meters, const bool profile); }; diff --git a/source/adios2/toolkit/transportman/dataman/DataMan.cpp b/source/adios2/toolkit/transportman/dataman/DataMan.cpp index c30344df544dda4bd5010467047e8634accb8223..6bb2e19a74dfd51fdcfa1c99873898adbba6bc7b 100644 --- a/source/adios2/toolkit/transportman/dataman/DataMan.cpp +++ b/source/adios2/toolkit/transportman/dataman/DataMan.cpp @@ -21,7 +21,7 @@ DataMan::DataMan(MPI_Comm mpiComm, const bool debugMode) } void DataMan::OpenWANTransports(const std::string &name, - const OpenMode openMode, + const Mode openMode, const std::vector<Params> ¶metersVector, const bool profile) { diff --git a/source/adios2/toolkit/transportman/dataman/DataMan.h b/source/adios2/toolkit/transportman/dataman/DataMan.h index c0e009f67fe84268f8b56519bebdd6878654543e..3609b3e568e1ba96af25362ce5fc4fab40c67387 100644 --- a/source/adios2/toolkit/transportman/dataman/DataMan.h +++ b/source/adios2/toolkit/transportman/dataman/DataMan.h @@ -28,7 +28,7 @@ public: virtual ~DataMan() = default; - void OpenWANTransports(const std::string &name, const OpenMode openMode, + void OpenWANTransports(const std::string &name, const Mode openMode, const std::vector<Params> ¶metersVector, const bool profile); diff --git a/source/adios2/transform/compress/CompressZfp.h b/source/adios2/transform/compress/CompressZfp.h index 251d14b455a86b8d7dd86b8bf4cc756e912cd312..ec340e93fcfa4b1b1060ee9a79608f4f5476a37f 100644 --- a/source/adios2/transform/compress/CompressZfp.h +++ b/source/adios2/transform/compress/CompressZfp.h @@ -17,7 +17,6 @@ namespace adios2 { - namespace transform { diff --git a/testing/adios2/engine/adios1/TestADIOS1WriteRead.cpp b/testing/adios2/engine/adios1/TestADIOS1WriteRead.cpp index 99fc439bccb5667a190bba1d7553518f34418b71..31e6d3656401d56120d84bfba2b038e8ee07534b 100644 --- a/testing/adios2/engine/adios1/TestADIOS1WriteRead.cpp +++ b/testing/adios2/engine/adios1/TestADIOS1WriteRead.cpp @@ -97,7 +97,7 @@ TEST_F(ADIOS1WriteReadTest, ADIOS2ADIOS1WriteADIOS1Read1D8) io.AddTransport("file"); #endif - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < NSteps; ++step) @@ -393,7 +393,7 @@ TEST_F(ADIOS1WriteReadTest, ADIOS2ADIOS1WriteADIOS1Read2D2x4) io.AddTransport("file"); #endif - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < NSteps; ++step) @@ -702,7 +702,7 @@ TEST_F(ADIOS1WriteReadTest, _ADIOS2ADIOS1WriteADIOS1Read2D4x2) io.AddTransport("file"); #endif - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < NSteps; ++step) diff --git a/testing/adios2/engine/bp/TestBPWriteProfilingJSON.cpp b/testing/adios2/engine/bp/TestBPWriteProfilingJSON.cpp index c032ab98d40d8b1b24cac35e07ab6e9a9ab55329..c246a927c3a5938507e8cabe2b59fd0ff88a8a1f 100644 --- a/testing/adios2/engine/bp/TestBPWriteProfilingJSON.cpp +++ b/testing/adios2/engine/bp/TestBPWriteProfilingJSON.cpp @@ -76,7 +76,7 @@ TEST_F(BPWriteProfilingJSONTest, ADIOS2BPWriteProfilingJSON) io.SetParameters({{"Threads", "2"}}); io.AddTransport("File", {{"Library", "POSIX"}}); - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < 3; ++step) diff --git a/testing/adios2/engine/bp/TestBPWriteRead.cpp b/testing/adios2/engine/bp/TestBPWriteRead.cpp index 57eeafa21fcab4ad38a1264e25b3266ffc7c3822..ab90881c3ec0819c81a3590e2f007df6ef7bd0b0 100644 --- a/testing/adios2/engine/bp/TestBPWriteRead.cpp +++ b/testing/adios2/engine/bp/TestBPWriteRead.cpp @@ -65,7 +65,7 @@ TEST_F(BPWriteReadTest, ADIOS2BPWriteADIOS1Read1D8) io.SetEngine("BPFileWriter"); io.AddTransport("File"); - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < 3; ++step) @@ -281,7 +281,7 @@ TEST_F(BPWriteReadTest, ADIOS2BPWriteADIOS1Read2D2x4) io.SetEngine("BPFileWriter"); io.AddTransport("file"); - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < 3; ++step) @@ -507,7 +507,7 @@ TEST_F(BPWriteReadTest, ADIOS2BPWriteADIOS1Read2D4x2) io.SetEngine("BPFileWriter"); io.AddTransport("file"); - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < 3; ++step) diff --git a/testing/adios2/engine/bp/TestBPWriteReadAttributes.cpp b/testing/adios2/engine/bp/TestBPWriteReadAttributes.cpp index 8e8ce0704bdad98bdfdb40c11e966cc1ea292ccf..caa19224a5a8828999a1b7a8d32b643b6ef7f4d7 100644 --- a/testing/adios2/engine/bp/TestBPWriteReadAttributes.cpp +++ b/testing/adios2/engine/bp/TestBPWriteReadAttributes.cpp @@ -58,7 +58,7 @@ TEST_F(BPWriteReadAttributeTest, ADIOS2BPWriteADIOS1ReadSingleTypes) io.SetEngine("BPFileWriter"); io.AddTransport("File"); - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); // Close the file @@ -200,7 +200,7 @@ TEST_F(BPWriteReadAttributeTest, ADIOS2BPWriteADIOS1ReadArrayTypes) io.SetEngine("BPFileWriter"); io.AddTransport("File"); - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); // Close the file diff --git a/testing/adios2/engine/bp/TestBPWriteReadfstream.cpp b/testing/adios2/engine/bp/TestBPWriteReadfstream.cpp index 33164aae4921b79d6afc68e92e20a9a7fa1c6e74..4fc0cb9a8d9510adfca4009338ecf8571003e1d1 100644 --- a/testing/adios2/engine/bp/TestBPWriteReadfstream.cpp +++ b/testing/adios2/engine/bp/TestBPWriteReadfstream.cpp @@ -65,7 +65,7 @@ TEST_F(BPWriteReadTest, ADIOS2BPWriteADIOS1Read1D8fstream) io.SetEngine("BPFileWriter"); io.AddTransport("File", {{"Library", "fstream"}}); - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < 3; ++step) @@ -281,7 +281,7 @@ TEST_F(BPWriteReadTest, ADIOS2BPWriteADIOS1Read2D2x4fstream) io.SetEngine("BPFileWriter"); io.AddTransport("file", {{"Library", "fstream"}}); - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < 3; ++step) @@ -507,7 +507,7 @@ TEST_F(BPWriteReadTest, ADIOS2BPWriteADIOS1Read2D4x2fstream) io.SetEngine("BPFileWriter"); io.AddTransport("file", {{"Library", "fstream"}}); - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < 3; ++step) diff --git a/testing/adios2/engine/bp/TestBPWriteReadstdio.cpp b/testing/adios2/engine/bp/TestBPWriteReadstdio.cpp index b55d6f4290ad7d96580947d5bbe49a5378cf3e61..b50177ea26bd8c1447e6b612ba9bfe284031db8f 100644 --- a/testing/adios2/engine/bp/TestBPWriteReadstdio.cpp +++ b/testing/adios2/engine/bp/TestBPWriteReadstdio.cpp @@ -65,7 +65,7 @@ TEST_F(BPWriteReadTest, ADIOS2BPWriteADIOS1Read1D8stdio) io.SetEngine("BPFileWriter"); io.AddTransport("File", {{"Library", "stdio"}}); - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < 3; ++step) @@ -281,7 +281,7 @@ TEST_F(BPWriteReadTest, ADIOS2BPWriteADIOS1Read2D2x4stdio) io.SetEngine("BPFileWriter"); io.AddTransport("file", {{"Library", "stdio"}}); - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < 3; ++step) @@ -507,7 +507,7 @@ TEST_F(BPWriteReadTest, ADIOS2BPWriteADIOS1Read2D4x2stdio) io.SetEngine("BPFileWriter"); io.AddTransport("file", {{"Library", "stdio"}}); - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < 3; ++step) diff --git a/testing/adios2/engine/hdf5/TestHDF5WriteRead.cpp b/testing/adios2/engine/hdf5/TestHDF5WriteRead.cpp index 3ad94d769a42466683778faefa76289ff29d60a5..094ff5907738e2edbfb9bc7eefd2c7113dd9988b 100644 --- a/testing/adios2/engine/hdf5/TestHDF5WriteRead.cpp +++ b/testing/adios2/engine/hdf5/TestHDF5WriteRead.cpp @@ -220,7 +220,7 @@ TEST_F(HDF5WriteReadTest, ADIOS2HDF5WriteHDF5Read1D8) // Create the HDF5 Engine io.SetEngine("HDF5Writer"); - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < 3; ++step) @@ -427,7 +427,7 @@ TEST_F(HDF5WriteReadTest, ADIOS2HDF5WriteHDF5Read2D2x4) io.AddTransport("file"); // Create the HDF5 Engine - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < 3; ++step) @@ -642,7 +642,7 @@ TEST_F(HDF5WriteReadTest, ADIOS2HDF5WriteHDF5Read2D4x2) io.SetEngine("HDF5Writer"); io.AddTransport("file"); - auto engine = io.Open(fname, adios2::OpenMode::Write); + auto engine = io.Open(fname, adios2::Mode::Write); ASSERT_NE(engine.get(), nullptr); for (size_t step = 0; step < 3; ++step) diff --git a/testing/adios2/interface/TestADIOSDefineVariable.cpp b/testing/adios2/interface/TestADIOSDefineVariable.cpp index 100f05fc4e7df69a6512a749cf7b3cf1eb705260..f3fc08cbfb346cb556a22780025412a2758a2802 100644 --- a/testing/adios2/interface/TestADIOSDefineVariable.cpp +++ b/testing/adios2/interface/TestADIOSDefineVariable.cpp @@ -97,8 +97,8 @@ TEST_F(ADIOSDefineVariableTest, DefineGlobalArrayWithSelections) // Make a 3D selection to describe the local dimensions of the // variable we write and its offsets in the global spaces - adios2::SelectionBoundingBox sel({50, n / 2, 0}, {10, n / 2, 30}); - globalarray.SetSelection(sel); + globalarray.SetSelection( + adios2::Box<adios2::Dims>({50, n / 2, 0}, {10, n / 2, 30})); // Verify the dimensions, name, and type are correct ASSERT_EQ(globalarray.m_Shape.size(), 3); @@ -128,7 +128,7 @@ TEST_F(ADIOSDefineVariableTest, DefineGlobalArrayConstantDims) ::testing::StaticAssertTypeEq<decltype(globalarray), adios2::Variable<int> &>(); - adios2::SelectionBoundingBox sel({50, n / 2, 0}, {10, n / 2, 30}); + adios2::Box<adios2::Dims> sel({50, n / 2, 0}, {10, n / 2, 30}); EXPECT_THROW(globalarray.SetSelection(sel), std::invalid_argument); // Verify the dimensions, name, and type are correct @@ -206,10 +206,9 @@ TEST_F(ADIOSDefineVariableTest, DefineLocalArrayWithSelection) // Make a 3D selection to describe the local dimensions of the // variable we write - adios2::SelectionBoundingBox sel({}, {10, n / 2, 30}); - localarray.SetSelection(sel); + localarray.SetSelection(adios2::Box<adios2::Dims>({}, {10, n / 2, 30})); - adios2::SelectionBoundingBox selbad({50, n / 2, 0}, {10, n / 2, 30}); + adios2::Box<adios2::Dims> selbad({50, n / 2, 0}, {10, n / 2, 30}); EXPECT_THROW(localarray.SetSelection(selbad), std::invalid_argument); // Verify the dimensions, name, and type are correct @@ -235,7 +234,7 @@ TEST_F(ADIOSDefineVariableTest, DefineLocalArrayConstantDims) ::testing::StaticAssertTypeEq<decltype(localarray), adios2::Variable<int> &>(); - adios2::SelectionBoundingBox sel({}, {10, n / 2, 30}); + adios2::Box<adios2::Dims> sel({}, {10, n / 2, 30}); EXPECT_THROW(localarray.SetSelection(sel), std::invalid_argument); // Verify the dimensions, name, and type are correct diff --git a/testing/adios2/xml/TestXMLConfig.cpp b/testing/adios2/xml/TestXMLConfig.cpp index 5d3cb161b01080cd33a19083516deba70d3caaaa..e032dd00899ec5656fe3e548db14374a64e46d34 100644 --- a/testing/adios2/xml/TestXMLConfig.cpp +++ b/testing/adios2/xml/TestXMLConfig.cpp @@ -41,7 +41,8 @@ TEST_F(XMLConfigTest, TwoIOs) EXPECT_EQ(params.at("MaxBufferSize"), "20Mb"); EXPECT_EQ(params.at("InitialBufferSize"), "1Mb"); EXPECT_EQ(params.at("BufferGrowthFactor"), "2"); - auto engine = io.Open("Test BP Writer 1", adios2::OpenMode::Write); + adios2::Engine &engine = + io.Open("Test BP Writer 1", adios2::Mode::Write); }); EXPECT_NO_THROW({