如何使用MPI发送和接收字符串

7
我正在尝试使用MPI发送和接收字符串,但结果是无望的。
发送函数:
MPI_Send(&result, result.size(), MPI_CHAR, 0, 0, MPI_COMM_WORLD);

接收函数:
    MPI_Recv(&result,      /* message buffer */
        128,                 /* one data item */
        MPI_CHAR,        /* of type char real */
        MPI_ANY_SOURCE,    /* receive from any sender */
        MPI_ANY_TAG,       /* any type of message */
        MPI_COMM_WORLD,    /* default communicator */
        &status);          /* info about the received message */

“result”是一个字符串。
我没有收到任何错误信息,但程序不想结束。
2个回答

18

std::string的地址与底层C字符串的地址不同,因此应该像这样修复发送问题:

MPI_Send(result.c_str(), result.size(), MPI_CHAR, 0, 0, MPI_COMM_WORLD);
接收操作不能按照你尝试的方式进行。你需要一个缓冲区(一个char数组),将其传递给MPI_Recv,然后稍后使用它创建一个std::string实例。要获取接收到的字符串长度,请使用MPI_Get_count - 你应该将其作为指向缓冲区的指针传递给std::string构造函数。
为了避免预先分配缓冲区并允许其接收任何大小的字符串,你应该首先调用MPI_ProbeMPI_Get_count以获取长度。知道长度后,你可以分配具有确切大小的缓冲区,并只调用MPI_Recv
如果这听起来有点复杂,那么你可以考虑使用BOOST MPI wrappers

1
+1,你比我先说了。关于接收方面,如果已知 result 有足够大的缓冲区(之前已创建),他可以使用 &result[0] 来获取指向内部缓冲区的非 const 指针。 - Eran
如果result是一个std::string,那么&result[0]应该与result.c_str()相同,除了它是非const的。我个人会使用前者,并使用const_cast。我明白你的意思,在MPI_Recv中传递预分配的std::string可以工作,但如果字符串包含0,则会失败,因此需要小心处理... - piokuc
当我将参数更改为字符数组时,一切都正常工作。谢谢大家。 :) - John
2
你应该使用MPI_Send(result.c_str(), result.size() + 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);来包含字符串终止符'\0',对吧? - Darqer
@piokuc MPI_Send(result.c_str(), result.size(), MPI_CHAR, 0, 0, MPI_COMM_WORLD); 给出编译器错误,指示具有const char类型的第一个参数与void参数不兼容。 我该如何解决? - Nurlan
@Nurlan 我知道这已经很晚了,但是你的问题在于你将 result 声明为 const。然而,根据 Send/Recv 对的定义,你需要能够在接收端更改 result。因此它不能是一个 const std::string,而应该是一个非 const 的 std::string - NoseKnowsAll

-1
我曾经遇到过类似的问题,需要在MPI C中的两个进程之间传递一个字符串。我的解决方案如下,与您的问题相符:
MPI_Send(&result, strlen(result)+1, MPI_CHAR, 1, 0, MPI_COMM_WORLD); // Destination: Process 1

另一方面,进程0将具有以下MPI_Recv函数:

MPI_Recv(&result, 100, MPI_CHAR, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); // Source: Process 0 and considering 100 as the maximum string length

必须在头文件中添加<string.h>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接