From 77148b5a972fb76cfc66a4ed3cbbc72ce1440d9e Mon Sep 17 00:00:00 2001 From: Alessandro Sidero <75628365+Alessandro624@users.noreply.github.com> Date: Mon, 24 Feb 2025 19:07:10 +0100 Subject: [PATCH] fix(MPI): resolved cyclic inclusion and MPI issue --- eo/src/mpi/implMpi.h | 474 +++++++++++++++++++++---------------------- 1 file changed, 236 insertions(+), 238 deletions(-) diff --git a/eo/src/mpi/implMpi.h b/eo/src/mpi/implMpi.h index d52b84b26..0efb89a75 100644 --- a/eo/src/mpi/implMpi.h +++ b/eo/src/mpi/implMpi.h @@ -22,7 +22,7 @@ Authors: #ifndef __EO_IMPL_MPI_HPP__ #define __EO_IMPL_MPI_HPP__ -#include "eoMpi.h" +#include #include "../serial/eoSerial.h" /** @@ -43,290 +43,288 @@ Authors: */ namespace eo { -namespace mpi -{ - /** - * @ingroup Parallel - * @{ - */ - - /** - * @brief Constant indicating that a message can come from any process. - */ - extern const int any_source; - - /** - * @brief Constant indicating that a message can come from any tag (channel). - */ - extern const int any_tag; - - /** - * @brief Wrapper class to have a MPI environment. - * - * Instead of calling MPI_Init and MPI_Finalize, it is only necessary to instantiate - * this class once, in the global context. - */ - class environment + namespace mpi { - public: + /** + * @ingroup Parallel + * @{ + */ /** - * @brief Inits MPI context. + * @brief Constant indicating that a message can come from any process. + */ + extern const int any_source; + + /** + * @brief Constant indicating that a message can come from any tag (channel). + */ + extern const int any_tag; + + /** + * @brief Wrapper class to have a MPI environment. * - * @param argc Number of params in command line (same as one in main) - * @param argv Strings containing params (same as one in main) + * Instead of calling MPI_Init and MPI_Finalize, it is only necessary to instantiate + * this class once, in the global context. */ - environment(int argc, char**argv); - - /** - * @brief Closes MPI context. - */ - ~environment(); - }; - - struct MPI_Status { - int count; - int cancelled; - int MPI_SOURCE; - int MPI_TAG; - int MPI_ERROR; - }; - - /** - * @brief Wrapper class for MPI_Status - * - * Consists only in a C++ wrapper class, giving getters on status attributes. - */ - class status - { + class environment + { public: + /** + * @brief Inits MPI context. + * + * @param argc Number of params in command line (same as one in main) + * @param argv Strings containing params (same as one in main) + */ + environment(int argc, char **argv); + + /** + * @brief Closes MPI context. + */ + ~environment(); + }; + + /* struct MPI_Status + { + int count; + int cancelled; + int MPI_SOURCE; + int MPI_TAG; + int MPI_ERROR; + }; */ /** - * @brief Converts a MPI_Status into a status. + * @brief Wrapper class for MPI_Status + * + * Consists only in a C++ wrapper class, giving getters on status attributes. */ - status( const MPI_Status & s ); + class status + { + public: + /** + * @brief Converts a MPI_Status into a status. + */ + status(const MPI_Status &s); - /** - * @brief Returns the tag of the associated communication. - */ - int tag() { return _tag; } + /** + * @brief Returns the tag of the associated communication. + */ + int tag() { return _tag; } - /** - * @brief Indicates which error number we obtained in the associated communication. - */ - int error() { return _error; } + /** + * @brief Indicates which error number we obtained in the associated communication. + */ + int error() { return _error; } - /** - * @brief Returns the MPI rank of the source of the associated communication. - */ - int source() { return _source; } + /** + * @brief Returns the MPI rank of the source of the associated communication. + */ + int source() { return _source; } private: int _source; int _tag; int _error; - }; + }; - /** - * @brief Main object, used to send / receive messages, get informations about the rank and the size of the world, - * etc. - */ - class communicator - { + /** + * @brief Main object, used to send / receive messages, get informations about the rank and the size of the world, + * etc. + */ + class communicator + { public: + /** + * Creates the communicator, using the whole world as a MPI_Comm. + * + * @todo Allow the user to precise which MPI_Comm to use + */ + communicator(); - /** - * Creates the communicator, using the whole world as a MPI_Comm. - * - * @todo Allow the user to precise which MPI_Comm to use - */ - communicator( ); + ~communicator(); - ~communicator(); + /** + * @brief Returns the MPI rank of the current process. + */ + int rank(); - /** - * @brief Returns the MPI rank of the current process. - */ - int rank(); + /** + * @brief Returns the size of the MPI cluster. + */ + int size(); - /** - * @brief Returns the size of the MPI cluster. - */ - int size(); + /* + * SEND / RECV INT + */ - /* - * SEND / RECV INT - */ + /** + * @brief Sends an integer to dest on channel "tag". + * + * @param dest MPI rank of the receiver + * @param tag MPI tag of message + * @param n The integer to send + */ + void send(int dest, int tag, int n); - /** - * @brief Sends an integer to dest on channel "tag". - * - * @param dest MPI rank of the receiver - * @param tag MPI tag of message - * @param n The integer to send - */ - void send( int dest, int tag, int n ); + /* + * @brief Receives an integer from src on channel "tag". + * + * @param src MPI rank of the sender + * @param tag MPI tag of message + * @param n Where to save the received integer + */ + void recv(int src, int tag, int &n); - /* - * @brief Receives an integer from src on channel "tag". - * - * @param src MPI rank of the sender - * @param tag MPI tag of message - * @param n Where to save the received integer - */ - void recv( int src, int tag, int& n ); + /* + * SEND / RECV STRING + */ - /* - * SEND / RECV STRING - */ + /** + * @brief Sends a string to dest on channel "tag". + * + * @param dest MPI rank of the receiver + * @param tag MPI tag of message + * @param str The std::string to send + */ + void send(int dest, int tag, const std::string &str); - /** - * @brief Sends a string to dest on channel "tag". - * - * @param dest MPI rank of the receiver - * @param tag MPI tag of message - * @param str The std::string to send - */ - void send( int dest, int tag, const std::string& str ); + /* + * @brief Receives a string from src on channel "tag". + * + * @param src MPI rank of the sender + * @param tag MPI tag of message + * @param std::string Where to save the received string + */ + void recv(int src, int tag, std::string &str); - /* - * @brief Receives a string from src on channel "tag". - * - * @param src MPI rank of the sender - * @param tag MPI tag of message - * @param std::string Where to save the received string - */ - void recv( int src, int tag, std::string& str ); + /* + * SEND / RECV Objects + */ - /* - * SEND / RECV Objects - */ + /** + * @brief Sends an eoserial::Persistent to dest on channel "tag". + * + * @param dest MPI rank of the receiver + * @param tag MPI tag of message + * @param persistent The object to send (it must absolutely implement eoserial::Persistent) + */ + void send(int dest, int tag, const eoserial::Persistent &persistent); - /** - * @brief Sends an eoserial::Persistent to dest on channel "tag". - * - * @param dest MPI rank of the receiver - * @param tag MPI tag of message - * @param persistent The object to send (it must absolutely implement eoserial::Persistent) - */ - void send( int dest, int tag, const eoserial::Persistent & persistent ); - - /** - * @brief Sends an array of eoserial::Persistent to dest on channel "tag". - * - * @param dest MPI rank of the receiver - * @param tag MPI tag of message - * @param table The array of eoserial::Persistent objects - * @param size The number of elements to send (no check is done, the user has to be sure that the size won't - * overflow!) - */ - 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 ) + /** + * @brief Sends an array of eoserial::Persistent to dest on channel "tag". + * + * @param dest MPI rank of the receiver + * @param tag MPI tag of message + * @param table The array of eoserial::Persistent objects + * @param size The number of elements to send (no check is done, the user has to be sure that the size won't + * overflow!) + */ + template + void send(int dest, int tag, T *table, int size) { - array->push_back( table[i].pack() ); + // 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()); } - // Encapsulates the array into an object - eoserial::Object* obj = new eoserial::Object; - obj->add( "array", array ); - std::stringstream ss; - obj->print( ss ); - delete obj; + /* + * @brief Receives an eoserial::Persistent object from src on channel "tag". + * + * @param src MPI rank of the sender + * @param tag MPI tag of message + * @param persistent Where to unpack the serialized object? + */ + void recv(int src, int tag, eoserial::Persistent &persistent); - // Sends the object as a string - send( dest, tag, ss.str() ); - } - - /* - * @brief Receives an eoserial::Persistent object from src on channel "tag". - * - * @param src MPI rank of the sender - * @param tag MPI tag of message - * @param persistent Where to unpack the serialized object? - */ - void recv( int src, int tag, eoserial::Persistent & persistent ); - - /* - * @brief Receives an array of eoserial::Persistent from src on channel "tag". - * - * @param src MPI rank of the sender - * @param tag MPI tag of message - * @param table The table in which we're saving the received objects. It must have been allocated by the user, - * as no allocation is performed here. - * @param size The number of elements to receive (no check is done, the user has to be sure that the size won't - * overflow!) - */ - 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 ) + /* + * @brief Receives an array of eoserial::Persistent from src on channel "tag". + * + * @param src MPI rank of the sender + * @param tag MPI tag of message + * @param table The table in which we're saving the received objects. It must have been allocated by the user, + * as no allocation is performed here. + * @param size The number of elements to receive (no check is done, the user has to be sure that the size won't + * overflow!) + */ + template + void recv(int src, int tag, T *table, int size) { - eoserial::unpackObject( *array, i, table[i] ); + // 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; } - delete obj; - } - /* - * Other methods - */ + /* + * Other methods + */ - /** - * @brief Wrapper for MPI_Probe - * - * Waits for a message to come from process having rank src, on the channel - * tag. - * - * @param src MPI rank of the sender (any_source if it can be any sender) - * @param tag MPI tag of the expected message (any_tag if it can be any tag) - */ - status probe( int src = any_source, int tag = any_tag ); + /** + * @brief Wrapper for MPI_Probe + * + * Waits for a message to come from process having rank src, on the channel + * tag. + * + * @param src MPI rank of the sender (any_source if it can be any sender) + * @param tag MPI tag of the expected message (any_tag if it can be any tag) + */ + status probe(int src = any_source, int tag = any_tag); - /** - * @brief Wrapper for MPI_Barrier - * - * - */ - void barrier(); + /** + * @brief Wrapper for MPI_Barrier + * + * + */ + void barrier(); private: int _rank; int _size; - char* _buf; // temporary buffer for sending and receiving strings. Avoids reallocations + char *_buf; // temporary buffer for sending and receiving strings. Avoids reallocations int _bufsize; // size of the above temporary buffer - }; + }; - /** - * @brief Wrapper for MPI_Bcast - * - * Broadcasts an integer value on the communicator comm, from the process having the MPI rank root. - * - * @param comm The communicator on which to broadcast - * @param value The integer value to send - * @param root The MPI rank of the broadcaster - * - * @todo Actually comm isn't used and broadcast is performed on the whole MPI_COMM_WORLD. TODO: Use comm instead - */ - void broadcast( communicator & comm, int value, int root ); + /** + * @brief Wrapper for MPI_Bcast + * + * Broadcasts an integer value on the communicator comm, from the process having the MPI rank root. + * + * @param comm The communicator on which to broadcast + * @param value The integer value to send + * @param root The MPI rank of the broadcaster + * + * @todo Actually comm isn't used and broadcast is performed on the whole MPI_COMM_WORLD. TODO: Use comm instead + */ + void broadcast(communicator &comm, int value, int root); - /** - * @} - */ -} // namespace mpi + /** + * @} + */ + } // namespace mpi } // namespace eo -# endif //__EO_IMPL_MPI_HPP__ +#endif //__EO_IMPL_MPI_HPP__