无法理解MPI_Type_create_struct

时间:2015-11-09 21:51:42

标签: c struct mpi

我无法理解MPI_Type_create_struct方法。假设我们有一个结构:

   struct foo(){
       float value;
       char rank;
   }

我们希望将此结构发送到另一个进程。考虑下面的代码示例:

int count = 2; //number of elements in struct
MPI_Aint offsets[count] = {0, 8};
int blocklengths[count] = {1, 1};
MPI_Datatype types[count] = {MPI_FLOAT, MPI_CHAR};
MPI_Datatype my_mpi_type;

MPI_Type_create_struct(count, blocklengths, offsets, types, &my_mpi_type);

我不确定此示例中的偏移量和块长度是多少。有人可以解释上面这两部分吗?

1 个答案:

答案 0 :(得分:12)

如您所知,MPI_Type_create_struct()的目的是提供一种创建用户MPI_Datatype映射其结构化类型的方法。这些新类型随后可用作MPI通信和其他调用,就像默认类型一样,例如,允许传输结构数组的方式与传输intfloat数组的方式相同。 / p>

现在让我们更详细地看一下这个功能本身 以下是man命令返回的概要:

NAME
   MPI_Type_create_struct -  Create an MPI datatype from a general set of
           datatypes, displacements, and block sizes

SYNOPSIS
   int MPI_Type_create_struct(int count,
                              const int array_of_blocklengths[],
                              const MPI_Aint array_of_displacements[],
                              const MPI_Datatype array_of_types[],
                              MPI_Datatype *newtype)

INPUT PARAMETERS
   count   - number  of  blocks  (integer)  ---  also number of entries
             in arrays array_of_types, array_of_displacements and
             array_of_blocklengths
   array_of_blocklengths
           - number of elements in each block (array of integer)
   array_of_displacements
           - byte displacement of each block (array of address integer)
   array_of_types
           - type of elements in each block (array of handles to datatype
             objects)

OUTPUT PARAMETERS
   newtype - new datatype (handle)

让我们看看输入参数的含义是否需要进一步解释:

  • count:这很清楚,在您的情况下,这将是2
  • array_of_types:嗯,你的例子就是{ MPI_FLOAT, MPI_CHAR }
  • array_of_blocklengths:再说一遍,不多说。这里需要{ 1, 1 }
  • array_of_displacements:这是你必须要小心一点的。它对应于从结构起点到array_of_types中列出的每个元素的地址的内存地址偏移量。在您的情况下,这类似{ &f.value - &f, &f.rank - &f }f类型为foo。这里棘手的部分是,由于潜在的对齐约束,你无法确定它是否等于{ 0, sizeof( float ) }(尽管在这里我很确定它会是)。因此,如图所示使用地址偏移使得该方法完全可移植。此外(thx Hristo Iliev指向我)你可以(并且应该)使用来自offsetof()的{​​{1}}宏来完成这个指针算术,将代码简化为{{1看起来更好。

通过这种方式初始化参数,对stddef.h的调用将返回一个新的{ offsetof( foo, value ), offsetof( foo, rank ) },适用于发送或接收一个 MPI_Type_create_struct() at时间。原因是这种新类型没有考虑结构的实际范围,包括其字段的对齐约束。你的例子在这方面是完美的,因为它(很可能)是空心的。

原因是MPI_Datatype通常具有32b的对齐约束,而foo s没有。因此,主题数组的第二个结构float的起始地址不在第一个结尾。它位于下一个32b对齐的内存地址。这将使我们在结构元素的结尾与数组中下一个元素的开头之间留下3个字节的洞。

要处理此问题,您必须调整类型大小,以便使用char进行扩展,其大纲如下:

foo

使用它非常简单,因为MPI_Type_create_resized()NAME MPI_Type_create_resized - Create a datatype with a new lower bound and extent from an existing datatype SYNOPSIS int MPI_Type_create_resized(MPI_Datatype oldtype, MPI_Aint lb, MPI_Aint extent, MPI_Datatype *newtype) INPUT PARAMETERS oldtype - input datatype (handle) lb - new lower bound of datatype (address integer) extent - new extent of datatype (address integer) OUTPUT PARAMETERS newtype - output datatype (handle) 都可以通过直接调用专门用于此目的的函数来检索,即lb(但实际上,您也可以直接使用extendMPI_Type_get_extent())。此外,由于用于调用0sizeof( foo )的中间类型未在任何实际MPI通信中使用,因此不需要使用MPI_Type_get_extent()提交,从而节省了一些调用和时间。

现在,您的代码变为:

MPI_Type_create_resized()