diff --git a/examples/groupless/multistep/CMakeLists.txt b/examples/groupless/multistep/CMakeLists.txt index 97c434eab396f551791abb62bb7e53e70872e8a1..902a35b6cfe0c6d1a21d5773670956858c679959 100644 --- a/examples/groupless/multistep/CMakeLists.txt +++ b/examples/groupless/multistep/CMakeLists.txt @@ -9,6 +9,17 @@ if(ADIOS_USE_MPI) add_executable(writer_multistep writer_multistep.cpp) target_include_directories(writer_multistep PRIVATE ${MPI_C_INCLUDE_PATH}) target_link_libraries(writer_multistep ${MPI_C_LIBRARIES}) + + add_executable(reader_stepping reader_stepping.cpp) + target_include_directories(reader_stepping PRIVATE ${MPI_C_INCLUDE_PATH}) + target_link_libraries(reader_stepping ${MPI_C_LIBRARIES}) + + add_executable(reader_allsteps reader_allsteps.cpp) + target_include_directories(reader_allsteps PRIVATE ${MPI_C_INCLUDE_PATH}) + target_link_libraries(reader_allsteps ${MPI_C_LIBRARIES}) + endif() target_link_libraries(writer_multistep adios2) +target_link_libraries(reader_stepping adios2) +target_link_libraries(reader_allsteps adios2) diff --git a/examples/groupless/multistep/reader_allsteps.cpp b/examples/groupless/multistep/reader_allsteps.cpp index 0b3afb4f8a169dc9925a0bec264ad8f420f94bc9..935d298c8492968e42aa4c0d6608089d41566b91 100644 --- a/examples/groupless/multistep/reader_allsteps.cpp +++ b/examples/groupless/multistep/reader_allsteps.cpp @@ -14,6 +14,41 @@ #include <adios2.h> #include <mpi.h> +template <class T> +T **Make2DArray(int nRows, int nCols) +{ + T **ptr = new T *[nRows]; + ptr[0] = new T[nRows * nCols]; + for (int i = 1; i < nRows; i++) + { + ptr[i] = ptr[i - 1] + nCols; + } + return ptr; +} + +template <class T> +void Delete2DArray(T **ptr) +{ + delete[] ptr[0]; + delete[] ptr; +} + +template <class T> +void Print2DArray(T **ptr, int nRows, int nCols, std::string name) +{ + std::cout << name << " = { \n"; + for (int step = 0; step < nRows; step++) + { + std::cout << " { "; + for (int col = 0; col < nCols; col++) + { + std::cout << ptr[step][col] << " "; + } + std::cout << "}\n"; + } + std::cout << "}\n"; +} + int main(int argc, char *argv[]) { int rank, nproc; @@ -22,29 +57,46 @@ int main(int argc, char *argv[]) MPI_Comm_size(MPI_COMM_WORLD, &nproc); const bool adiosDebug = true; - adios::ADIOS adios(MPI_COMM_WORLD, adiosDebug); - - // Application variable - std::vector<double> NiceArray; - std::vector<float> RaggedArray; + adios::ADIOS adios(MPI_COMM_WORLD, adios::Verbose::WARN); - int Nparts; + // Info variables from the file int Nwriters; int Nsteps; + // Data variables from the file + // 1. Global value, constant across processes, constant over time + unsigned int Nx; + // 2. Local value, varying across processes, constant over time + std::vector<int> ProcessID; + // 3. Global array, global dimensions, local dimensions and offsets are + // constant over time + std::vector<double> GlobalArrayFixedDims; + + // 4. Local array, local dimensions are + // constant over time (but different across processors here) + std::vector<float> LocalArrayFixedDims; + + // 5. Global value, constant across processes, VARYING value over time + std::vector<unsigned int> Nys; + // 6. Local value, varying across processes, VARYING over time + // Read as a 2D array, time as first dimension + + // 7. Global array, dimensions and offsets are VARYING over time + std::vector<double> GlobalArray; + // 8. Local array, dimensions and offsets are VARYING over time + std::vector<float> IrregularArray; try { // Define method for engine creation // 1. Get method def from config file or define new one - adios::Method &bpReaderSettings = adios.GetMethod("input"); - if (bpReaderSettings.undeclared()) + adios::Method &bpReaderSettings = adios.DeclareMethod("input"); + if (!bpReaderSettings.IsUserDefined()) { // if not defined by user, we can change the default settings - bpReaderSettings.SetEngine("BP"); // BP is the default engine - // By default we see all steps available in a file, so the next line - // is - // not needed - bpReaderSettings.SetParameters("Stepping", false); + bpReaderSettings.SetEngine( + "ADIOS1Reader"); // BP is the default engine + // see only one step at a time + bpReaderSettings.SetParameters("OpenAsFile"); } // Create engine smart pointer due to polymorphism, @@ -53,97 +105,93 @@ int main(int argc, char *argv[]) // this would just open with a default transport, which is "BP" auto bpReader = adios.Open("myNumbers.bp", "r", bpReaderSettings); - // All the above is same as default use: - // auto bpReader = adios.Open( "myNumbers.bp", "r"); - if (bpReader == nullptr) throw std::ios_base::failure( "ERROR: failed to open ADIOS bpReader\n"); - /* Note: there is no global number of steps. Each variable has its own + /* Note: there is no global number of steps. Each variable has its + * own * number of steps */ + adios::Variable<int> *vNproc = bpReader->InquireVariableInt("Nproc"); + Nwriters = vNproc->m_Data[0]; + std::cout << "# of writers = " << Nwriters << std::endl; + /* NX */ - /* There is a single value for each step. We can read all into a 1D - * array - * with a step selection. - * We can also just conveniently get the first with a simple read - * statement. - * Steps are not automatically presented as an array dimension and read - * does - * not read it as array. + /* There is a single value written once. */ - unsigned int Nx; - bpReader->Read<unsigned int>( - "NX", - &Nx); // read a Global scalar which has a single value in a step - - std::shared_ptr<adios::Variable<void>> varNx = - bpReader.InquiryVariable("Nx"); - std::vector<int> Nxs(varNx->nsteps()); // number of steps available + // read a Global scalar which has a single value in a step + adios::Variable<unsigned int> *vNX = + bpReader->InquireVariableUInt("NX"); + Nx = vNX->m_Data[0]; + // bpReader->Read<unsigned int>("NX", &Nx); + std::cout << "NX = " << Nx << std::endl; + + /* NY */ + /* We can read all into a 1D array with a step selection. + Steps are not automatically presented as an array dimension + and read does not read it as array by default. + */ + adios::Variable<unsigned int> *vNY = + bpReader->InquireVariableUInt("NY"); + Nys.resize(vNY->GetNSteps()); // number of steps available // make a StepSelection to select multiple steps. Args: From, #of // consecutive steps - std::unique_ptr<adios::StepSelection> stepsNx = - adios.StepSelection(0, varNx->nsteps()); // ? How do we make a selection for an arbitrary list of steps ? - varNX.SetStepSelection(stepsNx); - bpReader->Read<unsigned int>(varNx, Nxs.data()); + vNY->SetStepSelection(0, vNY->GetNSteps()); + bpReader->Read<unsigned int>(*vNY, Nys.data()); - auto itmax = std::max_element(std::begin(Nxs), std::end(Nxs)); - auto itmin = std::min_element(std::begin(Nxs), std::end(Nxs)); - if (*itmin != *itmax) + std::cout << "NY = { "; + for (const auto &it : Nys) { - throw std::ios_base::failure( - "ERROR: NX is not the same at all steps!\n"); + std::cout << it << " "; } - - /* nproc */ - bpReader->Read<int>("nproc", &Nwriters); // also a global scalar + std::cout << "}\n"; /* Nparts */ - // Nparts local scalar is presented as a 1D array of Nwriters elements. + // Nparts local scalar is presented as a 1D array of Nwriters + // elements. // We can read all steps into a 2D array of nproc * Nwriters - std::shared_ptr<adios::Variable<void>> varNparts = - bpReader.InquiryVariable("Nparts"); - std::vector<int> partsV(Nproc * Nwriters); - varNparts->SetStepSelection( - adios.StepSelection(0, varNparts->nsteps())); - bpReader->Read<int>(varNparts, - partsV.data()); // missing spatial selection = whole - // array at each step - - /* Nice */ + adios::Variable<unsigned int> *vNparts = + bpReader->InquireVariableUInt("Nparts"); + unsigned int **Nparts = + Make2DArray<unsigned int>(vNparts->GetNSteps(), Nwriters); + vNparts->SetStepSelection(0, vNparts->GetNSteps()); + bpReader->Read<unsigned int>(*vNparts, Nparts[0]); + Print2DArray(Nparts, vNparts->GetNSteps(), Nwriters, "Nparts"); + Delete2DArray(Nparts); + + /* GlobalArrayFixedDims */ // inquiry about a variable, whose name we know - std::shared_ptr<adios::Variable<void>> varNice = - bpReader.InquiryVariable("Nice"); + std::shared_ptr<adios::Variable<void *>> vGlobalArrayFixedDims = + bpReader->InquireVariable("GlobalArrayFixedDims"); - if (varNice == nullptr) - throw std::ios_base::failure("ERROR: failed to find variable " - "'myDoubles' in input file\n"); + if (vGlobalArrayFixedDims == nullptr) + throw std::ios_base::failure( + "ERROR: failed to find variable " + "'GlobalArrayFixedDims' in input file\n"); // ? how do we know about the type? std::string varNice->m_Type - unsigned long long int gdim = - varMyDoubles->m_Shape[0]; // ?member var or member func? - unsigned long long int ldim = gdim / nproc; - unsigned long long int offs = rank * ldim; + std::size_t gdim = + vGlobalArrayFixedDims->m_Shape[0]; // ?member var or member func? + std::size_t count = gdim / nproc; + std::size_t start = rank * count; if (rank == nproc - 1) { - ldim = gdim - (ldim * gdim); + count = gdim - (count * gdim); } - NiceArray.reserve(ldim); + GlobalArrayFixedDims.resize(count); // Make a 1D selection to describe the local dimensions of the variable - // we - // READ and - // its offsets in the global spaces - std::unique_ptr<adios::Selection> bbsel = adios.SelectionBoundingBox( - {ldim}, {offs}); // local dims and offsets; both as list - bpReader->Read<double>("Nice", bbsel, - NiceArray.data()); // Base class Engine own the - // Read<T> that will call - // overloaded Read from Derived + // we READ and its offsets in the global spaces + vGlobalArrayFixedDims->SetSelection({start}, {count}); + bpReader->ScheduleRead<void>(vGlobalArrayFixedDims, + GlobalArrayFixedDims.data()); + bpReader->PerformReads(adios::PerformReadMode::BLOCKINGREAD); +// overloaded Read from Derived +#if 0 /* Ragged */ // inquiry about a variable, whose name we know std::shared_ptr<adios::Variable<void>> varRagged = @@ -162,9 +210,9 @@ int main(int argc, char *argv[]) varRagged->InquiryBlocks(); // now we have the dimensions per block - unsigned long long int ldim = + unsigned long long int count = varRagged->blockinfo[rank].m_Dimensions[0]; - RaggedArray.resize(ldim); + RaggedArray.resize(count); std::unique_ptr<adios::Selection> wbsel = adios.SelectionWriteblock(rank); @@ -172,7 +220,7 @@ int main(int argc, char *argv[]) // We can use bounding box selection as well std::unique_ptr<adios::Selection> rbbsel = - adios.SelectionBoundingBox({1, ldim}, {rank, 0}); + adios.SelectionBoundingBox({1, count}, {rank, 0}); bpReader->Read<float>("Ragged", rbbsel, RaggedArray.data()); } @@ -182,6 +230,8 @@ int main(int argc, char *argv[]) std::vector<int> raggedDims = varRagged->GetVaryingGlobalDimensions( 1); // contains all individual sizes in that dimension +#endif + // Close file/stream bpReader->Close(); } diff --git a/examples/groupless/multistep/reader_stepping.cpp b/examples/groupless/multistep/reader_stepping.cpp index 7835c54dbe1479aab44a75dc9143cf60ced3534f..d7c0f3d5a81f7513c1319ead4680b049259999d8 100644 --- a/examples/groupless/multistep/reader_stepping.cpp +++ b/examples/groupless/multistep/reader_stepping.cpp @@ -22,53 +22,84 @@ int main(int argc, char *argv[]) MPI_Comm_size(MPI_COMM_WORLD, &nproc); const bool adiosDebug = true; - adios::ADIOS adios(MPI_COMM_WORLD, adiosDebug); + adios::ADIOS adios(MPI_COMM_WORLD); - // Application variable - std::vector<double> NiceArray; - std::vector<float> RaggedArray; - unsigned int Nx; - int Nparts; + // Info variables from the file int Nwriters; int Nsteps; + // Data variables from the file + // 1. Global value, constant across processes, constant over time + unsigned int Nx; + // 2. Local value, varying across processes, constant over time + std::vector<int> ProcessID; + // 3. Global array, global dimensions, local dimensions and offsets are + // constant over time + std::vector<double> GlobalArrayFixedDims; + + // 4. Local array, local dimensions are + // constant over time (but different across processors here) + std::vector<float> LocalArrayFixedDims; + + // 5. Global value, constant across processes, VARYING value over time + unsigned int Ny; + // 6. Local value, varying across processes, VARYING over time + std::vector<unsigned int> Nparts; + // 7. Global array, dimensions and offsets are VARYING over time + std::vector<double> GlobalArray; + // 8. Local array, dimensions and offsets are VARYING over time + std::vector<float> IrregularArray; try { // Define method for engine creation // 1. Get method def from config file or define new one - adios::Method &bpReaderSettings = adios.GetMethod("input"); - if (bpReaderSettings.undeclared()) + adios::Method &bpReaderSettings = adios.DeclareMethod("input"); + if (!bpReaderSettings.IsUserDefined()) { // if not defined by user, we can change the default settings - bpReaderSettings.SetEngine("BP"); // BP is the default engine - bpReaderSettings.SetParameters("Stepping", - true); // see only one step at a time + bpReaderSettings.SetEngine( + "ADIOS1Reader"); // BP is the default engine + // see only one step at a time + // this is default, nothing to be done } - // Create engine smart pointer due to polymorphism, - // Default behavior - // auto bpReader = adios.Open( "myNumbers.bp", "r" ); - // this would just open with a default transport, which is "BP" - try + auto bpReader = adios.Open("myNumbers.bp", "r", bpReaderSettings); + if (bpReader != nullptr) { - auto bpReader = adios.Open("myNumbers.bp", "r", bpReaderSettings); - - while (true) + int step = 0; + while (bpReader->GetAdvanceStatus() == adios::AdvanceStatus::OK) { + std::cout << "Process step " << std::to_string(step) + << std::endl; /* NX */ - bpReader->Read<unsigned int>("NX", - &Nx); // read a Global scalar which - // has a single value in a - // step + if (step == 0) + { + // read a Global scalar which has a single value in a step + adios::Variable<int> *vNproc = + bpReader->InquireVariableInt("Nproc"); + Nwriters = vNproc->m_Data[0]; + std::cout << "# of writers = " << Nwriters << std::endl; + + adios::Variable<unsigned int> *vNX = + bpReader->InquireVariableUInt("NX"); + Nx = vNX->m_Data[0]; + // bpReader->Read<unsigned int>("NX", &Nx); + std::cout << "NX = " << Nx << std::endl; + } - /* nproc */ - bpReader->Read<int>("nproc", &Nwriters); // also a global scalar + adios::Variable<unsigned int> *vNY = + bpReader->InquireVariableUInt("NY"); + Ny = vNY->m_Data[0]; + std::cout << "NY = " << Ny << std::endl; +#if 0 /* Nparts */ // Nparts local scalar is presented as a 1D array of Nwriters // elements. // We can read all as a 1D array std::vector<int> partsV(Nwriters); + adios::Variable<unsigned int> *vNproc = + bpReader->InquireVariableUInt("Nproc"); bpReader->Read<int>("Nparts", &partsV); // read with string name, no // selection => read whole array @@ -86,7 +117,7 @@ int main(int argc, char *argv[]) // ? how do we know about the type? std::string varNice->m_Type unsigned long long int gdim = varMyDoubles->m_Shape[0]; // ?member var or - // member func? + // member func? unsigned long long int ldim = gdim / nproc; unsigned long long int offs = rank * ldim; if (rank == nproc - 1) @@ -110,8 +141,7 @@ int main(int argc, char *argv[]) // inquiry about a variable, whose name we know std::shared_ptr<adios::Variable<void>> varRagged = bpReader.InquiryVariable("Ragged"); - if (varRagged->m_Shape[1] != - adios::VARYING_DIMENSION) + if (varRagged->m_Shape[1] != adios::VARYING_DIMENSION) { throw std::ios_base::failure( "Unexpected condition: Ragged array's fast " @@ -150,6 +180,7 @@ int main(int argc, char *argv[]) varRagged->GetVaryingGlobalDimensions( 1); // contains all individual sizes in that // dimension +#endif // promise to not read more from this step bpReader->Release(); @@ -158,27 +189,12 @@ int main(int argc, char *argv[]) // bpReader->Advance(adios::NextStep); // bpReader->Advance(adios::LatestStep); bpReader->Advance(); // default is adios::NextStep + ++step; } // Close file/stream bpReader->Close(); } - catch (adios::end_of_stream &e) - { - if (rank == 0) - { - std::cout << "Reached end of stream, end processing loop.\n"; - } - // Close file/stream - bpReader->Close(); - } - catch (adios::file_not_found &e) - { - if (rank == 0) - { - std::cout << "File/stream does not exist, quit.\n"; - } - } } catch (std::invalid_argument &e) { diff --git a/examples/groupless/multistep/writer_multistep.cpp b/examples/groupless/multistep/writer_multistep.cpp index 0879ddb4d6ef2bc8b836a593b11399043c069170..6f98f599dc0fa0ab074753c86b63c779de8750d8 100644 --- a/examples/groupless/multistep/writer_multistep.cpp +++ b/examples/groupless/multistep/writer_multistep.cpp @@ -23,6 +23,10 @@ int main(int argc, char *argv[]) const bool adiosDebug = true; const int NSTEPS = 5; + // generate different random numbers on each process, + // but always the same sequence at each run + srand(rank * 32767); + adios::ADIOS adios(MPI_COMM_WORLD, adios::Verbose::WARN); // Application variables for output @@ -58,10 +62,11 @@ int main(int argc, char *argv[]) // 1. Global value, constant across processes, constant over time adios::Variable<unsigned int> &varNX = adios.DefineVariable<unsigned int>("NX"); + adios::Variable<int> &varNproc = adios.DefineVariable<int>("Nproc"); // 2. Local value, varying across processes, constant over time adios::Variable<int> &varProcessID = adios.DefineVariable<int>( - "processid", {nproc}, {rank}, {1}, adios::ConstantShape); + "ProcessID", {nproc}, {rank}, {1}, adios::ConstantShape); // 3. Global array, global dimensions (shape), offsets (start) and local // dimensions (count) are constant over time @@ -98,8 +103,9 @@ int main(int argc, char *argv[]) adios::Variable<double> &varGlobalArray = adios.DefineVariable<double>("GlobalArray", {adios::UnknownDim}); - // 8. Ragged array, dimensions and offsets are VARYING over time - // Want to see this at reading as a ragged 2D array with rank serving as + // 8. Local array, dimensions and offsets are VARYING over time + // Want to see this at reading as an irregular 2D array with rank + // serving as // offset in the slow dimension adios::Variable<float> &varIrregularArray = adios.DefineVariable<float>("Irregular", {nproc, adios::VarDim}); @@ -145,7 +151,8 @@ int main(int argc, char *argv[]) GlobalArray[i] = rank * Ny + (double)i; } - Nparts = rand() % 6 + 5; // random size per process, 5..10 each + // random size per process, 5..10 each + Nparts = rand() % 6 + 5; IrregularArray.reserve(Nparts); for (int i = 0; i < Nparts; i++) { @@ -159,13 +166,17 @@ int main(int argc, char *argv[]) if (step == 0) { bpWriter->Write<unsigned int>(varNX, Nx); + bpWriter->Write<int>("Nproc", nproc); } bpWriter->Write<unsigned int>(varNY, Ny); } // 2. and 6. Writing a local scalar on every process. Will be shown // at reading as a 1D array - bpWriter->Write<int>(varProcessID, ProcessID); + if (step == 0) + { + bpWriter->Write<int>(varProcessID, ProcessID); + } bpWriter->Write<unsigned int>(varNparts, Nparts); // 3.