diff --git a/Makefile b/Makefile index 0581afa17e57133858bfc748cb81c681fb987621..ea705d1d4e18a4eb215cd4dcc5b7fe35e7ccba2d 100644 --- a/Makefile +++ b/Makefile @@ -4,12 +4,24 @@ #DEFAULT COMPILERS IN PATH, LIBS will be modified in Makefile.libs CC:=g++ -AR:=ar MPICC:=mpic++ LIBS:= +SHARED:=no CFLAGS:=-c -Wall -Wpedantic -std=c++11 -O0 -g -ARFLAGS:=rcs +LINKERMPI:=ar +LINKERNoMPI:=ar +LINKERFLAGS:= rcs +LIBEXT:=a + +ifeq ($(SHARED),yes) + CFLAGS+= -fPIC + LINKERMPI=$(MPICC) + LINKERNoMPI=$(CC) + LINKERFLAGS= -shared -o + LIBEXT=so +endif + #ADIOS HFiles:=$(shell find ./include -type f -name "*.h") @@ -38,23 +50,23 @@ all: mpi nompi mpi: $(HFiles) $(OBJMPI) @( mkdir -p ./lib ); - $(AR) $(ARFLAGS) ./lib/libadios.a $(OBJMPI) - @echo "Finished building MPI library lib/libadios.a"; + $(LINKERMPI) $(LINKERFLAGS) ./lib/libadios.$(LIBEXT) $(OBJMPI) + @echo "Finished building MPI library ./lib/libadios.$(LIBEXT)"; @echo ./bin/mpi/%.o: %.cpp $(HFiles) @( mkdir -p ./bin/mpi ); - $(MPICC) $(CFLAGS) -DHAVE_MPI $(INC) -o $@ $< + $(MPICC) $(CFLAGS) $(INC) -o $@ $< nompi: $(HFiles) $(OBJNoMPI) @( mkdir -p ./lib ); - $(AR) $(ARFLAGS) ./lib/libadios_nompi.a $(OBJNoMPI) - @echo "Finished building noMPI library lib/libadios_nompi.a"; + $(LINKERNoMPI) $(LINKERFLAGS) ./lib/libadios_nompi.$(LIBEXT) $(OBJNoMPI) + @echo "Finished building noMPI library ./lib/libadios.$(LIBEXT)"; @echo ./bin/nompi/%.o: %.cpp $(HFiles) @( mkdir -p ./bin/nompi ); - $(CC) $(CFLAGS) $(INC) -o $@ $< + $(CC) $(CFLAGS) $(INC) -DADIOS_NOMPI -o $@ $< clean: - rm ./bin/mpi/*.o ./lib/libadios.a ./bin/nompi/*.o ./lib/libadios_nompi.a + rm ./bin/mpi/*.o ./bin/nompi/*.o ./lib/* diff --git a/include/ADIOS.h b/include/ADIOS.h index 3671e22bda8ce87e6988f6a56f7a6cabdf23bf09..e6d51dcc91f4d69a72d091373a343ab06b349c7b 100644 --- a/include/ADIOS.h +++ b/include/ADIOS.h @@ -18,10 +18,10 @@ #include <complex> /// \endcond -#ifdef HAVE_MPI - #include <mpi.h> -#else +#ifdef ADIOS_NOMPI #include "mpidummy.h" +#else + #include <mpi.h> #endif #include "core/Transform.h" @@ -58,6 +58,14 @@ class ADIOS public: // PUBLIC Constructors and Functions define the User Interface with ADIOS + + MPI_Comm m_MPIComm = MPI_COMM_SELF; ///< only used as reference to MPI communicator passed from parallel constructor, MPI_Comm is a pointer itself. Public as called from C + + int m_RankMPI = 0; ///< current MPI rank process + int m_SizeMPI = 1; ///< current MPI processes size + + std::string m_HostLanguage = "C++"; + /** * @brief ADIOS empty constructor. Used for non XML config file API calls. */ @@ -91,6 +99,7 @@ public: // PUBLIC Constructors and Functions define the User Interface with ADIO ~ADIOS( ); ///< empty, using STL containers for memory management + void InitMPI( ); ///< sets rank and size in m_rank and m_Size, respectively. /** * Look for template specialization @@ -121,9 +130,10 @@ public: // PUBLIC Constructors and Functions define the User Interface with ADIO const Dims globalOffsets = Dims() ) { CheckVariableInput( name, dimensions ); - m_Compound.emplace_back( name, sizeof(T), dimensions, globalDimensions, globalOffsets, m_DebugMode ); - m_Variables.emplace( name, std::make_pair( GetType<T>(), m_Compound.size()-1 ) ); - return m_Compound.back(); + const unsigned int size = m_Compound.size(); + m_Compound.emplace( size, VariableCompound( name, sizeof(T), dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<T>(), size ) ); + return m_Compound.at( size ); } VariableCompound& GetVariableCompound( const std::string name ); @@ -148,51 +158,51 @@ public: // PUBLIC Constructors and Functions define the User Interface with ADIO * @param mpiComm option to modify communicator from ADIOS class constructor * @param method looks for corresponding Method object in ADIOS to initialize the engine * @param iomode Independent or collective open/advance by writers/readers? Write() operations are always independent. - * @return Derived class of base Engine depending on Method parameters, shared_ptr for potential flexibility + * @param timeout_sec Wait some time before reporting on missing stream (i.e. wait for it for a while) + * @return Derived class of base Engine depending on Method parameters, shared_ptr for potential flexibility */ std::shared_ptr<Engine> Open( const std::string streamName, const std::string accessMode, MPI_Comm mpiComm, - const Method& method, const IOMode iomode ); + const Method& method, const IOMode iomode, const float timeout_sec = 0.0 ); /** - * @brief Open to Read with a timeout value specified. Creates a new engine from previously defined method + * @brief Open to Write, Read. Creates a new engine from previously defined method. + * Reuses MPI communicator from ADIOS constructor. * @param streamName unique stream or file name * @param accessMode "w" or "write", "r" or "read", "a" or "append", "u" or "update" - * @param mpiComm option to modify communicator from ADIOS class constructor - * @param method looks for corresponding Method object in ADIOS to initialize the engine + * @param method contains engine parameters * @param iomode Independent or collective open/advance by writers/readers? Write() operations are always independent. * @param timeout_sec Wait some time before reporting on missing stream (i.e. wait for it for a while) - * @return Derived class of base Engine depending on Method parameters, shared_ptr for potential flexibility + * @return Derived class of base Engine depending on Method parameters, shared_ptr for potential flexibility */ - std::shared_ptr<Engine> Open( const std::string streamName, const std::string accessMode, MPI_Comm mpiComm, - const Method& method, const IOMode iomode, - const float timeout_sec ); + std::shared_ptr<Engine> Open( const std::string streamName, const std::string accessMode, + const Method& method, const IOMode iomode, const float timeout_sec = 0.0 ); + + /** - * @brief Open to Write, Read. Creates a new engine from previously defined method. - * Reuses MPI communicator from ADIOS constructor. + * Version required by the XML config file implementation, searches method inside ADIOS through a unique name * @param streamName unique stream or file name - * @param accessMode "w" or "write", "r" or "read", "a" or "append", "u" or "update" - * @param method contains engine parameters + * @param accessMode "w" or "write", "r" or "read", "a" or "append" + * @param mpiComm mpi Communicator + * @param methodName used to search method object inside ADIOS object * @param iomode Independent or collective open/advance by writers/readers? Write() operations are always independent. + * @param timeout_sec Wait some time before reporting on missing stream (i.e. wait for it for a while) * @return Derived class of base Engine depending on Method parameters, shared_ptr for potential flexibility */ - std::shared_ptr<Engine> Open( const std::string streamName, const std::string accessMode, const Method& method, - const IOMode iomode ); - + std::shared_ptr<Engine> Open( const std::string streamName, const std::string accessMode, MPI_Comm mpiComm, + const std::string methodName, const IOMode iomode, const float timeout_sec = 0.0 ); /** - * @brief Open to Read with a timeout value specified. Creates a new engine from previously defined method - * Reuses MPI communicator from ADIOS constructor. + * Version required by the XML config file implementation, searches method inside ADIOS through a unique name. + * Reuses ADIOS MPI Communicator from constructor. * @param streamName unique stream or file name - * @param accessMode "w" or "write", "r" or "read", "a" or "append", "u" or "update" - * @param method looks for corresponding Method object in ADIOS to initialize the engine + * @param accessMode "w" or "write", "r" or "read", "a" or "append" + * @param methodName used to search method object inside ADIOS object * @param iomode Independent or collective open/advance by writers/readers? Write() operations are always independent. * @param timeout_sec Wait some time before reporting on missing stream (i.e. wait for it for a while) * @return Derived class of base Engine depending on Method parameters, shared_ptr for potential flexibility */ - std::shared_ptr<Engine> Open( const std::string streamName, const std::string accessMode, const Method& method, - const IOMode iomode, - const float timeout_sec ); - + std::shared_ptr<Engine> Open( const std::string streamName, const std::string accessMode, + const std::string methodName, const IOMode iomode, const float timeout_sec = 0.0 ); /** * @brief Open to Read all steps from a file. No streaming, advancing is possible here. All steps in the file @@ -215,7 +225,338 @@ public: // PUBLIC Constructors and Functions define the User Interface with ADIO -private: //no const to allow default empty and copy constructors +protected: //no const to allow default empty and copy constructors + + std::map<unsigned int, Variable<char> > m_Char; + std::map<unsigned int, Variable<unsigned char> > m_UChar; + std::map<unsigned int, Variable<short> > m_Short; + std::map<unsigned int, Variable<unsigned short> > m_UShort; + std::map<unsigned int, Variable<int> > m_Int; + std::map<unsigned int, Variable<unsigned int> > m_UInt; + std::map<unsigned int, Variable<long int> > m_LInt; + std::map<unsigned int, Variable<unsigned long int> > m_ULInt; + std::map<unsigned int, Variable<long long int> > m_LLInt; + std::map<unsigned int, Variable<unsigned long long int> > m_ULLInt; + std::map<unsigned int, Variable<float> > m_Float; + std::map<unsigned int, Variable<double> > m_Double; + std::map<unsigned int, Variable<long double> > m_LDouble; + std::map<unsigned int, Variable<std::complex<float>> > m_CFloat; + std::map<unsigned int, Variable<std::complex<double>> > m_CDouble; + std::map<unsigned int, Variable<std::complex<long double>> > m_CLDouble; + std::map<unsigned int, VariableCompound > m_Compound; + + std::string m_ConfigFile; ///< XML File to be read containing configuration information + bool m_DebugMode = false; ///< if true will do more checks, exceptions, warnings, expect slower code + + //Variables + std::map< std::string, std::pair< std::string, unsigned int > > m_Variables; ///< Makes variable name unique, key: variable name, value: pair.first = type, pair.second = index in corresponding vector of Variable + + std::vector< std::shared_ptr<Transform> > m_Transforms; ///< transforms associated with ADIOS run + + + /** + * @brief List of Methods (engine metadata) defined from either ADIOS XML configuration file or the DeclareMethod function. + * <pre> + * Key: std::string unique method name + * Value: Method class + * </pre> + */ + std::map< std::string, Method > m_Methods; + std::set< std::string > m_EngineNames; ///< set used to check Engine name uniqueness in debug mode + + /** + * @brief Checks for group existence in m_Groups, if failed throws std::invalid_argument exception + * @param itGroup m_Groups iterator, usually from find function + * @param groupName unique name, passed for thrown exception only + * @param hint adds information to thrown exception + */ + void CheckVariableInput( const std::string name, const Dims& dimensions ) const; + + /** + * Checks for variable name, if not found throws an invalid exception + * @param itVariable iterator pointing to the variable name in m_Variables + * @param name variable name + * @param hint message to be thrown for debugging purporses + */ + void CheckVariableName( std::map< std::string, std::pair< std::string, unsigned int > >::const_iterator itVariable, + const std::string name, const std::string hint ) const; + + /** + * @brief Checks for method existence in m_Methods, if failed throws std::invalid_argument exception + * @param itMethod m_Methods iterator, usually from find function + * @param methodName unique name, passed for thrown exception only + * @param hint adds information to thrown exception + */ + void CheckMethod( std::map< std::string, Method >::const_iterator itMethod, + const std::string methodName, const std::string hint ) const; + + template< class T > + unsigned int GetVariableIndex( const std::string name ) + { + auto itVariable = m_Variables.find( name ); + CheckVariableName( itVariable, name, "in call to GetVariable<" + GetType<T>() + ">, or call to GetVariableCompound if <T> = <compound>\n" ); + return itVariable->second.second; + } + +}; + +//template specializations of DefineVariable: +template<> inline +Variable<char>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_Char.size(); + m_Char.emplace( size, Variable<char>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<char>(), size ) ); + return m_Char.at( size ); +} + + +template<> inline +Variable<unsigned char>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_UChar.size(); + m_UChar.emplace( size, Variable<unsigned char>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<unsigned char>(), size ) ); + return m_UChar.at( size ); +} + + +template<> inline +Variable<short>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_Short.size(); + m_Short.emplace( size, Variable<short>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<unsigned char>(), size ) ); + return m_Short.at( size ); +} + + +template<> inline +Variable<unsigned short>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_UShort.size(); + m_UShort.emplace( size, Variable<unsigned short>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<unsigned short>(), size ) ); + return m_UShort.at( size ); +} + + +template<> inline +Variable<int>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_Int.size(); + m_Int.emplace( size, Variable<int>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<int>(), size ) ); + return m_Int.at( size ); +} + + +template<> inline +Variable<unsigned int>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_UInt.size(); + m_UInt.emplace( size, Variable<unsigned int>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<unsigned int>(), size ) ); + return m_UInt.at( size ); +} + + +template<> inline +Variable<long int>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_LInt.size(); + m_LInt.emplace( size, Variable<long int>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<long int>(), size ) ); + return m_LInt.at( size ); +} + + +template<> inline +Variable<unsigned long int>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_LInt.size(); + m_ULInt.emplace( size, Variable<unsigned long int>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<unsigned long int>(), size ) ); + return m_ULInt.at( size ); +} + + +template<> inline +Variable<long long int>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_LLInt.size(); + m_LLInt.emplace( size, Variable<long long int>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<long long int>(), size ) ); + return m_LLInt.at( size ); +} + + +template<> inline +Variable<unsigned long long int>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_ULLInt.size(); + m_ULLInt.emplace( size, Variable<unsigned long long int>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<unsigned long long int>(), size ) ); + return m_ULLInt.at( size ); +} + +template<> inline +Variable<float>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_Float.size(); + m_Float.emplace( size, Variable<float>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<float>(), size ) ); + return m_Float.at( size ); +} + + +template<> inline +Variable<double>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_Double.size(); + m_Double.emplace( size, Variable<double>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<double>(), size ) ); + return m_Double.at( size ); +} + + +template<> inline +Variable<long double>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_LDouble.size(); + m_LDouble.emplace( size, Variable<long double>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<long double>(), size ) ); + return m_LDouble.at( size ); +} + + +template<> inline +Variable<std::complex<float>>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_CFloat.size(); + m_CFloat.emplace( size, Variable<std::complex<float>>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<std::complex<float>>(), size ) ); + return m_CFloat.at( size ); +} + + +template<> inline +Variable<std::complex<double>>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_CDouble.size(); + m_CDouble.emplace( size, Variable<std::complex<double>>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<std::complex<double>>(), size ) ); + return m_CDouble.at( size ); +} + + +template<> inline +Variable<std::complex<long double>>& ADIOS::DefineVariable( const std::string name, const Dims dimensions, + const Dims globalDimensions, const Dims globalOffsets ) +{ + CheckVariableInput( name, dimensions ); + const unsigned int size = m_CLDouble.size(); + m_CLDouble.emplace( size, Variable<std::complex<long double>>( name, dimensions, globalDimensions, globalOffsets, m_DebugMode ) ); + m_Variables.emplace( name, std::make_pair( GetType<std::complex<long double>>(), size ) ); + return m_CLDouble.at( size ); +} + + +//Get template specialization +template<> inline +Variable<char>& ADIOS::GetVariable( const std::string name ) +{ return m_Char.at( GetVariableIndex<char>(name) ); } + +template<> inline +Variable<unsigned char>& ADIOS::GetVariable( const std::string name ) +{ return m_UChar.at( GetVariableIndex<unsigned char>(name) ); } + +template<> inline +Variable<short>& ADIOS::GetVariable( const std::string name ) +{ return m_Short.at( GetVariableIndex<short>(name) ); } + +template<> inline +Variable<unsigned short>& ADIOS::GetVariable( const std::string name ) +{ return m_UShort.at( GetVariableIndex<unsigned short>(name) ); } + +template<> inline +Variable<int>& ADIOS::GetVariable( const std::string name ) +{ return m_Int.at( GetVariableIndex<int>(name) ); } + +template<> inline +Variable<unsigned int>& ADIOS::GetVariable( const std::string name ) +{ return m_UInt.at( GetVariableIndex<unsigned int>(name) ); } + +template<> inline +Variable<long int>& ADIOS::GetVariable( const std::string name ) +{ return m_LInt.at( GetVariableIndex<unsigned int>(name) ); } + +template<> inline +Variable<unsigned long int>& ADIOS::GetVariable( const std::string name ) +{ return m_ULInt.at( GetVariableIndex<unsigned long int>(name) ); } + +template<> inline +Variable<long long int>& ADIOS::GetVariable( const std::string name ) +{ return m_LLInt.at( GetVariableIndex<long long int>(name) ); } + +template<> inline +Variable<unsigned long long int>& ADIOS::GetVariable( const std::string name ) +{ return m_ULLInt.at( GetVariableIndex<unsigned long long int>(name) ); } + +template<> inline +Variable<float>& ADIOS::GetVariable( const std::string name ) +{ return m_Float.at( GetVariableIndex<float>(name) ); } + +template<> inline +Variable<double>& ADIOS::GetVariable( const std::string name ) +{ return m_Double.at( GetVariableIndex<double>(name) ); } + +template<> inline +Variable<long double>& ADIOS::GetVariable( const std::string name ) +{ return m_LDouble.at( GetVariableIndex<long double>(name) ); } + +template<> inline +Variable<std::complex<float>>& ADIOS::GetVariable( const std::string name ) +{ return m_CFloat.at( GetVariableIndex<std::complex<float>>(name) ); } + +template<> inline +Variable<std::complex<double>>& ADIOS::GetVariable( const std::string name ) +{ return m_CDouble.at( GetVariableIndex<std::complex<double>>(name) ); } + +template<> inline +Variable<std::complex<long double>>& ADIOS::GetVariable( const std::string name ) +{ return m_CLDouble.at( GetVariableIndex<std::complex<long double>>(name) ); } + }; diff --git a/include/core/Capsule.h b/include/core/Capsule.h index e7b54b5558b021883bce7a89f7be03d840a9849a..c04680b028f0ce2789f478495f0a09f4ffbd90da 100644 --- a/include/core/Capsule.h +++ b/include/core/Capsule.h @@ -39,6 +39,7 @@ public: * @param type derived class type * @param accessMode 'w':write, 'r':read, 'a':append * @param rankMPI current MPI rank + * @param debugMode */ Capsule( const std::string type, const std::string accessMode, const int rankMPI, const bool debugMode ); diff --git a/include/core/Engine.h b/include/core/Engine.h index 90c20a019bde84c4080e8696b39eb4da3dc1223e..55dd7aa176cd9ab6258f2f7aed543f9350308be8 100644 --- a/include/core/Engine.h +++ b/include/core/Engine.h @@ -1,5 +1,5 @@ /* - * Capsule.h + * Engine.h * * Created on: Nov 7, 2016 * Author: wfg @@ -18,10 +18,10 @@ #include <complex> //std::complex /// \endcond -#ifdef HAVE_MPI - #include <mpi.h> -#else +#ifdef ADIOS_NOMPI #include "mpidummy.h" +#else + #include <mpi.h> #endif #include "ADIOS.h" @@ -31,7 +31,7 @@ #include "core/Transform.h" #include "core/Transport.h" #include "core/Capsule.h" - +#include "core/Profiler.h" namespace adios { @@ -52,6 +52,19 @@ class Engine public: + + MPI_Comm m_MPIComm = MPI_COMM_SELF; + + const std::string m_EngineType; ///< from derived class + const std::string m_Name; ///< name used for this engine + const std::string m_AccessMode; ///< accessMode for buffers used by this engine + const Method& m_Method; ///< associated method containing engine metadata + + int m_RankMPI = 0; ///< current MPI rank process + int m_SizeMPI = 1; ///< current MPI processes size + + const std::string m_HostLanguage = "C++"; ///< default host language + /** * Unique constructor * @param adios @@ -89,11 +102,11 @@ public: throw std::invalid_argument( "ERROR: type not supported for variable " + var->name + " in call to GetVariable\n" ); } - /* + /** * Needed for DataMan Engine - * @param callback + * @param callback function passed from the user */ - //virtual void SetCallBack( std::function<void( const void*, std::string, std::string, std::string, Dims )> callback ); + virtual void SetCallBack( std::function<void( const void*, std::string, std::string, std::string, Dims )> callback ); /** * Write function that adds static checking on the variable to be passed by values @@ -125,20 +138,22 @@ public: * @param values */ template< class T > - void Write( Variable<T>& variable, const T& values ) + void Write( Variable<T>& variable, const T values ) { - Write( variable, &values ); + const T val = values; + Write( variable, &val ); } /** - * Single value version using string as variable handlers + * Single value version using string as variable handlers, allows rvalues to be passed * @param variableName * @param values */ template< class T > - void Write( const std::string variableName, const T& values ) + void Write( const std::string variableName, const T values ) { - Write( variableName, &values ); + const T val = values; + Write( variableName, &val ); } virtual void Write( Variable<char>& variable, const char* values ); @@ -316,7 +331,6 @@ public: */ void PerformReads( PerformReadMode mode ); - /** * Reader application indicates that no more data will be read from the current stream before advancing. * This is necessary to allow writers to advance as soon as possible. @@ -381,6 +395,41 @@ public: virtual void Close( const int transportIndex = -1 ) = 0; ///< Closes a particular transport, or all if -1 + +protected: + + ADIOS& m_ADIOS; ///< reference to ADIOS object that creates this Engine at Open + std::vector< std::shared_ptr<Transport> > m_Transports; ///< transports managed + const bool m_DebugMode = false; ///< true: additional checks, false: by-pass checks + unsigned int m_Cores = 1; + const std::string m_EndMessage; ///< added to exceptions to improve debugging + std::set<std::string> m_WrittenVariables; ///< contains the names of the variables that are being written + + virtual void Init( ); ///< Initialize m_Capsules and m_Transports, called from constructor + virtual void InitParameters( ); ///< Initialize parameters from Method, called from Initi in constructor + virtual void InitTransports( ); ///< Initialize transports from Method, called from Init in constructor + + /** + * Used to verify parameters in m_Method containers + * @param itParam iterator to a certain parameter + * @param parameters map of parameters, from m_Method + * @param parameterName used if exception is thrown to provide debugging information + * @param hint used if exception is thrown to provide debugging information + */ + void CheckParameter( const std::map<std::string, std::string>::const_iterator itParam, + const std::map<std::string, std::string>& parameters, + const std::string parameterName, + const std::string hint ) const; + + bool TransportNamesUniqueness( ) const; ///< checks if transport names are unique among the same types (file I/O) + + + /** + * Throws an exception in debug mode if transport index is out of range. + * @param transportIndex must be in the range [ -1 , m_Transports.size()-1 ] + */ + void CheckTransportIndex( const int transportIndex ); + }; diff --git a/include/core/Transport.h b/include/core/Transport.h index cb4d3ea08cc26bf5513a0c8932f160277f53e7a4..1c2c0d0bacec7fb76e4584ab5774723b0c0da8fd 100644 --- a/include/core/Transport.h +++ b/include/core/Transport.h @@ -13,12 +13,13 @@ #include <vector> /// \endcond -#ifdef HAVE_MPI - #include <mpi.h> +#ifdef ADIOS_NOMPI + #include "mpidummy.h" #else - #include "mpidummy.h" + #include <mpi.h> #endif +#include "core/Profiler.h" namespace adios @@ -34,14 +35,11 @@ public: std::string m_AccessMode; ///< from Open bool m_IsOpen = false; - #ifdef HAVE_MPI - MPI_Comm m_MPIComm = NULL; ///< only used as reference to MPI communicator passed from parallel constructor, MPI_Comm is a pointer itself. Public as called from C - #else - MPI_Comm m_MPIComm = 0; ///< only used as reference to MPI communicator passed from parallel constructor, MPI_Comm is a pointer itself. Public as called from C - #endif + MPI_Comm m_MPIComm = MPI_COMM_SELF; int m_RankMPI = 0; ///< current MPI rank process int m_SizeMPI = 1; ///< current MPI processes size + Profiler m_Profiler; ///< collects information about Open and bytes Transport /** * Base constructor that all derived classes pass @@ -80,10 +78,11 @@ public: virtual void Close( ); ///< closes current transport and flushes everything, transport becomes unreachable + virtual void InitProfiler( const std::string accessMode, const Support::Resolutions resolution ); + protected: const bool m_DebugMode = false; ///< if true: additional checks and exceptions - }; diff --git a/include/core/Variable.h b/include/core/Variable.h index 81f552ac4c306946ff8dcc65501c1bbc609f60df..ec8c636df6507073bf214f61037af98536a4d020 100644 --- a/include/core/Variable.h +++ b/include/core/Variable.h @@ -40,7 +40,7 @@ class Variable : public VariableBase public: const T* m_AppValues = nullptr; ///< pointer to values passed from user in ADIOS Write, it might change in ADIOS Read - //std::vector<T> m_Values; ///< Vector variable returned to user, might be used for zero-copy? + std::vector< TransformData > m_Transforms; ///< associated transforms, sequence determines application order, e.g. first Transforms[0] then Transforms[1]. Pointer used as reference (no memory management). Variable<T>( const std::string name, const Dims dimensions, const Dims globalDimensions, const Dims globalOffsets, @@ -67,6 +67,40 @@ public: * @return Number of steps */ int GetSteps(); + + void Monitor( std::ostream& logInfo ) const noexcept + { + logInfo << "Variable: " << m_Name << "\n"; + logInfo << "Type: " << m_Type << "\n"; + logInfo << "Size: " << TotalSize() << " elements\n"; + logInfo << "Payload: " << PayLoadSize() << " bytes\n"; + + if( m_AppValues != nullptr ) + { + logInfo << "Values (first 10 or max_size): \n"; + std::size_t size = TotalSize(); + if( size > 10 ) + size = 10; + + if( m_Type.find("complex") != m_Type.npos ) //it's complex + { + for( unsigned int i = 0; i < size; ++i ) + { + logInfo << "( " << std::real( m_AppValues[i] ) << " , " << std::imag( m_AppValues[i] ) << " ) "; + } + } + else + { + for( unsigned int i = 0; i < size; ++i ) + { + logInfo << m_AppValues[i] << " "; + } + } + + logInfo << " ..."; + } + logInfo << "\n"; + } }; diff --git a/src/ADIOS.cpp b/src/ADIOS.cpp index 0b05d9de871d9d53977bca51006874b2ab2c658f..0d4eefce363ebd94c2edb9b7b0fbba9061e421ea 100644 --- a/src/ADIOS.cpp +++ b/src/ADIOS.cpp @@ -13,13 +13,11 @@ /// \endcond #include "ADIOS.h" - - #include "functions/adiosFunctions.h" //Engines -#include "engine/bp/BPWriter.h" -#include "engine/bp/BPReader.h" +#include "engine/bp/BPFileWriter.h" +#include "engine/bp/BPFileReader.h" #ifdef HAVE_DATAMAN //external dependencies #include "engine/dataman/DataManWriter.h" @@ -46,7 +44,8 @@ ADIOS::ADIOS( const std::string configFileName, const bool debugMode ): } -ADIOS::ADIOS( const std::string xmlConfigFile, const MPI_Comm mpiComm, const bool debugMode ): + +ADIOS::ADIOS( const std::string xmlConfigFile, MPI_Comm mpiComm, const bool debugMode ): m_MPIComm{ mpiComm }, m_ConfigFile{ xmlConfigFile }, m_DebugMode{ debugMode } @@ -56,7 +55,7 @@ ADIOS::ADIOS( const std::string xmlConfigFile, const MPI_Comm mpiComm, const boo } -ADIOS::ADIOS( const MPI_Comm mpiComm, const bool debugMode ): +ADIOS::ADIOS( MPI_Comm mpiComm, const bool debugMode ): m_MPIComm{ mpiComm }, m_DebugMode{ debugMode } { @@ -70,6 +69,13 @@ ADIOS::~ADIOS( ) void ADIOS::InitMPI( ) { + if( m_DebugMode == true ) + { + if( m_MPIComm == MPI_COMM_NULL ) + throw std::ios_base::failure( "ERROR: engine communicator is MPI_COMM_NULL," + " in call to ADIOS Open or Constructor\n" ); + } + MPI_Comm_rank( m_MPIComm, &m_RankMPI ); MPI_Comm_size( m_MPIComm, &m_SizeMPI ); } @@ -87,7 +93,8 @@ Method& ADIOS::DeclareMethod( const std::string methodName, const std::string ty } -std::shared_ptr<Engine> ADIOS::Open( const std::string name, const std::string accessMode, MPI_Comm mpiComm, const Method& method, const unsigned int cores ) +std::shared_ptr<Engine> ADIOS::Open( const std::string name, const std::string accessMode, MPI_Comm mpiComm, + const Method& method, const unsigned int cores ) { if( m_DebugMode == true ) { @@ -99,16 +106,18 @@ std::shared_ptr<Engine> ADIOS::Open( const std::string name, const std::string a const std::string type( method.m_Type ); - const bool isDefaultWriter = ( accessMode == "w" || accessMode == "write" ) && type.empty() ? true : false; + const bool isDefaultWriter = ( accessMode == "w" || accessMode == "write" || + accessMode == "a" || accessMode == "append" ) && type.empty() ? true : false; + const bool isDefaultReader = ( accessMode == "r" || accessMode == "read" ) && type.empty() ? true : false; - if( isDefaultWriter || type == "BPWriter" || type == "bpwriter" ) + if( isDefaultWriter || type == "BPFileWriter" || type == "bpfilewriter" ) { - return std::make_shared<BPWriter>( *this, name, accessMode, mpiComm, method, m_DebugMode, cores ); + return std::make_shared<BPFileWriter>( *this, name, accessMode, mpiComm, method, m_DebugMode, cores ); } else if( isDefaultReader || type == "BPReader" || type == "bpreader" ) { - return std::make_shared<BPReader>( *this, name, accessMode, mpiComm, method, m_DebugMode, cores ); + return std::make_shared<BPFileReader>( *this, name, accessMode, mpiComm, method, m_DebugMode, cores ); } else if( type == "SIRIUS" || type == "sirius" || type == "Sirius" ) { @@ -176,7 +185,7 @@ std::shared_ptr<Engine> ADIOS::Open( const std::string name, const std::string a VariableCompound& ADIOS::GetVariableCompound( const std::string name ) { - return m_Compound[ GetVariableIndex<void>(name) ]; + return m_Compound.at( GetVariableIndex<void>(name) ); } @@ -227,6 +236,15 @@ void ADIOS::MonitorVariables( std::ostream& logStream ) else if( type == GetType<long double>() ) GetVariable<long double>( name ).Monitor( logStream ); + + else if( type == GetType<std::complex<float>>() ) + GetVariable<std::complex<float>>( name ).Monitor( logStream ); + + else if( type == GetType<std::complex<double>>() ) + GetVariable<std::complex<double>>( name ).Monitor( logStream ); + + else if( type == GetType<std::complex<long double>>() ) + GetVariable<std::complex<long double>>( name ).Monitor( logStream ); } } diff --git a/src/core/Transport.cpp b/src/core/Transport.cpp index 1b5cec2861f2bfe84a679828bad1136f9a0c48c4..4bbc1f7439e6f2db0e09859f16b0aecae7697bcb 100644 --- a/src/core/Transport.cpp +++ b/src/core/Transport.cpp @@ -37,5 +37,26 @@ void Transport::Close( ) { } +void Transport::InitProfiler( const std::string accessMode, const Support::Resolutions resolution ) +{ + m_Profiler.m_Timers.emplace_back( "open", Support::Resolutions::mus ); + + if( accessMode == "w" || accessMode == "write" ) + m_Profiler.m_Timers.emplace_back( "write", resolution ); + + else if( accessMode == "a" || accessMode == "append" ) + m_Profiler.m_Timers.emplace_back( "append", resolution ); + + else if( accessMode == "r" || accessMode == "read" ) + m_Profiler.m_Timers.emplace_back( "read", resolution ); + + m_Profiler.m_Timers.emplace_back( "close", Support::Resolutions::mus ); + + m_Profiler.m_TotalBytes.push_back( 0 ); + m_Profiler.m_IsActive = true; +} + + + } //end namespace diff --git a/src/mpidummy.cpp b/src/mpidummy.cpp index 811e90c7b7effed30d683502ec3140fec926e2b7..e58e1b817cdf2756be130428857f0c844079f0f4 100644 --- a/src/mpidummy.cpp +++ b/src/mpidummy.cpp @@ -1,4 +1,4 @@ -/* +/* * ADIOS is freely available under the terms of the BSD license described * in the COPYING file in the top level directory of this source distribution. * @@ -9,6 +9,7 @@ A dummy MPI implementation for the BP READ API, to have an MPI-free version of the API */ /// \cond EXCLUDE_FROM_DOXYGEN +#define __STDC_FORMAT_MACROS #include <stdint.h> #include <inttypes.h> #include <stdio.h> @@ -24,7 +25,7 @@ -#if defined(__APPLE__) || defined(__WIN32__) || defined(__CYGWIN__) +#if defined(__APPLE__) || defined(__WIN32__) || defined(__CYGWIN__) # define lseek64 lseek # define open64 open #endif @@ -35,16 +36,16 @@ namespace adios static char mpierrmsg[MPI_MAX_ERROR_STRING]; -int MPI_Init(int *argc, char ***argv) -{ - mpierrmsg[0] = '\0'; - return MPI_SUCCESS; +int MPI_Init(int *argc, char ***argv) +{ + mpierrmsg[0] = '\0'; + return MPI_SUCCESS; } -int MPI_Finalize() -{ - mpierrmsg[0] = '\0'; - return MPI_SUCCESS; +int MPI_Finalize() +{ + mpierrmsg[0] = '\0'; + return MPI_SUCCESS; } int MPI_Initialized( int* flag ) @@ -64,8 +65,8 @@ int MPI_Comm_size(MPI_Comm comm, int *size) { *size = 1; return MPI_SUCCESS; } int MPI_Comm_free(MPI_Comm *comm) { *comm = 0; return MPI_SUCCESS; } MPI_Comm MPI_Comm_f2c(MPI_Fint comm) { return comm; } -int MPI_Gather(void *sendbuf, int sendcnt, MPI_Datatype sendtype, - void *recvbuf, int recvcnt, MPI_Datatype recvtype, +int MPI_Gather(void *sendbuf, int sendcnt, MPI_Datatype sendtype, + void *recvbuf, int recvcnt, MPI_Datatype recvtype, int root, MPI_Comm comm) { int ier = MPI_SUCCESS; @@ -97,8 +98,8 @@ int MPI_Gather(void *sendbuf, int sendcnt, MPI_Datatype sendtype, return ier ; } -int MPI_Gatherv(void *sendbuf, int sendcnt, MPI_Datatype sendtype, - void *recvbuf, int *recvcnts, int *displs, +int MPI_Gatherv(void *sendbuf, int sendcnt, MPI_Datatype sendtype, + void *recvbuf, int *recvcnts, int *displs, MPI_Datatype recvtype, int root, MPI_Comm comm) { int ier = MPI_SUCCESS; @@ -117,8 +118,8 @@ int MPI_Allgather(void *sendbuf, int sendcount, MPI_Datatype sendtype, return MPI_Gather (sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, 0, comm); } -int MPI_Scatter(void *sendbuf, int sendcnt, MPI_Datatype sendtype, - void *recvbuf, int recvcnt, MPI_Datatype recvtype, int root, +int MPI_Scatter(void *sendbuf, int sendcnt, MPI_Datatype sendtype, + void *recvbuf, int recvcnt, MPI_Datatype recvtype, int root, MPI_Comm comm) { int ier = MPI_SUCCESS; @@ -150,7 +151,7 @@ int MPI_Scatter(void *sendbuf, int sendcnt, MPI_Datatype sendtype, return ier ; } -int MPI_Scatterv( void *sendbuf, int *sendcnts, int *displs, +int MPI_Scatterv( void *sendbuf, int *sendcnts, int *displs, MPI_Datatype sendtype, void *recvbuf, int recvcnt, MPI_Datatype recvtype, int root, MPI_Comm comm) @@ -167,10 +168,19 @@ int MPI_Scatterv( void *sendbuf, int *sendcnts, int *displs, int MPI_Recv( void *recvbuffer, int count, MPI_Datatype type, int source, int tag, MPI_Comm comm, MPI_Status* status ) { return 0; } +int MPI_Irecv( void *recvbuffer, int count, MPI_Datatype type, int source, int tag, MPI_Comm comm, MPI_Request* request ) +{ return 0; } + int MPI_Send( void *sendbuffer, int count, MPI_Datatype type, int destination, int tag, MPI_Comm comm ) { return 0; } -int MPI_File_open(MPI_Comm comm, char *filename, int amode, MPI_Info info, MPI_File *fh) +int MPI_Isend( void *recvbuffer, int count, MPI_Datatype type, int source, int tag, MPI_Comm comm, MPI_Request* request ) +{ return 0; } + +int MPI_Wait( MPI_Request* request, MPI_Status* status ) +{ return 0; } + +int MPI_File_open(MPI_Comm comm, char *filename, int amode, MPI_Info info, MPI_File *fh) { *fh = open64 (filename, amode); if (*fh == -1) { @@ -214,15 +224,15 @@ int MPI_File_seek(MPI_File fh, MPI_Offset offset, int whence) return MPI_SUCCESS; } -int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count) -{ +int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count) +{ *count = (int) *status; return MPI_SUCCESS; } int MPI_Error_string(int errorcode, char *string, int *resultlen) { - //sprintf(string, "Dummy lib does not know error strings. Code=%d\n",errorcode); + //sprintf(string, "Dummy lib does not know error strings. Code=%d\n",errorcode); strcpy(string, mpierrmsg); *resultlen = strlen(string); return MPI_SUCCESS; @@ -233,7 +243,7 @@ double MPI_Wtime() // Implementation not tested struct timeval tv; gettimeofday (&tv, NULL); - return (double)(tv.tv_sec) + (double)(tv.tv_usec) / 1000000; + return (double)(tv.tv_sec) + (double)(tv.tv_usec) / 1000000; } int MPI_Get_processor_name (char *name, int *resultlen)