如何在 C++ 中使用 MPI 收集字符字符串并为每个进程打印它们?
Posted
技术标签:
【中文标题】如何在 C++ 中使用 MPI 收集字符字符串并为每个进程打印它们?【英文标题】:How to gather char strings and print them for each process with MPI in C++? 【发布时间】:2021-10-21 22:29:20 【问题描述】:编辑 @GillesGouaillardet 的评论:
我正在使用 MPI 编写一个简单的 C++ 代码来进行并行处理。
我从进程 4 向 5 发送 char 消息,并为所有其他进程使用 'nothing'
初始化消息。
所以,我想收集每个进程的所有消息('nothing'
用于所有进程,但接收进程 4 发送的字符消息的第 5 个进程除外)并为每个进程打印出来,例如
Hello from process 0 among 8 of the machine jeremy-SATELLITE-P50-C
nothing
Hello from process 1 among 8 of the machine jeremy-SATELLITE-P50-C
nothing
...
Hello from process 5 among 8 of the machine jeremy-SATELLITE-P50-C
received
...
我尝试了几种类似的方法,例如:https://***.com/a/31932283/14901229,(您可以在下面的代码中看到)但它会逐字打印...
也许有人可以帮助我?提前致谢!
这是我的代码:
int rank,nbproc, taille;
char name[80];
char message[] = "preceived";
int longueur = strlen(message);
int len_buffer = 200;
char Buffer_Hello[len_buffer];
char receive[] = "nothing";
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nbproc);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Get_processor_name(name, &taille);
sprintf(Buffer_Hello,"Hello from process %d among %d of the machine %s",rank,nbproc,name);
MPI_Send(Buffer_Hello,len_buffer,MPI_CHAR,0,rank+10,MPI_COMM_WORLD);
if (rank == 4)
MPI_Send(&message[1],longueur+1,MPI_CHAR,5,2,MPI_COMM_WORLD);
// sends the message from the second element
if (rank == 5)
MPI_Recv(&receive,longueur+1,MPI_CHAR,4,2,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
int mylen = strlen(receive);
int* recvcounts = new int[nbproc*sizeof(int)];
MPI_Gather(&mylen,1,MPI_INT,recvcounts,1,MPI_INT,0,MPI_COMM_WORLD);
int totlen = 0;
int* displs = new int[nbproc*sizeof(int)];
if(rank == 0)
displs[0] = 0;
totlen += recvcounts[0] + 1;
for(int i=1; i < nbproc; i++)
totlen += recvcounts[i]+1;
displs[i] = displs[i-1] + recvcounts[i-1] + 1;
char* totalstring = new char[totlen*sizeof(char)];
if(rank == 0)
for (int i=0; i<totlen; i++)
totalstring[i] = ' ';
totalstring[totlen] = '\0';
MPI_Gatherv(&receive, mylen, MPI_CHAR,
totalstring, recvcounts, displs, MPI_CHAR,
0, MPI_COMM_WORLD);
if(rank == 0)
cout << Buffer_Hello << endl;
for(int i = 1; i < nbproc; i++)
MPI_Recv(Buffer_Hello,len_buffer,MPI_CHAR,i,i+10,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
cout << Buffer_Hello << endl;
cout << totalstring[i] << endl;
MPI_Finalize();
return 0;
我的输出:
Hello from process 0 among 8 of the machine jeremy-SATELLITE-P50-C
Hello from process 1 among 8 of the machine jeremy-SATELLITE-P50-C
o
Hello from process 2 among 8 of the machine jeremy-SATELLITE-P50-C
t
Hello from process 3 among 8 of the machine jeremy-SATELLITE-P50-C
h
Hello from process 4 among 8 of the machine jeremy-SATELLITE-P50-C
i
Hello from process 5 among 8 of the machine jeremy-SATELLITE-P50-C
n
Hello from process 6 among 8 of the machine jeremy-SATELLITE-P50-C
g
Hello from process 7 among 8 of the machine jeremy-SATELLITE-P50-C
【问题讨论】:
我不认为这是你的问题的根源,但你有 0 级发送给自己并且从不接收。原则上,如果 MPI_Send 实现为同步发送,它可能会死锁,但几乎可以肯定它是缓冲的,所以应该没问题。 请将您的代码缩减为minimal reproducible example,并明确说明预期结果以及它与当前结果之间的差异。 您为什么要测试 NaN,然后不使用该信息做任何事情? @VictorEijkhout 因为我不想打印 NaN,所以如果有一个,我什么也不打印(并且不做),但如果没有,那么它就是 else 部分。我知道这可能不是最优化的方式......我目前正在处理我的 char 收集和打印问题,我很接近,然后我可能会发布我的最终代码并可能会询问优化建议。 【参考方案1】:我终于找到了一种方法来收集这些 char 数组并为每个进程打印出来。
首先,我从每个进程中取回所有长度不同的消息,并用它们之间的所有单词和空格组成一个大字符串。可能不是更好的方法,但如果有人有更好的想法,请告诉我!
int mylen = strlen(receive);
int* recvcounts = new int[nbproc*sizeof(int)];
MPI_Gather(&mylen,1,MPI_INT,recvcounts,1,MPI_INT,0,MPI_COMM_WORLD);
int totlen = 0;
int* space = new int[nbproc*sizeof(int)];
if(rank == 0)
displs[0] = 0;
totlen += recvcounts[0] + 1;
for(int i=1; i < nbproc; i++)
totlen += recvcounts[i]+1;
space[i] = space[i-1] + recvcounts[i-1] + 1;
char* totalstring = new char[totlen*sizeof(char)];
if(rank == 0)
for (int i=0; i<totlen; i++)
totalstring[i] = ' ';
totalstring[totlen] = '\0';
MPI_Gatherv(&receive, mylen, MPI_CHAR,
totalstring, recvcounts, space, MPI_CHAR,
0, MPI_COMM_WORLD);
然后我将totalstring
拆分为多个片段,并在流程 0 中以正确的顺序打印出来。
char* piece = strtok(totalstring," ");
if(rank == 0)
cout << Buffer_Hello << endl;
cout << piece << endl;
for(int i = 1; i < nbproc; i++)
MPI_Recv(Buffer_Hello,len_buffer,MPI_CHAR,i,i+10,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
cout << Buffer_Hello << endl;
if(piece != NULL)
piece = strtok(NULL," ");
cout << piece << endl;
结果如下:
Hello from process 0 among 8 of the machine jeremy-SATELLITE-P50-C
nothing
Hello from process 1 among 8 of the machine jeremy-SATELLITE-P50-C
nothing
Hello from process 2 among 8 of the machine jeremy-SATELLITE-P50-C
nothing
Hello from process 3 among 8 of the machine jeremy-SATELLITE-P50-C
nothing
Hello from process 4 among 8 of the machine jeremy-SATELLITE-P50-C
nothing
Hello from process 5 among 8 of the machine jeremy-SATELLITE-P50-C
received
Hello from process 6 among 8 of the machine jeremy-SATELLITE-P50-C
nothing
Hello from process 7 among 8 of the machine jeremy-SATELLITE-P50-C
nothing
所以,你可以看到它有效,但它可能不是最好的方法,所以如果有人有更好的想法,不要犹豫!
【讨论】:
以上是关于如何在 C++ 中使用 MPI 收集字符字符串并为每个进程打印它们?的主要内容,如果未能解决你的问题,请参考以下文章
boost mpi:字符串变量在 mpi 消息中传递是不是有最大长度?