From 3397c5e54d08f5571beb46e8b35cd9c3f62d9e4d Mon Sep 17 00:00:00 2001 From: wfg <wfg@pc0098504.ornl.gov> Date: Thu, 13 Oct 2016 18:02:05 -0400 Subject: [PATCH] Ready to start testing hello Transport MPI and nonMPI POSIX methods. Warning: Makefile only compiling for all, not nompi or mpi --- Makefile | 42 ++--- doc/Doxyfile | 14 +- examples/hello/helloADIOS_nompi.cpp | 2 +- examples/hello/writer2Groups.xml | 72 +++++++++ include/ADIOS.h | 16 +- include/ADIOSFunctions.h | 15 ++ include/CGroup.h | 65 +++++++- include/CTransport.h | 11 +- include/CVariable.h | 7 +- include/SSupport.h | 23 +-- include/mpi/transport/CPOSIXMPI.h | 2 +- include/mpi/transport/CTransportMPI.h | 2 +- include/nompi/transport/CPOSIXNoMPI.h | 2 +- include/nompi/transport/CTransportNoMPI.h | 2 +- src/ADIOS.cpp | 50 ++++-- src/ADIOSFunctions.cpp | 177 +++++++++++++++++----- src/CGroup.cpp | 51 ++++++- src/mpi/transport/CPOSIXMPI.cpp | 2 +- src/nompi/transport/CPOSIXNoMPI.cpp | 2 +- 19 files changed, 437 insertions(+), 120 deletions(-) create mode 100644 examples/hello/writer2Groups.xml diff --git a/Makefile b/Makefile index bf31f7bae..000cffe96 100644 --- a/Makefile +++ b/Makefile @@ -22,56 +22,46 @@ ADIOS_INC=-I./include INCLUDE=$(ADIOS_INC) #Build Header Dependencies, if one changes it will rebuild -MPI_HFiles=$(shell find ./include/mpi/ -type f -name "*MPI.h") -NoMPI_HFiles=$(shell find ./include/nompi/ -type f -name "*NoMPI.h") -Local_HFiles=$(shell find ./include/ -type f -name "*.h") +MPI_HFiles=$(shell find ./include/mpi -type f -name "*MPI.h") +NoMPI_HFiles=$(shell find ./include/nompi -type f -name "*NoMPI.h") +Local_HFiles=$(shell find ./include -type f -name "*.h") HFiles=$(MPI_HFiles) $(NoMPI_HFiles) $(Local_HFiles) #Source *.cpp Files and Object Files -MPI_CPPFiles=$(shell find ./src/mpi/ -type f -name "*MPI.cpp") +MPI_CPPFiles=$(shell find ./src/mpi -type f -name "*MPI.cpp") MPI_ObjFiles=$(patsubst ./src/mpi/transport/%.cpp, ./bin/%.o, $(MPI_CPPFiles)) -NoMPI_CPPFiles=$(shell find ./src/nompi/ -type f -name "*NoMPI.cpp") +NoMPI_CPPFiles=$(shell find ./src/nompi -type f -name "*NoMPI.cpp") NoMPI_ObjFiles=$(patsubst ./src/nompi/transport/%.cpp, ./bin/%.o, $(NoMPI_CPPFiles)) +Common_CPPFiles=$(wildcard ./src/*.cpp) +Common_ObjFiles=$(patsubst ./src/%.cpp, ./bin/%.o, $(Common_CPPFiles)) + + ObjFiles=$(MPI_ObjFiles) $(NoMPI_ObjFiles) #Build all MPI and noMPI -all: $(MPI_ObjFiles) $(NoMPI_ObjFiles) ./bin/ADIOS.o ./bin/ADIOSFunctions.o $(HFiles) - @echo "ADIOS MPI headers" $(MPI_HFiles); - @echo "ADIOS No MPI headers" $(NoMPI_HFiles); +all: $(MPI_ObjFiles) $(NoMPI_ObjFiles) $(Common_ObjFiles) $(HFiles) $(AR) rcs ./lib/libadios.a $(MPI_ObjFiles) $(NoMPI_ObjFiles) ./bin/ADIOS.o ./bin/ADIOSFunctions.o ./bin/CGroup.o #MPI build -mpi: $(MPI_ObjFiles) ./bin/ADIOS.o $(MPI_HFiles) $(Local_HFiles) +mpi: $(MPI_ObjFiles) $(Common_ObjFiles) $(MPI_HFiles) $(Local_HFiles) $(AR) rcs ./lib/libadios.a $(MPI_ObjFiles) ./bin/ADIOS.o ./bin/ADIOSFunctions.o ./bin/CGroup.o ./bin/%.o: ./src/mpi/transport/%.cpp $(MPICC) $(CFLAGS) -DHAVE_MPI $(INCLUDE) -o $@ $< - -./bin/ADIOS.o: ./src/ADIOS.cpp + +./bin/%.o: ./src/%.cpp $(MPICC) $(CFLAGS) -DHAVE_MPI $(INCLUDE) -o $@ $< - #NoMPI build -nompi: $(NoMPI_ObjFiles) ./bin/ADIOS_nompi.o ./bin/ADIOSFunctions.o ./bin/CGroup.o $(NoMPI_HFiles) $(Local_HFiles) - $(AR) rcs ./lib/libadios_nompi.a $(NoMPI_ObjFiles) ./bin/ADIOS_nompi.o ./bin/ADIOSFunctions.o ./bin/CGroup.o +nompi: $(NoMPI_ObjFiles) $(Common_ObjFiles) $(NoMPI_HFiles) $(Local_HFiles) + $(AR) rcs ./lib/libadios_nompi.a $(NoMPI_ObjFiles) $(Common_ObjFiles) ./bin/%.o: ./src/nompi/transport/%.cpp $(NoMPI_HFiles) $(Local_HFiles) $(CC) $(CFLAGS) $(INCLUDE) -o $@ $< - -./bin/ADIOS_nompi.o: ./src/ADIOS.cpp $(NoMPI_HFiles) $(Local_HFiles) - $(CC) $(CFLAGS) $(INCLUDE) -o $@ $< - - -#Local common files -./bin/ADIOSFunctions.o: ./src/ADIOSFunctions.cpp $(NoMPI_HFiles) $(Local_HFiles) - $(CC) $(CFLAGS) $(INCLUDE) -o $@ $< - -./bin/CGroup.o: ./src/CGroup.cpp $(NoMPI_HFiles) $(Local_HFiles) - $(CC) $(CFLAGS) $(INCLUDE) -o $@ $< - + clean: rm ./bin/*.o ./lib/libadios.a ./lib/libadios_nompi.a diff --git a/doc/Doxyfile b/doc/Doxyfile index 0b9aae509..f4d1ec3b4 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -434,7 +434,7 @@ EXTRACT_PACKAGE = NO # included in the documentation. # The default value is: NO. -EXTRACT_STATIC = YES +EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, @@ -771,7 +771,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = /home/wfg/workspace/ADIOSPP/include /home/wfg/workspace/ADIOSPP/include/mpi/transport /home/wfg/workspace/ADIOSPP/include/nompi/transport +INPUT = /home/wfg/workspace/ADIOSPP/include /home/wfg/workspace/ADIOSPP/include/mpi/transport /home/wfg/workspace/ADIOSPP/include/nompi/transport /home/wfg/workspace/ADIOSPP/src /home/wfg/workspace/ADIOSPP/src/mpi/transport /home/wfg/workspace/ADIOSPP/src/nompi/transport # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -2218,7 +2218,7 @@ GROUP_GRAPHS = YES # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -UML_LOOK = NO +UML_LOOK = YES # If the UML_LOOK tag is enabled, the fields and methods are shown inside the # class node. If there are many fields or methods and many nodes the graph may @@ -2239,7 +2239,7 @@ UML_LIMIT_NUM_FIELDS = 10 # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -TEMPLATE_RELATIONS = NO +TEMPLATE_RELATIONS = YES # If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to # YES then doxygen will generate a graph for each documented file showing the @@ -2281,7 +2281,7 @@ CALL_GRAPH = YES # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -CALLER_GRAPH = NO +CALLER_GRAPH = YES # If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical # hierarchy of all classes instead of a textual one. @@ -2339,7 +2339,7 @@ DOT_PATH = # command). # This tag requires that the tag HAVE_DOT is set to YES. -DOTFILE_DIRS = +DOTFILE_DIRS = /home/wfg/workspace/ADIOSPP/include /home/wfg/workspace/ADIOSPP/include/mpi/transport /home/wfg/workspace/ADIOSPP/include/nompi/transport # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the \mscfile @@ -2388,7 +2388,7 @@ DOT_GRAPH_MAX_NODES = 50 # Minimum value: 0, maximum value: 1000, default value: 0. # This tag requires that the tag HAVE_DOT is set to YES. -MAX_DOT_GRAPH_DEPTH = 0 +MAX_DOT_GRAPH_DEPTH = 3 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not seem diff --git a/examples/hello/helloADIOS_nompi.cpp b/examples/hello/helloADIOS_nompi.cpp index e617aeef3..e01949eaa 100644 --- a/examples/hello/helloADIOS_nompi.cpp +++ b/examples/hello/helloADIOS_nompi.cpp @@ -18,7 +18,7 @@ int main( int argc, char* argv [] ) { adios::ADIOS adiosFile( "writer2Groups.xml" ); //testing with CPOSIXNoMPI adiosFile.Init( ); - adiosFile.MonitorGroups( ); + adiosFile.MonitorGroups( std::cout ); std::cout << "Finished initializing ADIOS\n"; } catch( std::exception& e ) diff --git a/examples/hello/writer2Groups.xml b/examples/hello/writer2Groups.xml new file mode 100644 index 000000000..d019bdfdc --- /dev/null +++ b/examples/hello/writer2Groups.xml @@ -0,0 +1,72 @@ +<?xml version="1.0"?> +<adios-config host-language="Fortran"> + <adios-group name="writer2D"> + + <var name="nproc" path="/info" type="integer"/> + <attribute name="description" path="/info/nproc" value="Number of writers"/> + <var name="npx" path="/info" type="integer"/> + <attribute name="description" path="/info/npx" value="Number of processors in x dimension"/> + <var name="npy" path="/info" type="integer"/> + <attribute name="description" path="/info/npy" value="Number of processors in y dimension"/> + + <var name="gdx" type="integer"/> + <attribute name="description" path="/gdx" value="Global array size in x dimension"/> + <var name="gdy" type="integer"/> + <attribute name="description" path="/gdy" value="Global array size in y dimension"/> + + <!-- Auxiliary variables for global array indexing written (overwritten) by each process --> + <var name="ox" type="integer"/> + <var name="oy" type="integer"/> + <var name="ldx" type="integer"/> + <var name="ldy" type="integer"/> + + <!-- 2D array to write with block,block decomposition --> + <global-bounds dimensions="gdx,gdy" offsets="ox,oy"> + <var name="xy" type="double" dimensions="ldx,ldy"/> + </global-bounds> + <attribute name="description" path="/xy" + value="2D array with 2D decomposition"/> + + </adios-group> + + <!-- Use transport method + DATASPACES for staging data in memory coupling or + FLEXPATH for socket based staging between applications + MPI for file-based coupling + --> + <!--transport group="writer2D" method="MPI">verbose=2</transport--> + <!--transport group="writer2D" method="DATASPACES">verbose=3</transport--> + <transport group="writer2D" method="DIMES">verbose=3</transport> + <!--transport group="writer2D" method="FLEXPATH">QUEUE_SIZE=10;verbose=3</transport--> + <adios-group name="writer3D"> + + <var name="nproc" path="/info" type="integer"/> + <attribute name="description" path="/info/nproc" value="Number of writers"/> + <var name="npx" path="/info" type="integer"/> + <attribute name="description" path="/info/npx" value="Number of processors in x dimension"/> + <var name="npy" path="/info" type="integer"/> + <attribute name="description" path="/info/npy" value="Number of processors in y dimension"/> + + <var name="gdx" type="integer"/> + <attribute name="description" path="/gdx" value="Global array size in x dimension"/> + <var name="gdy" type="integer"/> + <attribute name="description" path="/gdy" value="Global array size in y dimension"/> + + <!-- Auxiliary variables for global array indexing written (overwritten) by each process --> + <var name="ox" type="integer"/> + <var name="oy" type="integer"/> + <var name="ldx" type="integer"/> + <var name="ldy" type="integer"/> + + <!-- 2D array to write with block,block decomposition --> + <global-bounds dimensions="gdx,gdy" offsets="ox,oy"> + <var name="xy" type="double" dimensions="ldx,ldy"/> + </global-bounds> + <attribute name="description" path="/xy" + value="2D array with 2D decomposition"/> + + </adios-group> + + <buffer size-MB="40" allocate-time="now"/> + +</adios-config> diff --git a/include/ADIOS.h b/include/ADIOS.h index be8e79247..825bb0dbe 100644 --- a/include/ADIOS.h +++ b/include/ADIOS.h @@ -10,6 +10,7 @@ #include <string> #include <memory> +#include <ostream> #ifdef HAVE_MPI #include <mpi.h> @@ -78,16 +79,21 @@ public: // PUBLIC Constructors and Functions define the User Interface with ADIO */ unsigned long int GroupSize( const std::string groupName ) const; - /** * Submits a data element values for writing and associates it with the given variableName + * @param groupName name of group that owns the variable * @param variableName name of existing scalar or vector variable in the XML file or created with CreateVariable * @param values pointer to the variable values passed from the user application, use dynamic_cast to check that pointer is of the same value type */ template<class T> void Write( const std::string groupName, const std::string variableName, const T* values ); - void MonitorGroups( ); + /** + * @brief Dumps groups information to a file stream or standard output. + * Note that either the user closes this fileStream or it's closed at the end. + * @param logStream either std::cout standard output, or a std::ofstream file + */ + void MonitorGroups( std::ostream& logStream ) const; void Close( ); // dumps to file? @@ -124,6 +130,12 @@ private: #ifdef HAVE_MPI void InitMPI( ); ///< called from Init, initialize parallel MPI #endif + + /** + * Checks for group existence in m_Groups + * @param groupName to be checked + */ + void CheckGroup( const std::string groupName ); }; diff --git a/include/ADIOSFunctions.h b/include/ADIOSFunctions.h index 8e20700a2..5b57869fa 100644 --- a/include/ADIOSFunctions.h +++ b/include/ADIOSFunctions.h @@ -12,6 +12,10 @@ #include <vector> #include <map> +#ifdef HAVE_MPI +#include <mpi.h> //Just for MPI_Comm argument in SetMembersMPI +#endif + #include "CGroup.h" @@ -72,6 +76,17 @@ void GetPairsFromTag( const std::string& fileContent, const std::string tag, void SetMembers( const std::string& fileContent, std::string& hostLanguage, std::map< std::string, CGroup >& groups ); +#ifdef HAVE_MPI +/** + * Set members m_Groups and m_HostLanguage from XML file content, called within Init functions + * @param fileContent file Content in a single string + * @param hostLanguage return the host language from fileContent + * @param groups passed returns the map of groups defined in fileContent + */ +void SetMembers( const std::string& fileContent, std::string& hostLanguage, std::map< std::string, CGroup >& groups, + const MPI_Comm mpiComm ); +#endif + } //end namespace diff --git a/include/CGroup.h b/include/CGroup.h index a38f98189..018a021df 100644 --- a/include/CGroup.h +++ b/include/CGroup.h @@ -12,6 +12,11 @@ #include <string> #include <memory> //for shared_pointer #include <vector> +#include <ostream> + +#ifdef HAVE_MPI +#include <mpi.h> //for MPI_Comm in overloaded SetTransform +#endif #include "CVariable.h" #include "SAttribute.h" @@ -37,6 +42,23 @@ public: ~CGroup( ); ///< Using STL containers + /** + * Opens group and passes fileName and accessMode to m_Transport + * @param fileName + * @param accessMode + */ + void Open( const std::string fileName, const std::string accessMode = "w" ); + + + /** + * Passes variableName and values to m_Transport + * @param variableName + * @param values + */ + template<class T> + void Write( const std::string variableName, const T* values ); + + /** * @brief Sets a variable in current Group, name must be unique * @param name @@ -46,7 +68,7 @@ public: * @param transform method, format = lib or lib:level, where lib = zlib, bzip2, szip, and level=1:9 . If no level is defined then library default is taken */ void SetVariable( const std::string name, const bool isGlobal, const std::string type, - const std::string dimensionsCSV = {1}, const std::string transform = "" ); + const std::string dimensionsCSV = "1", const std::string transform = "" ); /** * @brief Sets a variable in current Group @@ -66,16 +88,34 @@ public: */ void SetGlobalBounds( const std::string dimensionsCSV, const std::string offsetsCSV = "" ); + /** - * Set a transport method for this group - * @param transport supported values in SSupport.h TransportMethods + * @brief Set a transport method for this group, if existing it will replace current transport method + * @param method supported values in SSupport.h TransportMethods * @param priority numeric priority for the I/O to schedule this write with others that might be pending * @param iteration iterations between writes of a group to gauge how quickly this data should be evacuated from the compute node - * @param verbose level */ - void SetTransportMethod( const std::string transport, unsigned int priority = 1, unsigned int iteration=1, unsigned int verbose = 0 ); + void SetTransport( const std::string method, const unsigned int priority, const unsigned int iteration ); - void MonitorGroup( ); ///< Dumps information about Group variables + #ifdef HAVE_MPI + /** + * @brief MPI version of SetTransport, includes the communicator + * @param method supported values in SSupport.h TransportMethods + * @param priority numeric priority for the I/O to schedule this write with others that might be pending + * @param iteration iterations between writes of a group to gauge how quickly this data should be evacuated from the compute node + * @param mpiComm MPI communicator from User->ADIOS->Group + */ + void SetTransport( const std::string method, const unsigned int priority, const unsigned int iteration, + const MPI_Comm mpiComm ); + #endif + + + /** + * @brief Dumps groups information to a file stream or standard output. + * Note that either the user closes this fileStream or it's closed at the end. + * @param logStream either std::cout standard output, or a std::ofstream file + */ + void Monitor( std::ostream& logStream ) const; ///< Dumps information about Group variables private: @@ -93,9 +133,12 @@ private: std::vector< std::string > m_GlobalDimensions; ///< from global-bounds in XML File, data in global space std::vector< std::string > m_GlobalOffsets; ///< from global-bounds in XML File, data in global space - std::shared_ptr< CTransport > m_TransportMethod; ///< transport method defined in XML File, using shared pointer as SGroup can be uninitialized - std::string m_ActiveMethod; + std::shared_ptr< CTransport > m_Transport; ///< transport method defined in XML File, using shared pointer as SGroup can be uninitialized + std::string m_ActiveTransport; + bool m_IsOpen = false; ///< checks if group was opened for operations; + std::string m_FileName; ///< associated fileName is the Group is opened. + std::string m_AcessMode; ///< file access mode /** * Called from XML constructor @@ -103,6 +146,12 @@ private: * @param groupName returns the groupName from <adios-group name=" " */ void ParseXMLGroup( const std::string& xmlGroup, std::string& groupName ); + + /** + * Function that checks if transport method is valid, called from overloaded SetTransform functions + * @param method transport method to be checked from SSupport + */ + void CheckTransport( const std::string method ); }; diff --git a/include/CTransport.h b/include/CTransport.h index 7f3c31d60..63de67c57 100644 --- a/include/CTransport.h +++ b/include/CTransport.h @@ -25,6 +25,8 @@ public: const unsigned int m_Priority; const unsigned int m_Iteration; const bool m_IsUsingMPI; + std::string m_FileName; + std::string m_AccessMode; CTransport( const std::string method, const unsigned int priority, const unsigned int iteration, bool isUsingMPI ): @@ -37,7 +39,14 @@ public: virtual ~CTransport( ) { } - virtual void Write( CVariable& variable ) = 0; + + void Open( const std::string fileName, const std::string accessMode = "w" ) + { + m_FileName = fileName; + m_AccessMode = accessMode; + } + + virtual void Write( const CVariable& variable ) = 0; }; diff --git a/include/CVariable.h b/include/CVariable.h index a1960b17c..5344f3833 100644 --- a/include/CVariable.h +++ b/include/CVariable.h @@ -48,7 +48,7 @@ public: template<class T, class U> void Set(const U& rhs); -//protected: +//protected: turned off for testing bool m_IsGlobal = false; std::string m_Type = "NONE"; ///< mandatory, double, float, unsigned integer, integer, etc. std::vector<std::string> m_Dimensions = {"1"}; ///< if empty variable is a scalar, else N-dimensional variable @@ -67,6 +67,7 @@ public: /** * Template constructor class required for putting CVariable objects as value in a STL map container * @param isGlobal + * @param type * @param dimensionsCSV * @param transform */ @@ -77,8 +78,10 @@ public: ~CVariableTemplate( ) { } + T* m_Value; // pointer or no pointer? + const T& Get() const { return m_Value; } - T m_Value; + }; diff --git a/include/SSupport.h b/include/SSupport.h index 5d4c06831..e07d4399d 100644 --- a/include/SSupport.h +++ b/include/SSupport.h @@ -15,9 +15,10 @@ namespace adios { -const std::string Version{"2.00"}; +const std::string c_Version{"2.00"}; -const std::set<std::string> HostLanguages { + +const std::set<std::string> c_HostLanguages { "C", "C++", "Fortran", @@ -25,7 +26,7 @@ const std::set<std::string> HostLanguages { "Java" }; -const std::set<std::string> TransportMethods { +const std::set<std::string> c_Transports { "NULL", "POSIX", "MPI", @@ -39,14 +40,14 @@ const std::set<std::string> TransportMethods { "ICEE" }; -const std::set<std::string> Tranformations { +const std::set<std::string> c_Transformations { "none", "identity", "bzip2", "isobar" }; -const std::map<std::string, std::string> DataTypes { +const std::map<std::string, std::string> c_DataTypes { { "unsigned integer", "unsigned int" }, { "integer", "int" }, { "real" , "float" }, @@ -55,17 +56,7 @@ const std::map<std::string, std::string> DataTypes { }; - - - - - - - - - - -} +} //end namespace #endif /* SSUPPORT_H_ */ diff --git a/include/mpi/transport/CPOSIXMPI.h b/include/mpi/transport/CPOSIXMPI.h index 3b337e032..db2977e7a 100644 --- a/include/mpi/transport/CPOSIXMPI.h +++ b/include/mpi/transport/CPOSIXMPI.h @@ -29,7 +29,7 @@ public: ~CPOSIXMPI( ); - void Write( CVariable& variable ); + void Write( const CVariable& variable ); }; diff --git a/include/mpi/transport/CTransportMPI.h b/include/mpi/transport/CTransportMPI.h index d70aeeb2d..77633cd74 100644 --- a/include/mpi/transport/CTransportMPI.h +++ b/include/mpi/transport/CTransportMPI.h @@ -32,7 +32,7 @@ public: virtual ~CTransportMPI( ) { } - virtual void Write( CVariable& variable ) = 0; + virtual void Write( const CVariable& variable ) = 0; }; diff --git a/include/nompi/transport/CPOSIXNoMPI.h b/include/nompi/transport/CPOSIXNoMPI.h index e590b1419..4bd390f8f 100644 --- a/include/nompi/transport/CPOSIXNoMPI.h +++ b/include/nompi/transport/CPOSIXNoMPI.h @@ -27,7 +27,7 @@ public: ~CPOSIXNoMPI( ); - void Write( CVariable& variable ); + void Write( const CVariable& variable ); }; diff --git a/include/nompi/transport/CTransportNoMPI.h b/include/nompi/transport/CTransportNoMPI.h index f45caeb57..7e212bcdf 100644 --- a/include/nompi/transport/CTransportNoMPI.h +++ b/include/nompi/transport/CTransportNoMPI.h @@ -26,7 +26,7 @@ public: virtual ~CTransportNoMPI( ) { } - virtual void Write( CVariable& variable ) = 0; + virtual void Write( const CVariable& variable ) = 0; }; diff --git a/src/ADIOS.cpp b/src/ADIOS.cpp index 0bba0cdf6..a2b55deba 100644 --- a/src/ADIOS.cpp +++ b/src/ADIOS.cpp @@ -62,41 +62,69 @@ void ADIOS::InitNoMPI( ) std::string xmlFileContent; DumpFileToStream( m_XMLConfigFile, xmlFileContent ); //in ADIOSFunctions.h dumps all XML Config File to xmlFileContent SetMembers( xmlFileContent, m_HostLanguage, m_Groups ); - - //SetMembersFromXMLConfigFile( xmlFileContent, m_HostLanguage, m_Groups ); //in ADIOSFunctions.h sets m_HostLanguage and m_Groups - //std::cout << "Finishing Initialization"; } -#ifdef MPI_VERSION + +#ifdef HAVE_MPI void ADIOS::InitMPI( ) { - std::cout << "Just testing the InitMPI Function\n"; + int rank; + MPI_Comm_rank( m_MPIComm, &rank ); + + int xmlFileContentSize; // common + std::string xmlFileContent; + + if( rank == 0 ) + { + std::string xmlFileContent; + DumpFileToStream( m_XMLConfigFile, xmlFileContent ); //in ADIOSFunctions.h dumps all XML Config File to xmlFileContent + xmlFileContentSize = m_XMLConfigFile.size( ) + 1; // add one for the null character + + MPI_Bcast( &xmlFileContentSize, 1, MPI_INT, 0, m_MPIComm ); //broadcast size + MPI_Bcast( (char*)xmlFileContent.c_str(), xmlFileContentSize, MPI_CHAR, 0, m_MPIComm ); + + SetMembers( xmlFileContent, m_HostLanguage, m_Groups ); + } + else + { + MPI_Bcast( &xmlFileContentSize, 1, MPI_INT, 0, m_MPIComm ); //broadcast size + char* xmlFileContentMPI = new char[ xmlFileContentSize ]; //allocate C char + MPI_Bcast( xmlFileContentMPI, xmlFileContentSize, MPI_CHAR, 0, m_MPIComm ); //receive from rank=0 + + xmlFileContent.assign( xmlFileContentMPI ); + SetMembers( xmlFileContent, m_HostLanguage, m_Groups ); + } } #endif void ADIOS::Open( const std::string groupName, const std::string fileName, const std::string accessMode ) { - //retrieve a group name from m_Groups - std::cout << "Just testing the Open function\n"; + m_Groups.at( groupName ).Open( fileName, accessMode ); } template<class T> void ADIOS::Write( const std::string groupName, const std::string variableName, const T* values ) { - std::cout << "Just testing the Write function\n"; + m_Groups.at( groupName ).Write( variableName, values ); } -void ADIOS::MonitorGroups( ) +void ADIOS::MonitorGroups( std::ostream& logStream ) const { for( auto& groupPair : m_Groups ) { - std::cout << "Group:..." << groupPair.first << "\n"; - groupPair.second.MonitorGroup(); + logStream << "Group:..." << groupPair.first << "\n"; + groupPair.second.Monitor( logStream ); } } +void ADIOS::CheckGroup( const std::string groupName ) +{ + auto it = m_Groups.find( groupName ); + if( it == m_Groups.end() ) throw std::invalid_argument( "ERROR: group " + groupName + " not found\n" ); +} + } //end namespace diff --git a/src/ADIOSFunctions.cpp b/src/ADIOSFunctions.cpp index 73ca9ff20..e83428196 100644 --- a/src/ADIOSFunctions.cpp +++ b/src/ADIOSFunctions.cpp @@ -136,13 +136,14 @@ void SetMembers( const std::string& fileContent, std::string& hostLanguage, std: startComment = currentContent.find( "<!--" ); } + std::string tag; //use for < > tags + std::vector< std::pair<const std::string, const std::string> > pairs; // pairs in tag + //Tag <adios-config - std::string configTag; currentPosition = 0; - GetSubString( "<", ">", currentContent, configTag, currentPosition ); - configTag = configTag.substr( 1, configTag.size() - 2 ); //eliminate < > - std::vector< std::pair<const std::string, const std::string> > pairs; - GetPairsFromTag( currentContent, configTag, pairs ); + GetSubString( "<", ">", currentContent, tag, currentPosition ); + tag = tag.substr( 1, tag.size() - 2 ); //eliminate < > + GetPairsFromTag( currentContent, tag, pairs ); for( auto& pair : pairs ) { @@ -150,7 +151,7 @@ void SetMembers( const std::string& fileContent, std::string& hostLanguage, std: } //adios-group - std::string xmlGroup( "Used for groups" ); + std::string xmlGroup; while( currentPosition != std::string::npos ) { GetSubString("<adios-group ", "</adios-group>", currentContent, xmlGroup, currentPosition ); @@ -159,43 +160,147 @@ void SetMembers( const std::string& fileContent, std::string& hostLanguage, std: std::string groupName; CGroup group( xmlGroup, groupName ); groups[ groupName ] = group; //copy as it's a small object - } + currentContent.erase( currentContent.find( xmlGroup ), xmlGroup.size() ); + currentPosition = 0; + } + //transport + currentPosition = 0; + while( currentPosition != std::string::npos ) + { + GetSubString( "<transport ", ">", currentContent, tag, currentPosition ); + if( tag.empty() ) break; + tag = tag.substr( 1, tag.size() - 2 ); //eliminate < > + pairs.clear(); + GetPairsFromTag( currentContent, tag, pairs ); + + std::string groupName, method, priorityStr, iterationStr; + for( auto& pair : pairs ) + { + if( pair.first == "group" ) groupName = pair.second; + else if( pair.first == "method" ) method = pair.second; + else if( pair.first == "priority" ) priorityStr = pair.second; + else if( pair.first == "iteration" ) iterationStr = pair.second; + } + auto itGroup = groups.find( groupName ); + if( itGroup == groups.end() ) //not found + { + continue; + } - //transports tag -// std::map< std::string, std::map<std::string,std::string> > groupsTransport; -// std::string::size_type startTransport = currentContent.find("<transport "); -// -// while( startTransport != currentContent.npos ) -// { -// std::string::size_type endTransport( currentContent.find( "</transport>") ); -// std::string::size_type endTag( currentContent.find('>', startTransport ) ); -// -// const std::string transportTag( currentContent.substr( startTransport+1, endTag-startTransport-1 ) ); -// std::vector< std::pair<const std::string, const std::string> > transportPairs; -// std::cout << "Transport tag..." << transportTag << "...\n"; -// GetPairsFromTag( currentContent, transportTag, transportPairs ); -// -// for( auto& pair : pairs ) -// { -// if( pair.first == "group" ) -// { -// -// } -// } -// const std::string transportContents( currentContent.substr( startTransport, endTransport-startTransport) ); -// std::cout << "Transport contents..." << transportContents << "...\n"; -// -// currentContent.erase( startTransport, endTransport-startComment + 12 ); -// std::cout << "Current content..." << currentContent << "...\n"; -// -// startTransport = currentContent.find( "<transport " ); -// } + //lambda function to check priority and iteration + auto lf_UIntCheck = []( const std::string method, const std::string fieldStr, const std::string fieldName, int& field ) + { + field = 0; + if( fieldStr.empty() == false ) + { + field = std::stoi( fieldStr ); //throws invalid_argument + if( field < 0 ) throw std::invalid_argument("ERROR: " + fieldName + " in transport " + method + " can't be negative\n" ); + } + }; + + int priority, iteration; + lf_UIntCheck( method, priorityStr, "priority", priority ); + lf_UIntCheck( method, iterationStr, "iteration", iteration ); + + itGroup->second.SetTransport( method, (unsigned int)priority, (unsigned int)iteration ); + } } +#ifdef HAVE_MPI +void SetMembers( const std::string& fileContent, std::string& hostLanguage, std::map< std::string, CGroup >& groups, + const MPI_Comm mpiComm ) +{ + //adios-config + std::string currentContent; + std::string::size_type currentPosition( 0 ); + GetSubString( "<adios-config ", "</adios-config>", fileContent, currentContent, currentPosition ); + + //remove comment sections + std::string::size_type startComment ( currentContent.find( "<!--" ) ); + + while( startComment != currentContent.npos ) + { + std::string::size_type endComment( currentContent.find( "-->") ); + currentContent.erase( startComment, endComment-startComment+3 ); + startComment = currentContent.find( "<!--" ); + } + + std::string tag; //use for < > tags + std::vector< std::pair<const std::string, const std::string> > pairs; // pairs in tag + + //Tag <adios-config + currentPosition = 0; + GetSubString( "<", ">", currentContent, tag, currentPosition ); + tag = tag.substr( 1, tag.size() - 2 ); //eliminate < > + GetPairsFromTag( currentContent, tag, pairs ); + + for( auto& pair : pairs ) + { + if( pair.first == "host-language" ) hostLanguage = pair.second; + } + + //adios-group + std::string xmlGroup; + while( currentPosition != std::string::npos ) + { + GetSubString("<adios-group ", "</adios-group>", currentContent, xmlGroup, currentPosition ); + if( xmlGroup.empty() ) break; + + std::string groupName; + CGroup group( xmlGroup, groupName ); + groups[ groupName ] = group; //copy as it's a small object + + currentContent.erase( currentContent.find( xmlGroup ), xmlGroup.size() ); + currentPosition = 0; + } + //transport + currentPosition = 0; + while( currentPosition != std::string::npos ) + { + GetSubString( "<transport ", ">", currentContent, tag, currentPosition ); + if( tag.empty() ) break; + tag = tag.substr( 1, tag.size() - 2 ); //eliminate < > + pairs.clear(); + GetPairsFromTag( currentContent, tag, pairs ); + + std::string groupName, method, priorityStr, iterationStr; + for( auto& pair : pairs ) + { + if( pair.first == "group" ) groupName = pair.second; + else if( pair.first == "method" ) method = pair.second; + else if( pair.first == "priority" ) priorityStr = pair.second; + else if( pair.first == "iteration" ) iterationStr = pair.second; + } + + auto itGroup = groups.find( groupName ); + if( itGroup == groups.end() ) //not found + { + continue; + } + + //lambda function to check priority and iteration + auto lf_UIntCheck = []( const std::string method, const std::string fieldStr, const std::string fieldName, int& field ) + { + field = 0; + if( fieldStr.empty() == false ) + { + field = std::stoi( fieldStr ); //throws invalid_argument + if( field < 0 ) throw std::invalid_argument("ERROR: " + fieldName + " in transport " + method + " can't be negative\n" ); + } + }; + + int priority, iteration; + lf_UIntCheck( method, priorityStr, "priority", priority ); + lf_UIntCheck( method, iterationStr, "iteration", iteration ); + + itGroup->second.SetTransport( method, (unsigned int)priority, (unsigned int)iteration, mpiComm ); + } +} +#endif diff --git a/src/CGroup.cpp b/src/CGroup.cpp index 31c5871f2..dcb47db68 100644 --- a/src/CGroup.cpp +++ b/src/CGroup.cpp @@ -9,6 +9,14 @@ #include "CGroup.h" #include "ADIOSFunctions.h" +#include "SSupport.h" + +//MPI transport methods +#ifdef HAVE_MPI +#include "mpi/transport/CPOSIXMPI.h" +#endif + +#include "nompi/transport/CPOSIXNoMPI.h" namespace adios @@ -25,6 +33,12 @@ CGroup::CGroup( const std::string& xmlGroup, std::string& groupName ) CGroup::~CGroup( ) { } +void CGroup::Open( const std::string fileName, const std::string accessMode ) +{ + m_IsOpen = true; + m_Transport->Open( fileName, accessMode ); +} + void CGroup::SetVariable( const std::string name, const bool isGlobal, const std::string type, const std::string dimensionsCSV, const std::string transform ) @@ -73,17 +87,36 @@ void CGroup::SetGlobalBounds( const std::string dimensionsCSV, const std::string } } -void CGroup::MonitorGroup( ) +void CGroup::SetTransport( const std::string method, const unsigned int priority, const unsigned int iteration ) +{ + CheckTransport( method ); + if( m_ActiveTransport == "POSIX" ) m_Transport = std::make_shared<CPOSIXNoMPI>( method, priority, iteration ); +} + +#ifdef HAVE_MPI +void CGroup::SetTransport( const std::string method, const unsigned int priority, const unsigned int iteration, + const MPI_Comm mpiComm ) +{ + CheckTransport( method ); + if( m_ActiveTransport == "POSIX" ) m_Transport = std::make_shared<CPOSIXMPI>( method, priority, iteration, mpiComm ); +} +#endif + + +//PRIVATE FUNCTIONS BELOW + +void CGroup::Monitor( std::ostream& logStream ) const { for( auto& variablePair : m_Variables ) { - std::cout << "VarName:..." << variablePair.first << " Type:..." << variablePair.second->m_Type << "\n"; + logStream << "VarName:..." << variablePair.first << " Type:..." << variablePair.second->m_Type << "\n"; } - std::cout << "Transport Method Unique?: " << m_TransportMethod.unique() << "\n"; - + logStream << "Transport Method " << m_ActiveTransport << "\n"; + logStream << std::ostream::boolalpha << "Transport Method Unique?: " << m_Transport.unique() << "\n"; } + void CGroup::ParseXMLGroup( const std::string& xmlGroup, std::string& groupName ) { //get name @@ -153,6 +186,16 @@ void CGroup::ParseXMLGroup( const std::string& xmlGroup, std::string& groupName } +void CGroup::CheckTransport( const std::string method ) +{ + if( c_Transports.count( method ) == 0 ) + throw std::invalid_argument( "ERROR: transport method " + method + " not supported. Check spelling or case sensitivity.\n" ); + + if( m_ActiveTransport.empty() == false ) //there is an existing transport method + m_Transport.reset(); + + m_ActiveTransport = method; +} } //end namespace diff --git a/src/mpi/transport/CPOSIXMPI.cpp b/src/mpi/transport/CPOSIXMPI.cpp index 1d697f694..3670c4620 100644 --- a/src/mpi/transport/CPOSIXMPI.cpp +++ b/src/mpi/transport/CPOSIXMPI.cpp @@ -25,7 +25,7 @@ CPOSIXMPI::~CPOSIXMPI( ) { } -void CPOSIXMPI::Write( CVariable& variable ) +void CPOSIXMPI::Write( const CVariable& variable ) { int rank; MPI_Comm_rank( m_MPIComm, &rank ); diff --git a/src/nompi/transport/CPOSIXNoMPI.cpp b/src/nompi/transport/CPOSIXNoMPI.cpp index 3bc5ed640..623e7d836 100644 --- a/src/nompi/transport/CPOSIXNoMPI.cpp +++ b/src/nompi/transport/CPOSIXNoMPI.cpp @@ -24,7 +24,7 @@ CPOSIXNoMPI::~CPOSIXNoMPI( ) { } -void Write( CVariable& variable ) +void CPOSIXNoMPI::Write( const CVariable& variable ) { std::cout << "Just saying Hello from CPOSIXNoMPI Write\n"; } -- GitLab