Skip to content
Snippets Groups Projects
Commit 83f3fcd9 authored by Podhorszki, Norbert's avatar Podhorszki, Norbert
Browse files

added multistep write/read example to the build. Not complete example yet.

parent 412ef7df
No related branches found
No related tags found
1 merge request!102Variables3
......@@ -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)
......@@ -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();
}
......
......@@ -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)
{
......
......@@ -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.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment