Reputation: 1348
I'm working on a compiler that generates C++ code. In instances such as:
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if(rank == 0){
auto i = function();
// do something
MPI_Bcast(&i, 1, MPI_INT, 0, MPI_COMM_WORLD);
}
else{
auto i;
MPI_Bcast(&i, 1, MPI_INT, 0, MPI_COMM_WORLD);
cout << i;
}
The type of variable 'i' is determined at compile-time, does MPI have a generic type that allows broadcasting such variables? If not, how do I broadcast such variables? And, how should I recieve such variables since simply declaring auto i;
isn't allowed.
Upvotes: 4
Views: 744
Reputation: 23497
You can use boost::mpi::get_mpi_datatype()
, such as follows:
#include <boost/mpi/datatype.hpp>
...
decltype(function()) i; // or, maybe: typename std::decay<decltype(function())>::type i;
if (rank == 0)
i = function();
auto mdt = boost::mpi::get_mpi_datatype(i);
MPI_Bcast((void*)(&i), 1, mdt, 0, MPI_COMM_WORLD);
For custom types, such a function can be easily defined by the following pattern:
static MPI_Datatype mpi_custom_type; // initialized somewhere
template <typename T>
struct get_mpi_datatype_t;
// specialization for particular types:
template <>
struct get_mpi_datatype_t<unsigned char> {
static const MPI_Datatype value = MPI_UNSIGNED_CHAR;
};
template <>
struct get_mpi_datatype_t<unsigned short> {
static const MPI_Datatype value = MPI_UNSIGNED_SHORT;
};
template <>
struct get_mpi_datatype_t<custom_type> {
static const MPI_Datatype& value = mpi_custom_type;
};
...
template <typename T>
MPI_Datatype get_mpi_datatype(const T& arg) {
return get_mpi_datatype_t<T>::value;
}
template <typename T>
MPI_Datatype get_mpi_datatype() {
return get_mpi_datatype(T());
}
Or, with Boost:
template <typename T>
struct get_mpi_datatype_t {
static const MPI_Datatype value = boost::mpi::get_mpi_datatype<T>();
};
// specialization for custom types only:
template <>
struct get_mpi_datatype_t<custom_type> {
static const MPI_Datatype& value = mpi_custom_type;
};
...
By the way, Boost MPI is a very nice and useful library, but sometimes it can be difficult to use/maintain if you work with many different HPC systems and within them with different compilers and different MPI implementations. The above described solution has the advantage that it does not need to link the boost_mpi
library, it requires only inclusion of the boost/mpi/datatype.hpp
header file.
Upvotes: 2
Reputation: 22670
I would recommend using Boost.MPI. It provides exactly the abstraction that Jonathan Dursi explains in their broadcast(...)
template for native MPI types. There are also many more very convenient C++ abstractions for MPI.
Upvotes: 1
Reputation: 50927
You can use templates to return the information you need:
#include <mpi.h>
#include <iostream>
int function() {
int r;
MPI_Comm_rank(MPI_COMM_WORLD, &r);
return r;
}
struct typecount {
MPI_Datatype mpitype;
int count;
};
template<typename T> typecount gettypecount(T t) { typecount tc={ MPI_BYTE, sizeof(T) }; return tc; };
template<> typecount gettypecount(int t) { typecount tc={ MPI_INT, 1 }; return tc; };
template<> typecount gettypecount(double t) { typecount tc={ MPI_DOUBLE, 1 }; return tc; };
template<> typecount gettypecount(char t) { typecount tc={ MPI_CHAR, 1 }; return tc; };
int main(int argc, char **argv) {
int rank;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0){
auto i = function();
const typecount tmap = gettypecount(i);
MPI_Bcast(&i, tmap.count, tmap.mpitype, 0, MPI_COMM_WORLD);
}
else{
decltype(function()) i = 0;
const typecount tmap = gettypecount(i);
MPI_Bcast(&i, tmap.count, tmap.mpitype, 0, MPI_COMM_WORLD);
std::cout << i << std::endl;
}
MPI_Finalize();
return 0;
}
Running gives:
$ mpicxx -o typetest typetest.cxx --std=c++11 -Wc++11-extensions -Wall
$ mpirun -np 4 ./typetest
0
0
0
Upvotes: 3
Reputation: 40224
You could try something like this:
MPI_Bcast(&i, sizeof(i), MPI_BYTE, 0, MPI_COMM_WORLD);
Upvotes: 0