MPI广播自动类型变量

4

我正在开发一款生成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;是不允许的,所以我应该如何接收这些变量。


1
实际上,i类型编译时 就已知。 - Bathsheba
感谢指出,已进行修改。 - Nitin Labhishetty
1
现在它不起作用,因为auto i没有被初始化为任何值(这就是为什么类型在编译时已知) - eduffy
没错!在 else 块内声明 i 的解决方案是什么? - Nitin Labhishetty
i的类型是function()的返回类型。 - eduffy
1
在 else 块中,使用 decltype(function()) i;。例如,auto mdt = boost::mpi::get_mpi_datatype(i);MPI_Bcast((void*)(&i),..., mdt, ...); 结合使用(详见我的答案)。 - Daniel Langr
4个回答

3
您可以使用模板来返回所需的信息:
#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

2
您可以使用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 实现,那么有时可能会很难使用/维护。上述解决方案的优点在于它不需要链接 boost_mpi 库,只需要包含 boost/mpi/datatype.hpp 头文件即可。

1
我建议使用Boost.MPI。它提供了Jonathan Dursi在其原生MPI类型的broadcast(...)模板中所解释的抽象。此外,还有许多非常方便的C++抽象用于MPI。

0
你可以尝试这样做:
 MPI_Bcast(&i, sizeof(i), MPI_BYTE, 0, MPI_COMM_WORLD);

1
这不是一个选项,因为它完全绕过了MPI类型系统,因此程序在异构平台上无法按预期运行,并且无法使用MUST等工具检查其正确性。 - Hristo Iliev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接