diff --git a/examples/groupless/Makefile b/examples/groupless/basic/Makefile similarity index 100% rename from examples/groupless/Makefile rename to examples/groupless/basic/Makefile diff --git a/examples/groupless/reader.cpp b/examples/groupless/basic/reader.cpp similarity index 50% rename from examples/groupless/reader.cpp rename to examples/groupless/basic/reader.cpp index e95426de6c8d0ddf133d4ea4f972ec61e990ad4b..3e162a139c867cc0fff6706bdeb9146440b1518c 100644 --- a/examples/groupless/reader.cpp +++ b/examples/groupless/basic/reader.cpp @@ -23,17 +23,18 @@ int main( int argc, char* argv [] ) adios::ADIOS adios( MPI_COMM_WORLD, adiosDebug ); //Application variable - std::vector<double> myDoubles; - std::vector<float> myFloats; - const unsigned int Nx; + std::vector<double> NiceArray; + std::vector<float> RaggedArray; + unsigned int Nx; + int Nparts; + int Nwriters; 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()) + if( bpReaderSettings.undeclared() ) { // if not defined by user, we can change the default settings bpReaderSettings.SetEngine( "BP" ); // BP is the default engine @@ -48,54 +49,88 @@ int main( int argc, char* argv [] ) if( bpReader == nullptr ) throw std::ios_base::failure( "ERROR: failed to open ADIOS bpReader\n" ); - bpReader->Read<unsigned int>( "Nx", &Nx ); + /* NX */ + bpReader->Read<unsigned int>( "NX", &Nx ); // read a Global scalar which has a single value in a step + + /* nproc */ + bpReader->Read<int>( "nproc", &Nwriters ); // also a global scalar + + + /* Nparts */ + // Nparts local scalar is presented as a 1D array of Nwriters elements. + // We need to read a specific value the same way as reading from any 1D array. + // Make a single-value selection to describe our rank's position in the + // 1D array of Nwriters values. + if( rank < Nwriters ) + { + std::unique_ptr<adios::Selection> selNparts = adios.SelectionBoundingBox( {1}, {rank} ); + bpReader->Read<int>( "Nparts", selNparts, &Nparts ); + } + + /* Nice */ // inquiry about a variable, whose name we know - std::shared_ptr<adios::Variable<void> > varMyDoubles = bpReader.InquiryVariable("myDoubles"); + std::shared_ptr<adios::Variable<void> > varNice = bpReader.InquiryVariable("Nice"); - if( varMyDoubles == nullptr ) + if( varNice == nullptr ) throw std::ios_base::failure( "ERROR: failed to find variable 'myDoubles' in input file\n" ); - // ? how do we know about the type? std::string varMyDoubles->m_Type - unsigned long long int gdim = varMyDoubles->m_GlobalDimensions[0]; + // ? how do we know about the type? std::string varNice->m_Type + unsigned long long int gdim = varMyDoubles->m_GlobalDimensions[0]; // ?member var or member func? unsigned long long int ldim = gdim / nproc; unsigned long long int offs = rank * ldim; - if (rank == nproc-1) + if( rank == nproc-1 ) { ldim = gdim - (ldim * gdim); } - myDoubles.resize(ldim); + NiceArray.reserve(ldim); // Make a 1D selection to describe the local dimensions of the variable we READ and // its offsets in the global spaces - adios::Selection& sel = adios.SelectionBoundingBox( {ldim}, {offs} ); // local dims and offsets; both as list - bpReader->Read<double>( "myDoubles", myDoubles.data() ); // Base class Engine own the Read<T> that will call overloaded Read from Derived + 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 + + /* Ragged */ // inquiry about a variable, whose name we know - std::shared_ptr<adios::Variable<void> > varMyFloats = bpReader.InquiryVariable("myFloats"); - // We have here varMyFloats->sum_nblocks, nsteps, nblocks[], global - if (rank < varMyFloats->nblocks[0]) + std::shared_ptr<adios::Variable<void> > varRagged = bpReader.InquiryVariable("Ragged"); + if( varRagged->m_GlobalDimensions[1] != adios::VARYING_DIMENSION) + { + throw std::ios_base::failure( "Unexpected condition: Ragged array's fast dimension " + "is supposed to be VARYING_DIMENSION\n" ); + } + // We have here varRagged->sum_nblocks, nsteps, nblocks[], global + if( rank < varRagged->nblocks[0] ) // same as rank < Nwriters in this example { // get per-writer size information - varMyFloats->InquiryBlocks(); + varRagged->InquiryBlocks(); // now we have the dimensions per block - unsigned long long int ldim = varMyFloats->blockinfo[rank].m_Dimensions[0]; - myFloats.resize( ldim ); + unsigned long long int ldim = varRagged->blockinfo[rank].m_Dimensions[0]; + RaggedArray.resize( ldim ); + + std::unique_ptr<adios::Selection> wbsel = adios.SelectionWriteblock( rank ); + bpReader->Read<float>( "Ragged", wbsel, RaggedArray.data() ); - adios::Selection& sel = adios.SelectionWriteblock( rank ); - bpReader->Read<double>( "myDoubles", myDoubles.data() ); + // We can use bounding box selection as well + std::unique_ptr<adios::Selection> rbbsel = adios.SelectionBoundingBox( {1,ldim}, {rank,0} ); + bpReader->Read<float>( "Ragged", rbbsel, RaggedArray.data() ); } + /* Extra help to process Ragged */ + int maxRaggedDim = varRagged->m_GlobalDimensions[1]; // contains the largest + + + // promise to not read more from this step - bpReader->ReleaseStep(); + bpReader->Release(); // want to move on to the next available step //bpReader->AdvanceStep(adios::NextImmediateStep); //bpReader->AdvanceStep(adios::NextAvailableStep); - bpReader->AdvanceStep(); // default is adios::NextAvailableStep + bpReader->Advance(); // default is adios::NextAvailableStep // Close file/stream diff --git a/examples/groupless/writer.cpp b/examples/groupless/basic/writer.cpp similarity index 60% rename from examples/groupless/writer.cpp rename to examples/groupless/basic/writer.cpp index 9b13979e29f44cf23446390e8814fbca17826b09..485ba658d5bbae4a2cbd690c0bdb9c9b3d59e252 100644 --- a/examples/groupless/writer.cpp +++ b/examples/groupless/basic/writer.cpp @@ -11,6 +11,13 @@ #include <mpi.h> #include "ADIOS_OOP.h" +namespace adios { + typedef enum { + VARYING_DIMENSION = -1, + LOCAL_VALUE = 0, + GLOBAL_VALUE = 1 + }; +} int main( int argc, char* argv [] ) { @@ -26,39 +33,43 @@ int main( int argc, char* argv [] ) const unsigned int Nx = 10; const int Nparts = rand()%6 + 5; // random size per process, 5..10 each - std::vector<double> NiceVar( Nx ); - for (int i=0; i < NX; i++) + std::vector<double> NiceArray( Nx ); + for( int i=0; i < Nx; i++ ) { - NiceVar[i] = rank*NX + (double)i; + NiceArray[i] = rank*Nx + (double)i; } - std::vector<float> RaggedVar( Nparts ); - for (int i=0; i < Nparts; i++) + + std::vector<float> RaggedArray( Nparts ); + for( int i=0; i < Nparts; i++ ) { - RaggedVar[i] = rank*NX + (float)i; + RaggedArray[i] = rank*Nx + (float)i; } try { //Define group and variables with transforms, variables don't have functions, only group can access variables - adios::Variable<int>& varNX = adios.DefineVariable<unsigned int>( "NX" ); // global scalar value - adios::Variable<int>& varNparts = adios.DefineVariable<int>( "Nparts" ); // scalar value different on every process - adios::Variable<double>& varNice = adios.DefineVariable<double>( "D", {nproc*Nx} ); // 1D global array - adios::Variable<float>& varRagged = adios.DefineVariable<float>( "F", {nproc,adios::VARYING_DIMENSION} ); // local array + adios::Variable<unsigned int>& varNX = adios.DefineVariable<unsigned int>( "NX" ); // global single-value across processes + adios::Variable<int>& varNproc = adios.DefineVariable<int>( "nproc", adios::GLOBAL_VALUE ); // same def for global value + adios::Variable<int>& varNparts = adios.DefineVariable<int>( "Nparts", adios::LOCAL_VALUE ); // a single-value different on every process + adios::Variable<double>& varNice = adios.DefineVariable<double>( "Nice", {nproc*Nx} ); // 1D global array + adios::Variable<float>& varRagged = adios.DefineVariable<float>( "Ragged", {nproc,adios::VARYING_DIMENSION} ); // ragged array //add transform to variable in group...not executed (just testing API) adios::Transform bzip2 = adios::transform::BZIP2( ); - NiceVar.AddTransform( bzip2, 1 ); + varNice->AddTransform( bzip2, 1 ); //Define method for engine creation // 1. Get method def from config file or define new one adios::Method& bpWriterSettings = adios.GetMethod( "output" ); - if (bpWriterSettings.undeclared()) + if( bpWriterSettings.undeclared() ) { // if not defined by user, we can change the default settings bpWriterSettings.SetEngine( "BP" ); // BP is the default engine - bpWriterSettings.SetAggregation( (nproc+1)/2 ); // number of aggregators - bpWriterSettings.AddTransport( "BP", "have_metadata_file=yes" ); // BP is the default transport + bpWriterSettings.AddTransport( "File", "lucky=yes" ); // ISO-POSIX file is the default transport + // Passing parameters to the transport + bpWriterSettings.SetParameters("have_metadata_file","yes" ); // Passing parameters to the engine + bpWriterSettings.SetParameters( "Aggregation", (nproc+1)/2 ); // number of aggregators } //Open returns a smart pointer to Engine containing the Derived class Writer @@ -68,21 +79,27 @@ int main( int argc, char* argv [] ) if( bpWriter == nullptr ) throw std::ios_base::failure( "ERROR: failed to open ADIOS bpWriter\n" ); - if (rank == 0) + if( rank == 0 ) { + // Writing a global scalar from only one process bpWriter->Write<unsigned int>( varNX, &Nx ); } + // Writing a local scalar on every process. Will be shown at reading as a 1D array bpWriter->Write<int>( varNparts, &Nparts ); + // Writing a global scalar on every process is useless. Information will be thrown away + // and only rank 0's data will be in the output + bpWriter->Write<int>( varNproc, &nproc ); + // Make a 1D selection to describe the local dimensions of the variable we write and // its offsets in the global spaces adios::Selection& sel = adios.SelectionBoundingBox( {Nx}, {rank*Nx} ); // local dims and offsets; both as list - NiceVar.SetSelection( sel ); - bpWriter->Write<double>( varMyDoubles, NiceVar.data() ); // Base class Engine own the Write<T> that will call overloaded Write from Derived + NiceArray.SetSelection( sel ); + bpWriter->Write<double>( varNice, NiceArray.data() ); // Base class Engine own the Write<T> that will call overloaded Write from Derived - adios::Selection& lsel = adios.SelectionBoundingBox( {Nx} ); // 0 offsets assumed - RaggedVar.SetSelection( sel ); - bpWriter->Write<float>( varMyFloats, RaggedVar.data() ); // Base class Engine own the Write<T> that will call overloaded Write from Derived + adios::Selection& lsel = adios.SelectionBoundingBox( {1,Nparts}, {rank,0} ); + RaggedArray.SetSelection( sel ); + bpWriter->Write<float>( varRagged, RaggedArray.data() ); // Base class Engine own the Write<T> that will call overloaded Write from Derived // Indicate we are done for this step // N-to-M Aggregation, disk I/O will be performed during this call, unless