MPI从包含结构和typedef

时间:2017-07-03 19:32:39

标签: types mpi

我有一个非常复杂的程序,我必须与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

2 个答案:

答案 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_BYTEsizeof(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标准仅声明enumchar或(无符号)整数类型,并将其留给实现以选择特定大小的整数。因此,sizeof enum eSign可能因编译器而异,这意味着将类型修改为例如MPI_INT无法工作。 Fortran用户很幸运,因为可以使用MPI_Type_match_size获取匹配的预定义MPI整数数据类型,只要它的大小以字节为单位。在C中,必须迭代MPI_CHARMPI_SHORTMPI_INT等,并将它们的大小(由MPI_Type_size返回)与sizeof enum eSign进行比较。由于enum的值非负值,因此类型很可能是无符号的,即MPI_UNSIGNED_SHORTMPI_UNSIGNED等。查找是否可能很棘手(不可能?)是否使用无符号类型。最后一部分仅适用于应在异构环境中运行的真正可移植的MPI程序,其中MPI可以执行与某些外部表示的类型转换。在同构环境中,enum可以被视为Gilles建议的字节数组。