From 191b280371e69af31ea36d4be354c6b76a31dc52 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Tue, 24 Jul 2012 16:16:56 +0200 Subject: [PATCH] Code organisation, splitted headers files in implementation files, as much as possible (impossible for templates functions, thank you C++) --- eo/src/mpi/CMakeLists.txt | 3 + eo/src/mpi/eoMpi.cpp | 26 ++- eo/src/mpi/eoMpi.h | 12 +- eo/src/mpi/eoMpiAssignmentAlgorithm.cpp | 204 +++++++++++++++++ eo/src/mpi/eoMpiAssignmentAlgorithm.h | 188 ++-------------- eo/src/mpi/eoMpiNode.cpp | 19 ++ eo/src/mpi/eoMpiNode.h | 18 +- eo/src/mpi/implMpi.cpp | 146 ++++++++++++ eo/src/mpi/implMpi.h | 129 +++++++++++ eo/src/mpi/implMpi.hpp | 283 ------------------------ 10 files changed, 550 insertions(+), 478 deletions(-) create mode 100644 eo/src/mpi/eoMpiAssignmentAlgorithm.cpp create mode 100644 eo/src/mpi/eoMpiNode.cpp create mode 100644 eo/src/mpi/implMpi.cpp create mode 100644 eo/src/mpi/implMpi.h delete mode 100644 eo/src/mpi/implMpi.hpp diff --git a/eo/src/mpi/CMakeLists.txt b/eo/src/mpi/CMakeLists.txt index 0e22e47e..00a33877 100644 --- a/eo/src/mpi/CMakeLists.txt +++ b/eo/src/mpi/CMakeLists.txt @@ -14,6 +14,9 @@ SET(LIBRARY_OUTPUT_PATH ${EOMPI_LIB_OUTPUT_PATH}) SET(EOMPI_SOURCES eoMpi.cpp + eoMpiAssignmentAlgorithm.cpp + eoMpiNode.cpp + implMpi.cpp ) ADD_LIBRARY(eompi STATIC ${EOMPI_SOURCES}) diff --git a/eo/src/mpi/eoMpi.cpp b/eo/src/mpi/eoMpi.cpp index 250d90bf..56422c13 100644 --- a/eo/src/mpi/eoMpi.cpp +++ b/eo/src/mpi/eoMpi.cpp @@ -4,16 +4,24 @@ namespace eo { namespace mpi { - bmpi::communicator Node::_comm; + /********************************************** + * *********** GLOBALS ************************ + * *******************************************/ eoTimerStat timerStat; - } -} -namespace mpi -{ - void broadcast( communicator & comm, int value, int root ) - { - comm; // unused - MPI_Bcast( &value, 1, MPI_INT, root, MPI_COMM_WORLD ); + namespace Channel + { + const int Commands = 0; + const int Messages = 1; + } + + namespace Message + { + const int Continue = 0; + const int Finish = 1; + const int Kill = 2; + } + + const int DEFAULT_MASTER = 0; } } diff --git a/eo/src/mpi/eoMpi.h b/eo/src/mpi/eoMpi.h index ee92e087..92c2ba99 100644 --- a/eo/src/mpi/eoMpi.h +++ b/eo/src/mpi/eoMpi.h @@ -143,8 +143,8 @@ namespace eo */ namespace Channel { - const int Commands = 0; - const int Messages = 1; + extern const int Commands; + extern const int Messages; } /** @@ -157,9 +157,9 @@ namespace eo */ namespace Message { - const int Continue = 0; - const int Finish = 1; - const int Kill = 2; + extern const int Continue; + extern const int Finish; + extern const int Kill; } /** @@ -167,7 +167,7 @@ namespace eo * * @ingroup MPI */ - const int DEFAULT_MASTER = 0; + extern const int DEFAULT_MASTER; /** * @brief Base class for the 4 algorithm functors. diff --git a/eo/src/mpi/eoMpiAssignmentAlgorithm.cpp b/eo/src/mpi/eoMpiAssignmentAlgorithm.cpp new file mode 100644 index 00000000..e51fc2b5 --- /dev/null +++ b/eo/src/mpi/eoMpiAssignmentAlgorithm.cpp @@ -0,0 +1,204 @@ +# include "eoMpiAssignmentAlgorithm.h" + +# include "eoMpiNode.h" + +namespace eo +{ + namespace mpi + { + const int REST_OF_THE_WORLD = -1; + + /******************************************************** + * DYNAMIC ASSIGNMENT ALGORITHM ************************* + *******************************************************/ + + DynamicAssignmentAlgorithm::DynamicAssignmentAlgorithm( ) + { + for(int i = 1; i < Node::comm().size(); ++i) + { + availableWrk.push_back( i ); + } + } + + DynamicAssignmentAlgorithm::DynamicAssignmentAlgorithm( int unique ) + { + availableWrk.push_back( unique ); + } + + DynamicAssignmentAlgorithm::DynamicAssignmentAlgorithm( const std::vector & workers ) + { + availableWrk = workers; + } + + DynamicAssignmentAlgorithm::DynamicAssignmentAlgorithm( int first, int last ) + { + if( last == REST_OF_THE_WORLD ) + { + last = Node::comm().size() - 1; + } + + for( int i = first; i <= last; ++i) + { + availableWrk.push_back( i ); + } + } + + int DynamicAssignmentAlgorithm::get( ) + { + int assignee = -1; + if (! availableWrk.empty() ) + { + assignee = availableWrk.back(); + availableWrk.pop_back(); + } + return assignee; + } + + int DynamicAssignmentAlgorithm::availableWorkers() + { + return availableWrk.size(); + } + + void DynamicAssignmentAlgorithm::confirm( int rank ) + { + availableWrk.push_back( rank ); + } + + std::vector DynamicAssignmentAlgorithm::idles( ) + { + return availableWrk; + } + + void DynamicAssignmentAlgorithm::reinit( int _ ) + { + ++_; + // nothing to do + } + + /******************************************************** + * STATIC ASSIGNMENT ALGORITHM ************************** + *******************************************************/ + + StaticAssignmentAlgorithm::StaticAssignmentAlgorithm( std::vector& workers, int runs ) + { + init( workers, runs ); + } + + StaticAssignmentAlgorithm::StaticAssignmentAlgorithm( int first, int last, int runs ) + { + std::vector workers; + + if( last == REST_OF_THE_WORLD ) + { + last = Node::comm().size() - 1; + } + + for(int i = first; i <= last; ++i) + { + workers.push_back( i ); + } + init( workers, runs ); + } + + StaticAssignmentAlgorithm::StaticAssignmentAlgorithm( int runs ) + { + std::vector workers; + for(int i = 1; i < Node::comm().size(); ++i) + { + workers.push_back( i ); + } + + init( workers, runs ); + } + + StaticAssignmentAlgorithm::StaticAssignmentAlgorithm( int unique, int runs ) + { + std::vector workers; + workers.push_back( unique ); + init( workers, runs ); + } + + void StaticAssignmentAlgorithm::init( std::vector & workers, int runs ) + { + unsigned int nbWorkers = workers.size(); + freeWorkers = nbWorkers; + + busy.clear(); + busy.resize( nbWorkers, false ); + realRank = workers; + + if( runs <= 0 ) + { + return; + } + + attributions.clear(); + attributions.reserve( nbWorkers ); + + // Let be the euclidean division of runs by nbWorkers : + // runs == q * nbWorkers + r, 0 <= r < nbWorkers + // This one liner affects q requests to each worker + for (unsigned int i = 0; i < nbWorkers; attributions[i++] = runs / nbWorkers) ; + // The first line computes r and the one liner affects the remaining + // r requests to workers, in ascending order + unsigned int diff = runs - (runs / nbWorkers) * nbWorkers; + for (unsigned int i = 0; i < diff; ++attributions[i++]); + } + + int StaticAssignmentAlgorithm::get( ) + { + int assignee = -1; + for( unsigned i = 0; i < busy.size(); ++i ) + { + if( !busy[i] && attributions[i] > 0 ) + { + busy[i] = true; + --freeWorkers; + assignee = realRank[ i ]; + break; + } + } + return assignee; + } + + int StaticAssignmentAlgorithm::availableWorkers( ) + { + return freeWorkers; + } + + std::vector StaticAssignmentAlgorithm::idles() + { + std::vector ret; + for(unsigned int i = 0; i < busy.size(); ++i) + { + if( !busy[i] ) + { + ret.push_back( realRank[i] ); + } + } + return ret; + } + + void StaticAssignmentAlgorithm::confirm( int rank ) + { + int i = -1; // i is the real index in table + for( unsigned int j = 0; j < realRank.size(); ++j ) + { + if( realRank[j] == rank ) + { + i = j; + break; + } + } + + --attributions[ i ]; + busy[ i ] = false; + ++freeWorkers; + } + + void StaticAssignmentAlgorithm::reinit( int runs ) + { + init( realRank, runs ); + } + } +} diff --git a/eo/src/mpi/eoMpiAssignmentAlgorithm.h b/eo/src/mpi/eoMpiAssignmentAlgorithm.h index 07f67415..3389db68 100644 --- a/eo/src/mpi/eoMpiAssignmentAlgorithm.h +++ b/eo/src/mpi/eoMpiAssignmentAlgorithm.h @@ -23,7 +23,6 @@ Authors: # define __MPI_ASSIGNMENT_ALGORITHM_H__ # include // std::vector -# include "eoMpiNode.h" namespace eo { @@ -35,7 +34,7 @@ namespace eo * * @ingroup MPI */ - const int REST_OF_THE_WORLD = -1; + extern const int REST_OF_THE_WORLD; /** * @brief Contains informations on the available workers and allows to find assignees for jobs. @@ -115,33 +114,21 @@ namespace eo /** * @brief Uses all the hosts whose rank is higher to 1, inclusive, as workers. */ - DynamicAssignmentAlgorithm( ) - { - for(int i = 1; i < Node::comm().size(); ++i) - { - availableWrk.push_back( i ); - } - } + DynamicAssignmentAlgorithm( ); /** * @brief Uses the unique host with given rank as a worker. * * @param unique MPI rank of the unique worker. */ - DynamicAssignmentAlgorithm( int unique ) - { - availableWrk.push_back( unique ); - } + DynamicAssignmentAlgorithm( int unique ); /** * @brief Uses the workers whose ranks are present in the argument as workers. * * @param workers std::vector containing MPI ranks of workers. */ - DynamicAssignmentAlgorithm( const std::vector & workers ) - { - availableWrk = workers; - } + DynamicAssignmentAlgorithm( const std::vector & workers ); /** * @brief Uses a range of ranks as workers. @@ -150,50 +137,17 @@ namespace eo * @param last The last worker to be included (inclusive). If last == eo::mpi::REST_OF_THE_WORLD, all * hosts whose rank is higher than first are taken. */ - DynamicAssignmentAlgorithm( int first, int last ) - { - if( last == REST_OF_THE_WORLD ) - { - last = Node::comm().size() - 1; - } + DynamicAssignmentAlgorithm( int first, int last ); - for( int i = first; i <= last; ++i) - { - availableWrk.push_back( i ); - } - } + virtual int get( ); - virtual int get( ) - { - int assignee = -1; - if (! availableWrk.empty() ) - { - assignee = availableWrk.back(); - availableWrk.pop_back(); - } - return assignee; - } + int availableWorkers(); - int availableWorkers() - { - return availableWrk.size(); - } + void confirm( int rank ); - void confirm( int rank ) - { - availableWrk.push_back( rank ); - } + std::vector idles( ); - std::vector idles( ) - { - return availableWrk; - } - - void reinit( int _ ) - { - ++_; - // nothing to do - } + void reinit( int _ ); protected: std::vector< int > availableWrk; @@ -223,10 +177,7 @@ namespace eo * @param workers std::vector of MPI ranks of workers which will be used. * @param runs Fixed amount of runs, strictly positive. */ - StaticAssignmentAlgorithm( std::vector& workers, int runs ) - { - init( workers, runs ); - } + StaticAssignmentAlgorithm( std::vector& workers, int runs ); /** * @brief Uses a range of workers. @@ -236,21 +187,7 @@ namespace eo * workers from the first one are taken as workers. * @param runs Fixed amount of runs, strictly positive. */ - StaticAssignmentAlgorithm( int first, int last, int runs ) - { - std::vector workers; - - if( last == REST_OF_THE_WORLD ) - { - last = Node::comm().size() - 1; - } - - for(int i = first; i <= last; ++i) - { - workers.push_back( i ); - } - init( workers, runs ); - } + StaticAssignmentAlgorithm( int first, int last, int runs ); /** * @brief Uses all the hosts whose rank is higher than 1 (inclusive) as workers. @@ -258,16 +195,7 @@ namespace eo * @param runs Fixed amount of runs, strictly positive. If it's not set, you'll have to call reinit() * later. */ - StaticAssignmentAlgorithm( int runs = 0 ) - { - std::vector workers; - for(int i = 1; i < Node::comm().size(); ++i) - { - workers.push_back( i ); - } - - init( workers, runs ); - } + StaticAssignmentAlgorithm( int runs = 0 ); /** * @brief Uses an unique host as worker. @@ -275,12 +203,7 @@ namespace eo * @param unique The MPI rank of the host which will be the worker. * @param runs Fixed amount of runs, strictly positive. */ - StaticAssignmentAlgorithm( int unique, int runs ) - { - std::vector workers; - workers.push_back( unique ); - init( workers, runs ); - } + StaticAssignmentAlgorithm( int unique, int runs ); private: /** @@ -292,89 +215,18 @@ namespace eo * @param workers Vector of hosts' ranks * @param runs Fixed amount of runs, strictly positive. */ - void init( std::vector & workers, int runs ) - { - unsigned int nbWorkers = workers.size(); - freeWorkers = nbWorkers; - - busy.clear(); - busy.resize( nbWorkers, false ); - realRank = workers; - - if( runs <= 0 ) - { - return; - } - - attributions.clear(); - attributions.reserve( nbWorkers ); - - // Let be the euclidean division of runs by nbWorkers : - // runs == q * nbWorkers + r, 0 <= r < nbWorkers - // This one liner affects q requests to each worker - for (unsigned int i = 0; i < nbWorkers; attributions[i++] = runs / nbWorkers) ; - // The first line computes r and the one liner affects the remaining - // r requests to workers, in ascending order - unsigned int diff = runs - (runs / nbWorkers) * nbWorkers; - for (unsigned int i = 0; i < diff; ++attributions[i++]); - } + void init( std::vector & workers, int runs ); public: - int get( ) - { - int assignee = -1; - for( unsigned i = 0; i < busy.size(); ++i ) - { - if( !busy[i] && attributions[i] > 0 ) - { - busy[i] = true; - --freeWorkers; - assignee = realRank[ i ]; - break; - } - } - return assignee; - } + int get( ); - int availableWorkers( ) - { - return freeWorkers; - } + int availableWorkers( ); - std::vector idles() - { - std::vector ret; - for(unsigned int i = 0; i < busy.size(); ++i) - { - if( !busy[i] ) - { - ret.push_back( realRank[i] ); - } - } - return ret; - } + std::vector idles(); - void confirm( int rank ) - { - int i = -1; // i is the real index in table - for( unsigned int j = 0; j < realRank.size(); ++j ) - { - if( realRank[j] == rank ) - { - i = j; - break; - } - } + void confirm( int rank ); - --attributions[ i ]; - busy[ i ] = false; - ++freeWorkers; - } - - void reinit( int runs ) - { - init( realRank, runs ); - } + void reinit( int runs ); private: std::vector attributions; diff --git a/eo/src/mpi/eoMpiNode.cpp b/eo/src/mpi/eoMpiNode.cpp new file mode 100644 index 00000000..22e88da0 --- /dev/null +++ b/eo/src/mpi/eoMpiNode.cpp @@ -0,0 +1,19 @@ +# include "eoMpiNode.h" + +namespace eo +{ + namespace mpi + { + void Node::init( int argc, char** argv ) + { + static bmpi::environment env( argc, argv ); + } + + bmpi::communicator& Node::comm() + { + return _comm; + } + + bmpi::communicator Node::_comm; + } +} diff --git a/eo/src/mpi/eoMpiNode.h b/eo/src/mpi/eoMpiNode.h index f4ffa8a0..c370e1c0 100644 --- a/eo/src/mpi/eoMpiNode.h +++ b/eo/src/mpi/eoMpiNode.h @@ -22,7 +22,7 @@ Authors: # ifndef __MPI_NODE_H__ # define __MPI_NODE_H__ -# include "implMpi.hpp" +# include "implMpi.h" namespace bmpi = mpi; namespace eo @@ -30,9 +30,9 @@ namespace eo namespace mpi { /** - * @brief Global object used to reach boost::mpi::communicator everywhere. + * @brief Global object used to reach mpi::communicator everywhere. * - * boost::mpi::communicator is the main object used to send and receive messages between the different hosts of + * mpi::communicator is the main object used to send and receive messages between the different hosts of * a MPI algorithm. * * @ingroup MPI @@ -49,18 +49,12 @@ namespace eo * @param argc Main's argc * @param argv Main's argv */ - static void init( int argc, char** argv ) - { - static bmpi::environment env( argc, argv ); - } + static void init( int argc, char** argv ); /** - * @brief Returns the global boost::mpi::communicator + * @brief Returns the global mpi::communicator */ - static bmpi::communicator& comm() - { - return _comm; - } + static bmpi::communicator& comm(); protected: static bmpi::communicator _comm; diff --git a/eo/src/mpi/implMpi.cpp b/eo/src/mpi/implMpi.cpp new file mode 100644 index 00000000..ae0dd1c9 --- /dev/null +++ b/eo/src/mpi/implMpi.cpp @@ -0,0 +1,146 @@ +# include "implMpi.h" + +namespace mpi +{ + const int any_source = MPI_ANY_SOURCE; + const int any_tag = MPI_ANY_TAG; + + environment::environment(int argc, char**argv) + { + MPI_Init(&argc, &argv); + } + + environment::~environment() + { + MPI_Finalize(); + } + + status::status( const MPI_Status & s ) + { + _source = s.MPI_SOURCE; + _tag = s.MPI_TAG; + _error = s.MPI_ERROR; + } + + communicator::communicator( ) + { + _rank = -1; + _size = -1; + + _buf = 0; + _bufsize = -1; + } + + communicator::~communicator() + { + if( _buf ) + { + delete _buf; + _buf = 0; + } + } + + int communicator::rank() + { + if ( _rank == -1 ) + { + MPI_Comm_rank( MPI_COMM_WORLD, &_rank ); + } + return _rank; + } + + int communicator::size() + { + if ( _size == -1 ) + { + MPI_Comm_size( MPI_COMM_WORLD, &_size ); + } + return _size; + } + + /* + * SEND / RECV INT + */ + void communicator::send( int dest, int tag, int n ) + { + MPI_Send( &n, 1, MPI_INT, dest, tag, MPI_COMM_WORLD ); + } + + void communicator::recv( int src, int tag, int& n ) + { + MPI_Status stat; + MPI_Recv( &n, 1, MPI_INT, src, tag, MPI_COMM_WORLD , &stat ); + } + + /* + * SEND / RECV STRING + */ + void communicator::send( int dest, int tag, const std::string& str ) + { + int size = str.size() + 1; + send( dest, tag, size ); + MPI_Send( (char*)str.c_str(), size, MPI_CHAR, dest, tag, MPI_COMM_WORLD); + } + + void communicator::recv( int src, int tag, std::string& str ) + { + int size = -1; + MPI_Status stat; + recv( src, tag, size ); + + if( _buf == 0 ) + { + _buf = new char[ size ]; + _bufsize = size; + } else if( _bufsize < size ) + { + delete [] _buf; + _buf = new char[ size ]; + _bufsize = size; + } + MPI_Recv( _buf, size, MPI_CHAR, src, tag, MPI_COMM_WORLD, &stat ); + str.assign( _buf ); + } + + /* + * SEND / RECV Objects + */ + void communicator::send( int dest, int tag, const eoserial::Persistent & persistent ) + { + eoserial::Object* obj = persistent.pack(); + std::stringstream ss; + obj->print( ss ); + delete obj; + send( dest, tag, ss.str() ); + } + + void communicator::recv( int src, int tag, eoserial::Persistent & persistent ) + { + std::string asText; + recv( src, tag, asText ); + eoserial::Object* obj = eoserial::Parser::parse( asText ); + persistent.unpack( obj ); + delete obj; + } + + /* + * Other methods + */ + status communicator::probe( int src, int tag ) + { + MPI_Status stat; + MPI_Probe( src, tag, MPI_COMM_WORLD , &stat ); + return status( stat ); + } + + void communicator::barrier() + { + MPI_Barrier( MPI_COMM_WORLD ); + } + + void broadcast( communicator & comm, int value, int root ) + { + comm; // unused + MPI_Bcast( &value, 1, MPI_INT, root, MPI_COMM_WORLD ); + } +} diff --git a/eo/src/mpi/implMpi.h b/eo/src/mpi/implMpi.h new file mode 100644 index 00000000..b56ba242 --- /dev/null +++ b/eo/src/mpi/implMpi.h @@ -0,0 +1,129 @@ +# ifndef __EO_MPI_HPP__ +# define __EO_MPI_HPP__ + +# include +# include + +namespace mpi +{ + extern const int any_source; + extern const int any_tag; + + class environment + { + public: + + environment(int argc, char**argv); + + ~environment(); + }; + + class status + { + public: + + status( const MPI_Status & s ); + + int tag() { return _tag; } + int error() { return _error; } + int source() { return _source; } + + private: + int _source; + int _tag; + int _error; + }; + + class communicator + { + public: + + communicator( ); + + ~communicator(); + + int rank(); + + int size(); + + /* + * SEND / RECV INT + */ + void send( int dest, int tag, int n ); + + void recv( int src, int tag, int& n ); + + /* + * SEND / RECV STRING + */ + void send( int dest, int tag, const std::string& str ); + + void recv( int src, int tag, std::string& str ); + + /* + * SEND / RECV Objects + */ + void send( int dest, int tag, const eoserial::Persistent & persistent ); + + template< class T > + void send( int dest, int tag, T* table, int size ) + { + // Puts all the values into an array + eoserial::Array* array = new eoserial::Array; + + for( int i = 0; i < size; ++i ) + { + array->push_back( table[i].pack() ); + } + + // Encapsulates the array into an object + eoserial::Object* obj = new eoserial::Object; + obj->add( "array", array ); + std::stringstream ss; + obj->print( ss ); + delete obj; + + // Sends the object as a string + send( dest, tag, ss.str() ); + } + + void recv( int src, int tag, eoserial::Persistent & persistent ); + + template< class T > + void recv( int src, int tag, T* table, int size ) + { + // Receives the string which contains the object + std::string asText; + recv( src, tag, asText ); + + // Parses the object and retrieves the table + eoserial::Object* obj = eoserial::Parser::parse( asText ); + eoserial::Array* array = static_cast( (*obj)["array"] ); + + // Retrieves all the values from the array + for( int i = 0; i < size; ++i ) + { + eoserial::unpackObject( *array, i, table[i] ); + } + delete obj; + } + + /* + * Other methods + */ + status probe( int src = any_source, int tag = any_tag ); + + void barrier(); + + private: + int _rank; + int _size; + + char* _buf; + int _bufsize; + }; + + void broadcast( communicator & comm, int value, int root ); +} // namespace mpi + +# endif //__EO_MPI_HPP__ diff --git a/eo/src/mpi/implMpi.hpp b/eo/src/mpi/implMpi.hpp deleted file mode 100644 index 4bf71dcc..00000000 --- a/eo/src/mpi/implMpi.hpp +++ /dev/null @@ -1,283 +0,0 @@ -# ifndef __EO_MPI_HPP__ -# define __EO_MPI_HPP__ - -# include -# include - -# include - -namespace mpi -{ - const int any_source = MPI_ANY_SOURCE; - const int any_tag = MPI_ANY_TAG; - - class environment - { - public: - - environment(int argc, char**argv) - { - MPI_Init(&argc, &argv); - } - - ~environment() - { - MPI_Finalize(); - } - }; - - class status - { - public: - - status( const MPI_Status & s ) - { - _source = s.MPI_SOURCE; - _tag = s.MPI_TAG; - _error = s.MPI_ERROR; - } - - int tag() { return _tag; } - int error() { return _error; } - int source() { return _source; } - - private: - int _source; - int _tag; - int _error; - }; - - class communicator - { - public: - - communicator( ) - { - _rank = -1; - _size = -1; - - _buf = 0; - _bufsize = -1; - } - - ~communicator() - { - if( _buf ) - { - delete _buf; - _buf = 0; - } - } - - int rank() - { - if ( _rank == -1 ) - { - MPI_Comm_rank( MPI_COMM_WORLD, &_rank ); - } - return _rank; - } - - int size() - { - if ( _size == -1 ) - { - MPI_Comm_size( MPI_COMM_WORLD, &_size ); - } - return _size; - } - - /* - * SEND / RECV INT - */ - void send( int dest, int tag, int n ) - { - //send( dest, tag, &n, 1 ); - MPI_Send( &n, 1, MPI_INT, dest, tag, MPI_COMM_WORLD ); - } - - void recv( int src, int tag, int& n ) - { - MPI_Status stat; - MPI_Recv( &n, 1, MPI_INT, src, tag, MPI_COMM_WORLD , &stat ); - //recv( src, tag, &n, 1 ); - } - - /* - void send( int dest, int tag, int* table, int size ) - { - MPI_Send( table, size, MPI_INT, dest, tag, MPI_COMM_WORLD ); - } - - void recv( int src, int tag, int* table, int size ) - { - MPI_Status stat; - MPI_Recv( table, size, MPI_INT, src, tag, MPI_COMM_WORLD , &stat ); - } - */ - - /* - * SEND / RECV STRING - */ - void send( int dest, int tag, const std::string& str ) - { - int size = str.size() + 1; - send( dest, tag, size ); - MPI_Send( (char*)str.c_str(), size, MPI_CHAR, dest, tag, MPI_COMM_WORLD); - } - - void recv( int src, int tag, std::string& str ) - { - int size = -1; - MPI_Status stat; - recv( src, tag, size ); - - if( _buf == 0 ) - { - _buf = new char[ size ]; - _bufsize = size; - } else if( _bufsize < size ) - { - delete [] _buf; - _buf = new char[ size ]; - _bufsize = size; - } - MPI_Recv( _buf, size, MPI_CHAR, src, tag, MPI_COMM_WORLD, &stat ); - str.assign( _buf ); - } - - /* - * SEND / RECV Objects - */ - void send( int dest, int tag, const eoserial::Persistent & persistent ) - { - eoserial::Object* obj = persistent.pack(); - std::stringstream ss; - obj->print( ss ); - delete obj; - send( dest, tag, ss.str() ); - } - - /* - void send( int dest, int tag, eoserial::Persistent* table, int size ) - { - // Puts all the values into an array - eoserial::Array* array = new eoserial::Array; - - std::cout << "DEBUG EO: @ premier: " << table << " / @ second: " << table+1 << std::endl; - - for( int i = 0; i < size; ++i ) - { - array->push_back( table[i].pack() ); - } - - // Encapsulates the array into an object - eoserial::Object* obj = new eoserial::Object; - obj->add( "array", array ); - std::stringstream ss; - obj->print( ss ); - delete obj; - - // Sends the object as a string - send( dest, tag, ss.str() ); - } - */ - - template< class T > - void send( int dest, int tag, T* table, int size ) - { - // Puts all the values into an array - eoserial::Array* array = new eoserial::Array; - - for( int i = 0; i < size; ++i ) - { - array->push_back( table[i].pack() ); - } - - // Encapsulates the array into an object - eoserial::Object* obj = new eoserial::Object; - obj->add( "array", array ); - std::stringstream ss; - obj->print( ss ); - delete obj; - - // Sends the object as a string - send( dest, tag, ss.str() ); - } - - - void recv( int src, int tag, eoserial::Persistent & persistent ) - { - std::string asText; - recv( src, tag, asText ); - eoserial::Object* obj = eoserial::Parser::parse( asText ); - persistent.unpack( obj ); - delete obj; - } - - /* - void recv( int src, int tag, eoserial::Persistent* table, int size ) - { - // Receives the string which contains the object - std::string asText; - recv( src, tag, asText ); - - // Parses the object and retrieves the table - eoserial::Object* obj = eoserial::Parser::parse( asText ); - eoserial::Array* array = static_cast( (*obj)["array"] ); - - // Retrieves all the values from the array - for( int i = 0; i < size; ++i ) - { - eoserial::unpackObject( *array, i, table[i] ); - } - delete obj; - } - */ - - template< class T > - void recv( int src, int tag, T* table, int size ) - { - // Receives the string which contains the object - std::string asText; - recv( src, tag, asText ); - - // Parses the object and retrieves the table - eoserial::Object* obj = eoserial::Parser::parse( asText ); - eoserial::Array* array = static_cast( (*obj)["array"] ); - - // Retrieves all the values from the array - for( int i = 0; i < size; ++i ) - { - eoserial::unpackObject( *array, i, table[i] ); - } - delete obj; - } - - /* - * Other methods - */ - status probe( int src = any_source, int tag = any_tag ) - { - MPI_Status stat; - MPI_Probe( src, tag, MPI_COMM_WORLD , &stat ); - return status( stat ); - } - - void barrier() - { - MPI_Barrier( MPI_COMM_WORLD ); - } - - private: - int _rank; - int _size; - - char* _buf; - int _bufsize; - }; - - void broadcast( communicator & comm, int value, int root ); -} // namespace mpi - -# endif //__EO_MPI_HPP__