From 4df1c4f0765daccdb26d25b8bbce7d121f8ae074 Mon Sep 17 00:00:00 2001 From: wfg <wfg@pc0098504.ornl.gov> Date: Mon, 13 Mar 2017 17:58:16 -0400 Subject: [PATCH] Dynamic libadios.so version in Makefile and Python bindings Started implementation of bindings/python using boost::python Modified Makefile to allow for dynamic library compilation To do: Work on time aggregation --- Makefile | 24 ++- bindings/python/Makefile | 41 +++++ bindings/python/include/ADIOSPy.h | 65 ++++++++ bindings/python/include/adiosPyFunctions.h | 27 ++++ bindings/python/src/ADIOSPy.cpp | 169 +++++++++++++++++++++ bindings/python/src/adiosPyFunctions.cpp | 45 ++++++ bindings/python/src/glue.cpp | 48 ++++++ bindings/python/test_hello.py | 38 +++++ examples/hello/bpWriter/helloBPWriter.cpp | 2 +- include/ADIOS.h | 4 +- include/core/VariableBase.h | 1 - src/engine/bp/BPFileWriter.cpp | 4 +- 12 files changed, 455 insertions(+), 13 deletions(-) create mode 100644 bindings/python/Makefile create mode 100644 bindings/python/include/ADIOSPy.h create mode 100644 bindings/python/include/adiosPyFunctions.h create mode 100644 bindings/python/src/ADIOSPy.cpp create mode 100644 bindings/python/src/adiosPyFunctions.cpp create mode 100644 bindings/python/src/glue.cpp create mode 100644 bindings/python/test_hello.py diff --git a/Makefile b/Makefile index 33d285130..706583463 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,8 +50,8 @@ 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) @@ -48,8 +60,8 @@ mpi: $(HFiles) $(OBJMPI) 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) diff --git a/bindings/python/Makefile b/bindings/python/Makefile new file mode 100644 index 000000000..68eca071f --- /dev/null +++ b/bindings/python/Makefile @@ -0,0 +1,41 @@ +#Makefile +# Created on: Mar 13, 2017 +# Author: wfg + +# location of the Python header files +PYTHON_VERSION:= 2.7 +PYTHON_INC:= /usr/include/python$(PYTHON_VERSION) +PYTHON_LIBLOC:= /usr/lib/python2.7/config-x86_64-linux-gnu/ + +# location of the Boost Python include files and library +BOOST_INC:= /usr/include/boost +BOOST_LIBLOC:= /lib/x86_64-linux-gnu/ + +# location of ADIOS include and lib +ADIOS_INC:= /home/wfg/workspace/ADIOSPP/include +ADIOS_LIB:= /home/wfg/workspace/ADIOSPP/lib +ADIOSPy_INC:=./include + +CFLAGS:=-c -Wall -fPIC -O0 -g -std=c++11 + +CPPFiles:=$(shell find ./src -type f -name "*.cpp") +OBJS:=$(patsubst %.cpp, ./bin/%.o, $(notdir $(CPPFiles)) ) + +INC:= -I$(PYTHON_INC) -I$(BOOST_INC) -I$(ADIOS_INC) -I$(ADIOSPy_INC) +LIBS:= -L$(ADIOS_LIB) -ladios -L$(BOOST_LIBLOC) -lboost_python-py27 -L$(PYTHON_LIBLOC) -lpython$(PYTHON_VERSION) + + +# compile mesh classes +TARGET = ADIOSPy + +all: $(TARGET).so + +$(TARGET).so: $(OBJS) + mpic++ -shared -o $(TARGET).so -Wl,--export-dynamic $(OBJS) $(LIBS) + +./bin/%.o: ./src/%.cpp + @( mkdir -p ./bin ); + mpic++ $(INC) $(CFLAGS) -o $@ $< + +clean: + rm ./bin/*.o *.so \ No newline at end of file diff --git a/bindings/python/include/ADIOSPy.h b/bindings/python/include/ADIOSPy.h new file mode 100644 index 000000000..ad802f4ff --- /dev/null +++ b/bindings/python/include/ADIOSPy.h @@ -0,0 +1,65 @@ +/* + * ADIOSPy.h + * + * Created on: Mar 13, 2017 + * Author: wfg + */ + +#ifndef ADIOSPY_H_ +#define ADIOSPY_H_ + +#include <string> + +#include <boost/python.hpp> + +#include "ADIOS.h" +#include "adiosPyFunctions.h" //ListToVector, VectorToList + + +namespace adios +{ + + +class ADIOSPy : public ADIOS +{ + +public: + + ADIOSPy( MPI_Comm mpiComm, const bool debug ); + ~ADIOSPy( ); + + void HelloMPI( ); ///< says hello from rank/size for testing + + std::string DefineVariableDouble( const std::string name, + const boost::python::list localDimensionsPy = boost::python::list(), + const boost::python::list globalDimensionsPy = boost::python::list(), + const boost::python::list globalOffsetsPy = boost::python::list() ); + + std::string DefineVariableFloat( const std::string name, + const boost::python::list localDimensionsPy = boost::python::list(), + const boost::python::list globalDimensionsPy = boost::python::list(), + const boost::python::list globalOffsetsPy = boost::python::list() ); + + void SetVariableLocalDimensions( const std::string name, const boost::python::list list ); + + boost::python::list GetVariableLocalDimensions( const std::string name ); + + +private: + template< class T > + std::string DefineVariablePy( const std::string name, const boost::python::list& localDimensionsPy, + const boost::python::list& globalDimensionsPy, const boost::python::list& globalOffsetsPy ) + { + DefineVariable<T>( name, ListToVector( localDimensionsPy ), ListToVector( globalDimensionsPy ), ListToVector( globalOffsetsPy ) ); + return name; + } + + +}; + + + +} //end namespace + + +#endif /* ADIOSPY_H_ */ diff --git a/bindings/python/include/adiosPyFunctions.h b/bindings/python/include/adiosPyFunctions.h new file mode 100644 index 000000000..99935b2a6 --- /dev/null +++ b/bindings/python/include/adiosPyFunctions.h @@ -0,0 +1,27 @@ +/* + * adiosPyFunctions.h + * + * Created on: Mar 13, 2017 + * Author: wfg + */ + +#ifndef ADIOSPYFUNCTIONS_H_ +#define ADIOSPYFUNCTIONS_H_ + +#include <vector> +#include <string> +#include <boost/python.hpp> + + +namespace adios +{ + +std::vector<std::size_t> ListToVector( const boost::python::list& list ); + +boost::python::list VectorToList( const std::vector<std::size_t>& list ); + +} + + + +#endif /* ADIOSPYFUNCTIONS_H_ */ diff --git a/bindings/python/src/ADIOSPy.cpp b/bindings/python/src/ADIOSPy.cpp new file mode 100644 index 000000000..9b3845f21 --- /dev/null +++ b/bindings/python/src/ADIOSPy.cpp @@ -0,0 +1,169 @@ +/* + * ADIOSPy.cpp + * + * Created on: Mar 13, 2017 + * Author: wfg + */ + +#include <iostream> + +#include "ADIOSPy.h" + +namespace adios +{ + + +ADIOSPy::ADIOSPy( MPI_Comm mpiComm, const bool debug ): + ADIOS( mpiComm, debug ) +{ } + + +ADIOSPy::~ADIOSPy( ) +{ } + + +void ADIOSPy::HelloMPI( ) +{ + std::cout << "Hello ADIOSPy from rank " << m_RankMPI << "/" << m_SizeMPI << "\n"; +} + + +std::string ADIOSPy::DefineVariableFloat( const std::string name, const boost::python::list localDimensionsPy, + const boost::python::list globalDimensionsPy, const boost::python::list globalOffsetsPy ) +{ + return DefineVariablePy<float>( name, localDimensionsPy, globalDimensionsPy, globalOffsetsPy ); +} + + +std::string ADIOSPy::DefineVariableDouble( const std::string name, const boost::python::list localDimensionsPy, + const boost::python::list globalDimensionsPy, const boost::python::list globalOffsetsPy ) +{ + return DefineVariablePy<double>( name, localDimensionsPy, globalDimensionsPy, globalOffsetsPy ); +} + + +void ADIOSPy::SetVariableLocalDimensions( const std::string name, const boost::python::list list ) +{ + + auto itVar = m_Variables.find( name ); + CheckVariableName( itVar, name, " in SetVariableLocalDimensions\n" ); + + const std::string type = itVar->second.first; + + if( type == GetType<char>() ) + GetVariable<char>( name ).m_Dimensions = ListToVector( list ); + + else if( type == GetType<unsigned char>() ) + GetVariable<unsigned char>( name ).m_Dimensions = ListToVector( list ); + + else if( type == GetType<short>() ) + GetVariable<short>( name ).m_Dimensions = ListToVector( list ); + + else if( type == GetType<unsigned short>() ) + GetVariable<unsigned short>( name ).m_Dimensions = ListToVector( list ); + + else if( type == GetType<int>() ) + GetVariable<int>( name ).m_Dimensions = ListToVector( list ); + + else if( type == GetType<unsigned int>() ) + GetVariable<unsigned int>( name ).m_Dimensions = ListToVector( list ); + + else if( type == GetType<long int>() ) + GetVariable<long int>( name ).m_Dimensions = ListToVector( list ); + + else if( type == GetType<unsigned long int>() ) + GetVariable<unsigned long int>( name ).m_Dimensions = ListToVector( list ); + + else if( type == GetType<long long int>() ) + GetVariable<long long int>( name ).m_Dimensions = ListToVector( list ); + + else if( type == GetType<unsigned long long int>() ) + GetVariable<unsigned long long int>( name ).m_Dimensions = ListToVector( list ); + + else if( type == GetType<float>() ) + GetVariable<float>( name ).m_Dimensions = ListToVector( list ); + + else if( type == GetType<double>() ) + GetVariable<double>( name ).m_Dimensions = ListToVector( list ); + + else if( type == GetType<long double>() ) + GetVariable<long double>( name ).m_Dimensions = ListToVector( list ); + + else if( type == GetType<std::complex<float>>() ) + GetVariable<std::complex<float>>( name ).m_Dimensions = ListToVector( list ); + + else if( type == GetType<std::complex<double>>() ) + GetVariable<std::complex<double>>( name ).m_Dimensions = ListToVector( list ); + + else if( type == GetType<std::complex<long double>>() ) + GetVariable<std::complex<long double>>( name ).m_Dimensions = ListToVector( list ); +} + + +boost::python::list ADIOSPy::GetVariableLocalDimensions( const std::string name ) +{ + auto itVar = m_Variables.find( name ); + CheckVariableName( itVar, name, " in SetVariableLocalDimensions\n" ); + + const std::string type = itVar->second.first; + + std::vector<std::size_t> dims; + + if( type == GetType<char>() ) + dims = GetVariable<char>( name ).m_Dimensions; + + else if( type == GetType<unsigned char>() ) + dims = GetVariable<unsigned char>( name ).m_Dimensions; + + else if( type == GetType<short>() ) + dims = GetVariable<short>( name ).m_Dimensions; + + else if( type == GetType<unsigned short>() ) + dims = GetVariable<unsigned short>( name ).m_Dimensions; + + else if( type == GetType<int>() ) + dims = GetVariable<int>( name ).m_Dimensions; + + else if( type == GetType<unsigned int>() ) + dims = GetVariable<unsigned int>( name ).m_Dimensions; + + else if( type == GetType<long int>() ) + dims = GetVariable<long int>( name ).m_Dimensions; + + else if( type == GetType<unsigned long int>() ) + dims = GetVariable<unsigned long int>( name ).m_Dimensions; + + else if( type == GetType<long long int>() ) + dims = GetVariable<long long int>( name ).m_Dimensions; + + else if( type == GetType<unsigned long long int>() ) + dims = GetVariable<unsigned long long int>( name ).m_Dimensions; + + else if( type == GetType<float>() ) + dims = GetVariable<float>( name ).m_Dimensions; + + else if( type == GetType<double>() ) + dims = GetVariable<double>( name ).m_Dimensions; + + else if( type == GetType<long double>() ) + dims = GetVariable<long double>( name ).m_Dimensions; + + else if( type == GetType<std::complex<float>>() ) + dims = GetVariable<std::complex<float>>( name ).m_Dimensions; + + else if( type == GetType<std::complex<double>>() ) + dims = GetVariable<std::complex<double>>( name ).m_Dimensions; + + else if( type == GetType<std::complex<long double>>() ) + dims = GetVariable<std::complex<long double>>( name ).m_Dimensions; + + //return dims; + return VectorToList( dims ); +} + + + + +} //end namespace + + diff --git a/bindings/python/src/adiosPyFunctions.cpp b/bindings/python/src/adiosPyFunctions.cpp new file mode 100644 index 000000000..df8b41439 --- /dev/null +++ b/bindings/python/src/adiosPyFunctions.cpp @@ -0,0 +1,45 @@ +/* + * adiosPyFunctions.cpp + * + * Created on: Mar 13, 2017 + * Author: wfg + */ +#include <iostream> + +#include "adiosPyFunctions.h" + + +namespace adios +{ + +std::vector<std::size_t> ListToVector( const boost::python::list& list ) +{ + const boost::python::ssize_t length = boost::python::len( list ); + std::vector<std::size_t> vec; + vec.reserve( length ); + + for( unsigned int i=0; i<length;i++ ) + vec.push_back( boost::python::extract<std::size_t>( list[i]) ); + + return vec; +} + + +boost::python::list VectorToList( const std::vector<std::size_t>& vec ) +{ + boost::python::list list; + + for( auto vecElement : vec ) + { + list.append( vecElement ); + } + + return list; +} + + + + + +} + diff --git a/bindings/python/src/glue.cpp b/bindings/python/src/glue.cpp new file mode 100644 index 000000000..93ebb9434 --- /dev/null +++ b/bindings/python/src/glue.cpp @@ -0,0 +1,48 @@ +/* + * glue.cpp + * + * Created on: Mar 13, 2017 + * Author: wfg + */ + +#include <mpi4py/mpi4py.h> +#include <boost/python.hpp> +#include <boost/python/suite/indexing/vector_indexing_suite.hpp> + +#include "ADIOSPy.h" +#include "adiosPyFunctions.h" + + +adios::ADIOSPy ADIOSPy( boost::python::object py_comm, const bool debug ) +{ + MPI_Comm* comm_p = PyMPIComm_Get( py_comm.ptr() ); + if (comm_p == NULL) boost::python::throw_error_already_set(); + return adios::ADIOSPy( *comm_p, debug ); +} + + +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( d_overloads, DefineVariableDouble, 1, 4 ) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS( f_overloads, DefineVariableFloat, 1, 4 ) + + +BOOST_PYTHON_MODULE( ADIOSPy ) +{ + if (import_mpi4py() < 0) return; /* Python 2.X */ + + + boost::python::class_<std::vector<std::size_t> >("Dims") + .def(boost::python::vector_indexing_suite< std::vector<std::size_t> >() ); + //functions + boost::python::def("ADIOSPy", ADIOSPy ); + + //classes + boost::python::class_<adios::ADIOSPy>("ADIOS", boost::python::no_init ) + .def("HelloMPI", &adios::ADIOSPy::HelloMPI ) + .def("DefineVariableDouble", &adios::ADIOSPy::DefineVariableDouble, d_overloads() ) + .def("DefineVariableFloat", &adios::ADIOSPy::DefineVariableFloat, f_overloads() ) + .def("SetVariableLocalDimensions", &adios::ADIOSPy::SetVariableLocalDimensions ) + .def("GetVariableLocalDimensions", &adios::ADIOSPy::GetVariableLocalDimensions ) + ; + + +} diff --git a/bindings/python/test_hello.py b/bindings/python/test_hello.py new file mode 100644 index 000000000..0b9cd13ce --- /dev/null +++ b/bindings/python/test_hello.py @@ -0,0 +1,38 @@ +# test_hello.py +# Created on: Feb 2, 2017 +# Author: wfg + +from mpi4py import MPI +from ADIOSPy import * + +adios = ADIOSPy( MPI.COMM_WORLD, True) +adios.HelloMPI( ) + +lDims = [10, 11, 12] +Nx = 1 + +print lDims +print lDims[0] +ioMyDoubles = adios.DefineVariableDouble( "ioMyDoubles", lDims ) +ioMyFloats = adios.DefineVariableFloat( "ioMyFloats", [Nx] ) + +print "My ADIOS Variable Double " + ioMyDoubles +print "My ADIOS Variable Float " + ioMyFloats + +dims = adios.GetVariableLocalDimensions( ioMyDoubles ) +print "Old Dimensions " +print dims + +lDims = [20,20,20] +adios.SetVariableLocalDimensions( ioMyDoubles, lDims ) + +dims = adios.GetVariableLocalDimensions( ioMyDoubles ) +print "New Dimensions " +print dims + + +# bpWriter = adios.Open( ) +# ADIOS.SetEngineComm( bpWriter, comm ) +# bpWriter.Hello( ) + +# challenge is to pass comm to C++ diff --git a/examples/hello/bpWriter/helloBPWriter.cpp b/examples/hello/bpWriter/helloBPWriter.cpp index 2251ecdf3..496bdeb3f 100644 --- a/examples/hello/bpWriter/helloBPWriter.cpp +++ b/examples/hello/bpWriter/helloBPWriter.cpp @@ -54,7 +54,7 @@ int main( int argc, char* argv [] ) //Define method for engine creation, it is basically straight-forward parameters adios::Method& bpWriterSettings = adios.DeclareMethod( "SingleFile" ); //default method type is BPWriter - bpWriterSettings.AddTransport( "File", "have_metadata_file=yes" ); //uses default POSIX library + bpWriterSettings.AddTransport( "File", "have_metadata_file=no" ); //uses default POSIX library //Create engine smart pointer due to polymorphism, //Open returns a smart pointer to Engine containing the Derived class Writer diff --git a/include/ADIOS.h b/include/ADIOS.h index 8c3ba6216..00c58e52a 100644 --- a/include/ADIOS.h +++ b/include/ADIOS.h @@ -84,10 +84,8 @@ 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 * @param name @@ -192,7 +190,7 @@ 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; diff --git a/include/core/VariableBase.h b/include/core/VariableBase.h index 07d6602f7..4bf492354 100644 --- a/include/core/VariableBase.h +++ b/include/core/VariableBase.h @@ -22,7 +22,6 @@ namespace adios using Dims = std::vector<std::size_t>; - class VariableBase { diff --git a/src/engine/bp/BPFileWriter.cpp b/src/engine/bp/BPFileWriter.cpp index 8be5a0249..a22d286c0 100644 --- a/src/engine/bp/BPFileWriter.cpp +++ b/src/engine/bp/BPFileWriter.cpp @@ -246,7 +246,7 @@ void BPFileWriter::InitTransports( ) for( const auto& parameters : m_Method.m_TransportParameters ) { auto itProfile = parameters.find( "profile_units" ); - Support::Resolutions resolution; + Support::Resolutions resolution = Support::Resolutions::s; //default is seconds if( itProfile != parameters.end() ) { if( itProfile->second == "mus" || itProfile->second == "microseconds" ) @@ -362,7 +362,7 @@ void BPFileWriter::WriteProcessGroupIndex( ) bool BPFileWriter::CheckBuffersAllocation( const std::size_t indexSize, const std::size_t payloadSize ) { //Check if data in buffer needs to be reallocated - const std::size_t neededSize = m_Buffer.m_DataPosition + payloadSize + indexSize + 500; //adding some bytes tolerance + const std::size_t neededSize = m_Buffer.m_DataPosition + payloadSize + indexSize + 100; //adding some bytes tolerance // might need to write payload in batches bool doTransportsFlush = ( neededSize > m_MaxBufferSize )? true : false; -- GitLab