如何将长整数和/或无符号整数传递给 MPI 参数

How can I pass long and/or unsigned integers to MPI arguments?

本文关键字:MPI 参数 无符号整数 长整数      更新时间:2023-10-16

>假设我有一个非常大的数组,我希望用MPI(v1(发送或接收它。为了索引这个数组,我使用了一个无符号的长整数。

现在,我看到的所有 MPI 函数调用都使用 int 类型作为它们的"count"参数,例如在此示例中:

MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)

但是,如果在我的实现中,我需要能够发送/接收大于 int 可以容纳的最大数量的数组怎么办?当我尝试将无符号整数馈送到"count"参数时,编译器自然会给我一个"无效转换"错误。我想过做一个转换,但后来我担心这会缩小我的变量,所以我有点不知

所措。

执行强制转换不是解决方案,因为它只会截断长计数。这里有两个障碍需要克服——一个容易的和一个困难的障碍。

简单的障碍是 count 参数的int类型。只需创建较小大小的连续类型,然后将数据作为新数据类型的倍数发送即可通过它。示例代码如下:

// Data to send
int data[1000];
// Create a contiguous datatype of 100 ints
MPI_Datatype dt100;
MPI_Type_contiguous(100, MPI_INT, &dt100);
MPI_Type_commit(&dt100);
// Send the data as 10 elements of the new type
MPI_Send(data, 10, dt100, ...);

由于 MPI_Type_contiguous 的 count 参数是int ,使用这种技术,您最多可以发送 (231-1(2 = (262 - 232 + 1( 个元素。如果这还不够,您可以从dt100数据类型创建新的连续数据类型,例如:

// Create a contiguous datatype of 100 dt100's (effectively 100x100 elements)
MPI_Datatype dt10000;
MPI_Type_contiguous(100, dt100, &dt10000);
MPI_Type_commit(&dt10000);

如果原始数据大小不是新数据类型大小的倍数,则可以创建一个结构数据类型,其第一个元素是连续数据类型的int(data_size / cont_type_length)元素数组,其第二个元素是基元数据类型的datasize % cont_type_length元素数组。示例如下:

// Data to send
int data[260];
// Create a structure type
MPI_Datatype dt260;
int blklens[2];
MPI_Datatype oldtypes[2];
MPI_Aint offsets[2];
blklens[0] = 2; // That's int(260 / 100)
offsets[0] = 0;
oldtypes[0] = dt100;
blklens[1] = 60; // That's 260 % 100
offsets[1] = blklens[0] * 100L * sizeof(int); // Offsets are in BYTES!
oldtypes[1] = MPI_INT;
MPI_Type_create_struct(2, blklens, offsets, oldtypes, &dt260);
MPI_Type_commit(&dt260);
// Send the data
MPI_Send(data, 1, dt260, ...);

MPI_Aint是足够大的整数,可以容纳大于 LP64 系统上int可以表示的偏移量。请注意,接收方必须构造相同的数据类型,并在MPI_Recv调用中以类似方式使用它。但是,接收连续数据类型的任意非整数量有点问题。

这是很容易遇到的障碍。当您的 MPI 实现不使用内部长计数时,就不那么容易了。在这种情况下,MPI通常会崩溃或仅发送部分数据,或者可能会发生奇怪的事情。即使不构造特殊数据类型,这样的 MPI 实现也可能崩溃,只需发送 INT_MAX 类型的 MPI_INT 元素,因为总消息大小为 (231 - 1( * 4 = 233 - 4。如果是这种情况,您唯一的逃生方法是手动拆分消息并在循环中发送/接收它。

一个快速/黑客的解决方案是在发送方中对未签名的计数器进行reinterpret_cast<int>(),并在接收方中进行反向转换。但是,我认为更好的解决方案是创建一个包含正确类型的指针和计数的结构,并按照此答案的建议创建自己的自定义数据类型以使用 MPI_Type_create_struct 传递。