Merge pull request #78 from Alessandro624/fix-mpi-ale
fix(MPI): resolved cyclic inclusion and MPI issue
This commit is contained in:
commit
3dc2058400
1 changed files with 246 additions and 248 deletions
|
|
@ -22,7 +22,7 @@ Authors:
|
|||
#ifndef __EO_IMPL_MPI_HPP__
|
||||
#define __EO_IMPL_MPI_HPP__
|
||||
|
||||
#include "eoMpi.h"
|
||||
#include <mpi.h>
|
||||
#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 <class T>
|
||||
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<eoserial::Array*>( (*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 <class T>
|
||||
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<eoserial::Array *>((*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__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue