2017-07-03 29 views
1

私はMPIと並列化する必要がある非常に複雑なプログラムを持っています。私はこれにMPICH3を使用します。MPI structとtypedefで構造体を含む構造体からMPI_Datatypeを作成します

私は、新しい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をどうやって行うことができるか教えてもらえますか? 私の主な問題は、私のMPI_Datatypeにこれをどのようにつなぐことができるのですか?

ありがとうございます! BigIntegerを書き換える chrigi

答えて

1

他の方法は、あなたが私の主な懸念はenum eSignの大きさであるblocklens={1000,1,1}

MPI_Type_create_struct()を使用することができます

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

です。ビッグエンディアンとリトルエンディアンを混在させない場合は、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標準では、enumcharまたは(符号なし)整数型のいずれかであり、特定のサイズの整数を選択するために実装に残ります。したがって、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_SHORTMPI_UNSIGNEDなど)です。符号なしの型が使用されているかどうかを調べるのは難しいかもしれません。この最後の部分は、異種環境で実行する必要のある真に移植可能なMPIプログラムにのみ関連します。異種環境では、MPIによって外部表現へのタイプ変換が実行される可能性があります。同種の環境では、enumは、Gillesの示唆するように、バイトの配列として扱うことができます。

関連する問題