我有一个非常复杂的程序,我必须与MPI并行。我使用MPICH3。
我知道如何制作新的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);
但我必须执行以下struct 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
答案 0 :(得分: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_BYTE
和sizeof(enum eSign)
答案 1 :(得分: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
,这也会有效。棘手的部分是获取与dt_esign
匹配的数据类型enum eSign
。 C标准仅声明enum
是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建议的字节数组。