2016-03-08 56 views
4

我正在研究生成C++代碼的編譯器。在如實例:MPI自動類型的廣播變量

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

+0

感謝您指出,做了編輯。 – codeln

+1

現在它不會工作,因爲'auto i'沒有初始化任何東西(這就是編譯時已知的類型) – eduffy

回答

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 
0

你可以嘗試這樣的事:

MPI_Bcast(&i, sizeof(i), MPI_BYTE, 0, MPI_COMM_WORLD); 
+1

這不是一個選項,因爲它完全繞過了MPI類型系統,因此該程序將無法在異構平臺上按預期運行,並且無法使用MUST等工具檢查其是否正確。 –

1

我會建議使用Boost.MPI。它提供了Jonathan Dursi在他們的broadcast(...)模板中解釋的本地MPI類型的抽象概念。 MPI還有很多非常方便的C++抽象。

2

可以使用boost::mpi::get_mpi_datatype(),例如如下:

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()); 
} 

或者,與升壓:

#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); 

對於自定義類型的,這種功能可以很容易地通過以下方式定義

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是一個非常好的和有用的庫,但有時它可以是di如果您使用許多不同的HPC系統並且使用不同的編譯器和不同的MPI實現,則很難使用/維護。上述解決方案的優點是不需要鏈接庫,它只需要包含boost/mpi/datatype.hpp頭文件。