自动类型的 MPI 广播变量
MPI Broadcast variable of auto type
我正在研究生成 C++ 代码的编译器。在以下情况下:
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;
}
变量'i'的类型是在编译时确定的,MPI是否有允许广播此类变量的通用类型?如果没有,我该如何广播这些变量?而且,我应该如何接收这些变量,因为不允许简单地声明 auto i;
。
您可以尝试这样的操作:
MPI_Bcast(&i, sizeof(i), MPI_BYTE, 0, MPI_COMM_WORLD);
您可以使用模板return您需要的信息:
#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;
}
运行 给出:
$ mpicxx -o typetest typetest.cxx --std=c++11 -Wc++11-extensions -Wall
$ mpirun -np 4 ./typetest
0
0
0
我建议使用 Boost.MPI。它准确地提供了 Jonathan Dursi 在其 broadcast(...)
模板中针对本机 MPI 类型所解释的抽象。还有很多更方便的 MPI C++ 抽象。
可以使用boost::mpi::get_mpi_datatype()
,例如:
#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);
对于自定义类型,可以通过以下模式轻松定义此类函数:
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());
}
或者,使用 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;
};
...
顺便说一句,Boost MPI 是一个非常好用且有用的库,但有时如果您使用许多不同的 HPC 系统并且在这些系统中使用不同的编译器和不同的 MPI 实现,那么 use/maintain 可能很难 use/maintain。上述解决方案的优点是不需要 link boost_mpi
库,它只需要包含 boost/mpi/datatype.hpp
头文件。
我正在研究生成 C++ 代码的编译器。在以下情况下:
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;
}
变量'i'的类型是在编译时确定的,MPI是否有允许广播此类变量的通用类型?如果没有,我该如何广播这些变量?而且,我应该如何接收这些变量,因为不允许简单地声明 auto i;
。
您可以尝试这样的操作:
MPI_Bcast(&i, sizeof(i), MPI_BYTE, 0, MPI_COMM_WORLD);
您可以使用模板return您需要的信息:
#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;
}
运行 给出:
$ mpicxx -o typetest typetest.cxx --std=c++11 -Wc++11-extensions -Wall
$ mpirun -np 4 ./typetest
0
0
0
我建议使用 Boost.MPI。它准确地提供了 Jonathan Dursi 在其 broadcast(...)
模板中针对本机 MPI 类型所解释的抽象。还有很多更方便的 MPI C++ 抽象。
可以使用boost::mpi::get_mpi_datatype()
,例如:
#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);
对于自定义类型,可以通过以下模式轻松定义此类函数:
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());
}
或者,使用 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;
};
...
顺便说一句,Boost MPI 是一个非常好用且有用的库,但有时如果您使用许多不同的 HPC 系统并且在这些系统中使用不同的编译器和不同的 MPI 实现,那么 use/maintain 可能很难 use/maintain。上述解决方案的优点是不需要 link boost_mpi
库,它只需要包含 boost/mpi/datatype.hpp
头文件。