我需要MPI_Gatherv()
一些 int/string 对。假设每一对看起来像这样:
struct Pair {
int x;
unsigned s_len;
char s[1]; // variable-length string of s_len chars
};
如何为 Pair 定义适当的 MPI 数据类型?
简而言之,理论上不可能发送一条可变大小的消息并将其接收到完美大小的缓冲区中。您要么必须发送带有每个字符串大小的第一条消息,然后发送带有字符串本身的第二条消息,要么将该元信息编码到有效负载中并使用静态接收缓冲区。
如果您必须只发送一条消息,那么我将放弃为 Pair 定义数据类型:相反,我将为整个有效负载创建一个数据类型,并将所有数据转储到一个连续的、无类型的包中。然后在接收端,您可以对其进行迭代,为每个字符串分配所需的确切空间量并填充它。让我画一个 ASCII 图表来说明。这将是您的有效载荷:
|..x1..|..s_len1..|..string1..|..x2..|..s_len2..|.string2.|..x3..|..s_len3.. |.......string3........|...
您将整个内容作为一个单元发送(例如 MPI_BYTE 数组),然后接收者将像这样解包它:
while (buffer is not empty)
{
read x;
read s_len;
allocate s_len characters;
move s_len characters from buffer to allocated space;
}
但是请注意,此解决方案仅适用于整数和字符的数据表示在发送和接收系统上相同的情况。
我不认为你可以用 MPI 做你想做的事。我是一名 Fortran 程序员,如果我对 C 的理解有点不稳定,请多多包涵。您似乎希望将一个由 1 个 int 和 1 个字符串(您通过传递字符串中第一个字符的位置来传递)组成的数据结构从一个进程传递到另一个进程?我认为你要做的是传递一个固定长度的字符串——因此,它与你真正想要传递的任何字符串一样长。用于收集这些琴弦的接收区域必须足够大,以接收所有琴弦及其长度。
您可能希望为您的结构声明一个新的 MPI 数据类型;然后您可以收集这些数据,并且由于收集的数据包括字符串的长度,因此可以在接收器处恢复字符串的有用部分。
我不确定这一点,但我从来没有遇到过你似乎想要使用的真正可变的消息长度,而且它确实有点不像 MPI。但这可能是我从未偶然发现的最新版本的 MPI 中实现的东西,尽管查看在线文档似乎并非如此。
MPI 实现不检查或解释消息的实际内容。只要您知道数据结构的大小,您就可以用一些 char 或 int 来表示该大小。MPI 实现不会知道或关心数据的实际内部细节。
有一些警告......发送方和接收方都需要就消息内容的解释达成一致,并且您在发送方和接收方提供的缓冲区需要适合一些可定义数量的 char 或 int。