发件人和收件人的MPI_Datatype类型不同
使用MPI,可以使用从相同基本类型派生并具有相同总长度的不同MPI_Datatype来发送和接收数据吗?
考虑两个MPI进程A和B. A有一个数组double a[n]
, B有一个数组double b[m]
。 两个进程都知道A想要发送以某种方式分布在a
B k
双精度(只有A知道这个分布)。 B (并且只有B )知道它想如何在b
排列k
双打。 因此,两者都创建(通过MPI_Type_indexed
和MPI_Type_commit
)数据类型,对于A ,它对应于它想要从a
发送的元素,对于B ,它对应于它想要将这些元素保存到b
。 A调用MPI_Isend(a, 1, A_datatype, ...)
和B调用MPI_Irecv(b, 1, B_datatype, ...)
。
这有用吗? 如果是,这是解决手头问题的标准方法吗? 如果不是,这种数据交换如何通常完成?
是的,它有效,而且这是解决它的标准方法。
数据类型只是如何在发送方打包数据的指令 ,以及如何在接收方解包它们的说明。
这是一个非常有用且非常标准的MPI-IO方法。
匹配发送和接收操作中的MPI类型必须是一致的 。 一致性是一种较弱的等价forms。 这意味着两种数据类型可能不相等,但它们的类型签名必须匹配。
每个MPI数据类型都是表单中的元组列表(offset[i], basic_type[i])
,其中offset[i]
是从数据缓冲区的开头以字节为单位的第i
个项的偏移量(也可能是negative)和basic_type[i]
是项目的语言数据类型。 这些元组的列表称为类型映射。 仅基本类型列表称为类型的签名。
想象一下,您声明一个索引数据类型,每个数据类型包含5个块,每个块包含一个元素:
// Data type 1 MPI_Datatype type1; int b_lens[5] = { 1, 1, 1, 1, 1 }; int b_offs[5] = { 1, 2, 3, 5, 7 }; MPI_Type_indexed(5, b_lens, b_offs, MPI_DOUBLE, &type1);
type1
具有以下类型映射: {(8,double),(16,double),(24,double),(40,double),(56,double)}和类型签名{double,double,double,双,双} 。
现在使用相同数量的基本元素创建不同的连续类型:
// Data type 2 MPI_Datatype type2; MPI_Type_contiguous(5, MPI_DOUBLE, &type2);
type2
具有以下类型映射: {(0,double),(8,double),(16,double),(24,double),(32,double)} 。 此类型映射显然与type1
映射不同,因为偏移量不同。 但类型签名是相同的: {double,double,double,double,double} 。 因此, type1
和type2
被认为是一致的。
以下代码是完全有效的MPI程序:
double array1[10]; double array2[5]; double array3[10]; if (rank == rank_sender) { MPI_Send(array1, 1, type1, rank_receiver, 0, MPI_COMM_WORLD); MPI_Send(array1, 1, type1, rank_receiver, 0, MPI_COMM_WORLD); } else if (rank == rank_receiver) { MPI_Status status; int num_elems; MPI_Recv(array2, 1, type2, rank_sender, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); MPI_Recv(array3, 10, MPI_DOUBLE, rank_sender, 0, MPI_COMM_WORLD, &status); MPI_Get_count(&status, MPI_DOUBLE, &num_elems); // num_elems will be set to 5 }
MPI_Send
调用将在发送器处选择array1
的第1,第2,第3,第5和第7个元素,并且MPI_Recv
调用将它们放置在接收器处的连续5元素数组array2
中。 另外,具有原始数据类型MPI_DOUBLE
的10元素接收与已发送消息的数据类型一致,但只填充缓冲区的前5个元素。对数据类型为MPI_DOUBLE
将返回5
。
基本上,两种类型的一致性意味着相同基本类型和相同顺序的相同数量的数据项被打包到消息中然后从消息中解压缩。
MPI标准要求在正确的应用中具有这种一致性。 但实际上,许多MPI实现不会在消息中传输类型签名,因此从不强制执行一致性。 例如,Open MPI和MPICH都允许您在发送方使用MPI_DOUBLE
,在接收方使用MPI_LONG
(假设使用LP64系统)。 这两种数据类型的字节大小相同,但将double
转换为long
是没有意义的。 有像MUST这样的运行时MPI正确性检查工具可以检测代码中的这些问题。