MPI Broadcast переменная автоматического типа

Я работаю над компилятором, который генерирует код 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; не допускается

4 ответа

Решение

Вы можете использовать шаблоны для возврата необходимой информации:

#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::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 заголовочный файл

Я бы порекомендовал использовать Boost.MPI. Это обеспечивает именно ту абстракцию, которую Джонатан Дурси объясняет в своих broadcast(...) шаблон для родных типов MPI. Есть также еще много очень удобных абстракций C++ для MPI.

Вы можете попробовать что-то вроде этого:

 MPI_Bcast(&i, sizeof(i), MPI_BYTE, 0, MPI_COMM_WORLD);
Другие вопросы по тегам