2017-07-03 158 views
1

我有一個相當複雜的程序,我必須與MPI並行。我爲此使用MPICH3。MPI從結構中創建MPI_Datatype包含結構與typedef結構

我知道做一個新MPI_Datatype結合的方式:

typedef struct{ 
    float x; 
    float y; 
    int centroid; 
} point; 
typedef struct{ 
    int csize;//the current size 
    int tsize;//the total size 
    point * data;//the data carried 
} ArrayList; 

const int nfields=3; 
MPI_Aint disps[nfields]; 
int blocklens[] = {1,1,1}; 
MPI_Datatype types[] = {MPI_FLOAT, MPI_FLOAT, MPI_INT}; 

disps[0] = offsetof(point, x); 
disps[1] = offsetof(point, y); 
disps[2] = offsetof(point, centroid); 

MPI_Datatype istruct, pstruct; 
MPI_Type_create_struct(nfields, blocklens, disps, types, &istruct); 
MPI_Type_create_resized(istruct, 0, (char *)&(points[1]) - (char *)(&points[0]), &pstruct); 
MPI_Type_commit(&pstruct); 

但我必須做下面的結構BigInteger的一個MPI_Datatype:

struct mylimb 
{ 
    int x; 
}; 
typedef struct mylimb limb; 
typedef enum eBoolean 
{ 
    FALSE = 0, 
    TRUE, 
} boolean; 

enum eSign 
{ 
    SIGN_POSITIVE = 0, 
    SIGN_NEGATIVE, 
}; 

typedef struct BigInteger 
{ 
    limb limbs[1000]; 
    int nbrLimbs; 
    enum eSign sign; 
} BigInteger; 

的結構被廣泛應用於碼所以我不能簡單地將它改爲更簡單的方法。那麼任何人都可以告訴我如何從BigInteger執行MPI_Datatype? 我的主要問題是肢體這是一個mylimb我怎麼可以連接到我的MPI_Datatype

在此先感謝! chrigi

回答

1

一種其他的方式來改寫BigInteger

typedef struct BigInteger 
{ 
    int limbs[1000]; 
    int nbrLimbs; 
    enum eSign sign; 
} BigInteger; 

所以你可以使用MPI_Type_create_struct()blocklens={1000,1,1}

我主要關注的是enum eSign大小。如果你不混合大端和小端,你可以聲明它作爲MPI_BYTEsizeof(enum eSign)

0

衍生MPI數據類型可以自由嵌套,以創建更加複雜的。沒有什麼能阻止你從創建匹配struct mylimb的MPI數據類型,然後在創建匹配struct BigInteger數據類型的使用它:

MPI_Datatype dt_limb_temp, dt_limb; 
disps[0] = offsetof(limb, x); 
blocklens[0] = 0; 
types[0] = MPI_INT; 
MPI_Type_create_struct(1, blocklens, disps, types, &dt_limb_temp); 
MPI_Type_create_resized(dt_limb_temp, 0, sizeof limb, &dt_limb); 
MPI_Type_free(dt_limb_temp); 

MPI_Datatype dt_biginteger; 
disps[0] = offsetof(BigInteger, limbs); 
disps[1] = offsetof(BigInteger, nbrLimbs); 
disps[2] = offsetof(BigInteger, sign); 
blocklens[0] = 1000; 
blocklens[1] = blocklens[2] = 1; 
types[0] = dt_limbs; 
types[1] = MPI_INT; 
types[2] = dt_esign; 
MPI_Type_create_struct(3, blocklens, disps, types, &dt_biginteger); 
MPI_Type_commit(&dt_biginteger); 

如果添加其他成員struct mylib這會甚至工作。棘手的部分是獲取匹配enum eSign的數據類型dt_esign。 C標準僅規定enum s是char或(無符號)整數類型,並將其留給實現以選擇特定大小的整數。因此,sizeof enum eSign可能因編譯器而異,這意味着將類型固定爲例如MPI_INT將不起作用。 Fortran用戶很幸運,因爲可以使用MPI_Type_match_size來獲取匹配的預定義MPI整數數據類型,因爲它的大小以字節爲單位。在C中,必須遍歷MPI_CHAR,MPI_SHORT,MPI_INT等,並將它們的大小(由MPI_Type_size返回)與sizeof enum eSign進行比較。由於enum的值是非負值,因此該類型很可能是無符號的,即MPI_UNSIGNED_SHORT,MPI_UNSIGNED等。找出是否使用無符號類型可能會非常棘手(不可能?)。最後一部分僅與真正可移植的MPI程序相關,這些程序應該在異構環境中運行,其中可以通過MPI執行與某些外部表示的類型轉換。在一個同類環境中,enum可以被視爲由Gilles建議的一個字節數組。