目录
前面各节介绍的MPI程序设计都是发送或接收连续的数据,其实MPI还可以处理不连续的数据,基本方法有两种:1、允许用户自定义新的数据类型(又称派生数据类型);2、数据的打包与解包,即在发送方将不连续的数据打包到连续的区域,然后发送出去,在接收方将打包后的连续数据解包到不连续的存储空间。
一、派生数据类型
前面各节介绍的通信只涉及相同数据类型的相邻缓冲区,这对两种用户限制太大:1、经常想传送含有不同数据类型值的消息的用户(例如一个整数计数值加一些实数);2、经常发送非连续数据的用户(例如发送矩阵的一个子块)。一种解决办法是在发送端把非连续的数据打包到一个连续的缓冲区,在接收端再解包。这样做的缺点在于两端都需要额外的内存到内存拷贝操作,甚至当通信域系统具有收集分散数据功能时也是如此。
在介绍派生数据类型前,我们先了解一种通用的数据类型描述方法——类型图。使用类型图可以用比较精确和形式化的方法来描述各种各样的类型。类型图是一系列二元组的集合,两个数据类型是否相同取决于它们的类型图是否相同。类型图的二元组如下:
基类型指出了该类型图中包括哪些基本的数据类型,而偏移则指出该基类型在整个类型图中的起始位置。基类型可以是预定义类型或派生类型,偏移可正可负,没有递增或递减的顺序要求。一个类型图中包括的所有基类型的集合称为某类型的类型表,表示为:
类型表={基类型0,……,基类型n-1}
将类型图和一个数据缓冲区的基地址结合起来,可以说明一个通信缓冲区内的数据分布情况。
预定义数据类型是通用数据类型的特例,比如MPI_INT是一个预定义的数据类型句柄,其类型图为{(int, 0)},有一个基类型入口项int和偏移0。其它的基本数据类型与此相似。数据类型的跨度被定义为该数据类型的类型图中从第一个基类型到最后一个基类型之间的距离。如果某一个类型的类型图为
则该类型图的下界定义为:
该类型图的上界定义为:
该类型图的跨度定义为:
由于不同的类型有不同的对齐位置要求,就是能够使类型图的跨度满足该类型的类型表中的所有的类型都能达到下一个对齐要求所需要的最小非负整数值。假设(一个double型的值在偏移0,后面在偏移8处跟一个字符值)。进一步假设double型的值必须严格分配到地址为8的倍数的存储空间,则该数据类型的extent是16(从9循环到下一个8的倍数)。一个由一个字符后面紧跟一个双精度的数据类型,其extent也是16。
二、定义新数据类型
1、连续复制的类型生成
最简单的数据类型生成器是MPI_TYPE_CONTIGUOUS,它得到的新类型是将一个已有的数据类型按照顺序依次连续进行复制后的结果。
MPI_TYPE_CONTIGUOUS(count, oldtype, newtype)
IN count 复制个数(非负整数)
IN oldtype 旧数据类型(句柄)
OUT newtype 新数据类型(句柄)
//c语言的说明
int MPI_Type_contiguous(int count, MPI_Datatype oldtype, MPI_Datatype *newtype)
//Fortran语言的说明
MPI_TYPE_CONTIGUOUS(COUNT, OLDTYPE, NEWTYPE, IERROR)
INTEGER COUNT, OLDTYPE, NEWTYPE, IERROR
用MPI_TYPE_CONTIGUOUS构造新的数据类型,设原来的数据类型oldtype的类型图为{(double, 0), (char, 8)},其中类型的跨度为extent=16,对旧类型重复的次数count=3,则newtype返回的新类型的类型图为
更加通用的表达为,设旧类型oldtype的类型图为
,其类型的跨度extent=ex。
新类型将旧类型连续复制count次,则新类型newtype的类型图为</