// This file contains wrappers for MPI routines and functions to pack/unpack data structures #ifndef MPI_WRAPPERS_INC #define MPI_WRAPPERS_INC #include #include #include #include #ifdef USE_MPI // Inlcude MPI #include "mpi.h" #else // Create fake MPI types typedef int MPI_Comm; typedef int MPI_Request; typedef int MPI_Status; #define MPI_COMM_WORLD 0 #define MPI_COMM_SELF 0 #define MPI_COMM_NULL -1 #define MPI_GROUP_NULL -2 #define MPI_STATUS_IGNORE NULL enum MPI_Datatype { MPI_LOGICAL, MPI_CHAR, MPI_UNSIGNED_CHAR, MPI_INT, MPI_UNSIGNED, MPI_LONG, MPI_UNSIGNED_LONG, MPI_LONG_LONG, MPI_FLOAT, MPI_DOUBLE }; enum MPI_Op { MPI_MIN, MPI_MAX, MPI_SUM }; typedef int MPI_Group; #define MPI_THREAD_SINGLE 0 #define MPI_THREAD_FUNNELED 1 #define MPI_THREAD_SERIALIZED 2 #define MPI_THREAD_MULTIPLE 3 // Fake MPI functions int MPI_Init(int*,char***); int MPI_Init_thread( int *argc, char ***argv, int required, int *provided ); int MPI_Finalize(); int MPI_Comm_size( MPI_Comm, int *size ); int MPI_Comm_rank( MPI_Comm, int *rank ); int MPI_Barrier(MPI_Comm); int MPI_Wait(MPI_Request*,MPI_Status*); int MPI_Waitall(int,MPI_Request[],MPI_Status[]); int MPI_Bcast(void*,int,MPI_Datatype,int,MPI_Comm); int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm); int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status); int MPI_Isend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request); int MPI_Irecv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request *request); int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm); int MPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm); int MPI_Allgatherv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, const int *recvcounts, const int *displs, MPI_Datatype recvtype, MPI_Comm comm); int MPI_Sendrecv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, int dest, int sendtag, void *recvbuf, int recvcount, MPI_Datatype recvtype, int source, int recvtag, MPI_Comm comm, MPI_Status *status); int MPI_Reduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm); double MPI_Wtime( void ); int MPI_Comm_group(MPI_Comm comm, MPI_Group *group); int MPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm *newcomm); int MPI_Comm_free(MPI_Comm *group); int MPI_Group_free(MPI_Group *group); int MPI_Comm_dup(MPI_Comm comm, MPI_Comm *newcomm); #endif //! Get the size of the MPI_Comm // Note: this is a thread and interrupt safe function inline int comm_size( MPI_Comm comm ) { int size = 1; MPI_Comm_size( comm, &size ); return size; } //! Get the rank of the MPI_Comm // Note: this is a thread and interrupt safe function inline int comm_rank( MPI_Comm comm ) { int rank = 1; MPI_Comm_rank( comm, &rank ); return rank; } //! Get the size of MPI_COMM_WORLD inline int MPI_WORLD_SIZE( ) { return comm_size( MPI_COMM_WORLD ); } //! Get the size of MPI_COMM_WORLD inline int MPI_WORLD_RANK( ) { return comm_rank( MPI_COMM_WORLD ); } //! Return the appropriate MPI datatype for a class template MPI_Datatype getMPItype(); //! Template function to return the buffer size required to pack a class template size_t packsize( const TYPE& rhs ); //! Template function to pack a class to a buffer template void pack( const TYPE& rhs, char *buffer ); //! Template function to unpack a class from a buffer template void unpack( TYPE& data, const char *buffer ); //! Template function to return the buffer size required to pack a std::vector template size_t packsize( const std::vector& rhs ); //! Template function to pack a class to a buffer template void pack( const std::vector& rhs, char *buffer ); //! Template function to pack a class to a buffer template void unpack( std::vector& data, const char *buffer ); //! Template function to return the buffer size required to pack a std::pair template size_t packsize( const std::pair& rhs ); //! Template function to pack a class to a buffer template void pack( const std::pair& rhs, char *buffer ); //! Template function to pack a class to a buffer template void unpack( std::pair& data, const char *buffer ); //! Template function to return the buffer size required to pack a std::map template size_t packsize( const std::map& rhs ); //! Template function to pack a class to a buffer template void pack( const std::map& rhs, char *buffer ); //! Template function to pack a class to a buffer template void unpack( std::map& data, const char *buffer ); //! Template function to return the buffer size required to pack a std::set template size_t packsize( const std::set& rhs ); //! Template function to pack a class to a buffer template void pack( const std::set& rhs, char *buffer ); //! Template function to pack a class to a buffer template void unpack( std::set& data, const char *buffer ); // Helper functions inline float sumReduce( MPI_Comm comm, float x ) { float y = 0; MPI_Allreduce(&x,&y,1,MPI_FLOAT,MPI_SUM,comm); return y; } inline int sumReduce( MPI_Comm comm, int x ) { int y = 0; MPI_Allreduce(&x,&y,1,MPI_INT,MPI_SUM,comm); return y; } inline bool sumReduce( MPI_Comm comm, bool x ) { int y = sumReduce( comm, x?1:0 ); return y>0; } inline std::vector sumReduce( MPI_Comm comm, const std::vector& x ) { auto y = x; MPI_Allreduce(x.data(),y.data(),x.size(),MPI_FLOAT,MPI_SUM,comm); return y; } inline std::vector sumReduce( MPI_Comm comm, const std::vector& x ) { auto y = x; MPI_Allreduce(x.data(),y.data(),x.size(),MPI_INT,MPI_SUM,comm); return y; } inline float maxReduce( MPI_Comm comm, float x ) { float y = 0; MPI_Allreduce(&x,&y,1,MPI_FLOAT,MPI_MAX,comm); return y; } #endif #include "common/MPI_Helpers.hpp"