C++ Boost - Mpi boostMPI20180509
C++ Boost - Mpi boostMPI20180509
The C++ Boost library has considerably extended the capabilities of such basic C++ components as
the Standard Library. Over the years much of this functionality has been integrated into new versions
of the language. Of particular interest for the HPC community is the Boost MPI library. It provides an
object-oriented interface to MPI allowing the programmer to concentrate on the parallel architecture
rather than the implementation details of packing and sending data.
I’m still learning Boost MPI but I’ll review some of the capabilities and give a few simple examples
illustrating the basic functionality. It looks very nice to me, and indeed seems to be resulting in
significantly cleaner code with essentially no performance penalty.
Overview
2011 c++11 Core: multithreading, generic programming, uniform initialization and performance. Gnu full support
Significant updates to the C++ Standard Library based on the Standard Template
Library. Included performance requirements.
Useful things like “auto” and lambda functions.
2014 c++14 Bug fixes and minor extras. Gnu full support
2017 c++17 Started to remove deprecated features (trigraphs, auto_ptr, ..) Gnu full support
A lot of additional detail capabilities.
“It’s not what a language allows you to do, but what it encourages you to do.”
And then MPI-3 came along and no-one felt like adding the C++
bindings.
● SO: MPI-3 does not include the old C++ bindings.
Boost Compiling & Linking
Just use the MPI scripts: mpiCC and mpirun
● of course MPI needs to be installed.
Need to link boost libraries both before and after the object file.
● Anyone else having this problem? (Using gnu c++ and OpenMPI on a Mint linux box)
CPPFLAGS = -std=c++11
CXX = mpiCC
LDFLAGS = -lboost_mpi -lboost_serialization
%: %.cpp
$(CXX) $(CPPFLAGS) $(LDFLAGS) [email protected] $(LDFLAGS) -o $@
int main()
{
mpi::environment env {};
mpi::communicator world;
int rank = world.rank();
int tag = 31; // always tag the messages
int master = 0;
if( rank == master ){
int i;
world.recv( mpi::any_source, tag, i ); // receive whichever comes in first
cout << "received from " << i << '\n';
} else {
world.send( master, tag, rank ); // send rank (integer) to master
}
}
Classic MPI send/receive
if( rank == sender ){
As usual need to
char* msg = (char *) "Message from sender"; package up the
int n_msg = strlen(msg) + 1; data, send a byte
stream, and then
MPI_Send( &n_msg, 1, MPI_INT, receiver, tag, MPI_COMM_WORLD ); un-package.
MPI_Send( msg, n_msg, MPI_CHAR, receiver, tag, MPI_COMM_WORLD );
} else if( rank == receiver ){
Careful with
int n_msg;
memory
MPI_Recv( &n_msg, 1, MPI_INT, sender, tag, MPI_COMM_WORLD, &status ); management, null
char* msg = new char[n_msg+1]; terminator, …
MPI_Recv( msg, n_msg, MPI_CHAR, sender, tag, MPI_COMM_WORLD, &status );
msg[n] = ‘\0’; Very bug-prone
approach, and
cerr << "send1: " << rank << "(receiver): received message \""
<< msg << "\"\n"; hard to debug.
Delete[] msg; // remember to delete temp variables
}
Boost Send String
Boost MPI handles classes/objects: does it’s own packing and unpacking.
#include <boost/mpi.hpp>
namespace mpi = boost::mpi;
string Serialize(){
const char DELIMITER = ' ';
stringstream s;
s << i << DELIMITER << a << DELIMITER << desc;
return s.str();
}
class TestClass Still need to serialize, but use the built-in Boost
{ serialization templates.
private: No need to explicitly write formatters or constructors.
int i; double a; string desc;
public:
TestClass();
...
vector<vector<double>> chunk_vec;
if( rank == 0 ){
cout << "vec_norm " << rank << ": master scattering chunks with stride="
<< stride << " n_processors=" << n_processors << endl;
if( rank == scatter_process ){ // send my sum back, and receive all sums
vector<double> chunk_sums;
mpi::gather( world, sum, chunk_sums, scatter_process );
return vec_sum( chunk_sums ); // sum the chunk sums (no parallelization)
● Note that the rank within the local communicator starts at 0. So each message is sent from local
processor 0 to the processors in that local communicator
Boost MPI Functionality
Pretty complete!
● Non-blocking/asynchronous
○ irecv(..), isend(..), wait_all(..), test(..)
● Status
● Reduce(..): takes a function to analyze data
○ All_reduce
● Broadcast
● Multiple communicators and processor groups.
Timing and Performance