微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

无法理解MPI_Type_create_struct

我无法理解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);

我不确定在这个例子中做什么偏移和块长度.有人可以解释上面这两部分吗?

解决方法

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

现在让我们更详细地看一下函数本身.
以下是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)

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

>伯爵:这很清楚,在你的情况下,那将是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指向我)你可以(并且应该)使用stddef.h中的offsetof()宏来完成这个指针算法,将代码简化为{offsetof(foo,value),offsetof(foo),排名)}看起来更好.

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

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

要处理此问题,您必须调整类型大小以使用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和extend,即MPI_Type_get_extent()(但实际上,您也可以直接使用0和sizeof(foo)).此外,由于用于调用MPI_Type_get_extent()和MPI_Type_create_resized()的中间类型未在任何实际MPI通信中使用,因此不需要使用MPI_Type_commit()提交,从而节省了一些调用和时间.

现在,通过它,您的代码变为:

int count = 2;
int array_of_blocklengths[] = { 1,1 };
MPI_Aint array_of_displacements[] = { offsetof( foo,value ),offsetof( foo,rank ) };
MPI_Datatype array_of_types[] = { MPI_FLOAT,MPI_CHAR };
MPI_Datatype tmp_type,my_mpi_type;
MPI_Aint lb,extent;

MPI_Type_create_struct( count,array_of_blocklengths,array_of_displacements,array_of_types,&tmp_type );
MPI_Type_get_extent( tmp_type,&lb,&extent );
MPI_Type_create_resized( tmp_type,lb,extent,&my_mpi_type );
MPI_Type_commit( &my_mpi_type );

原文地址:https://www.jb51.cc/c/118640.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐