正如已經指出的,有很多使用MPI_Gatherv
的例子,包括這裏的堆棧溢出;一個回答開始描述如何分散和收集工作,然後分散/聚集變種如何擴展,可以找到here。至關重要的是,對於更簡單的Gather操作,每個塊大小相同,MPI庫可以輕鬆地預先計算每個塊在最終編譯數組中的位置;在更普遍的collectv操作中,如果不太清楚,您可以選擇 - 實際上是要求 - 準確說明每個項目的起始位置。
這裏唯一的額外麻煩是你正在處理字符串,所以你可能不希望所有的東西都一起推進;你會需要額外的空格填充,當然最後還需要一個空終止符。
因此,讓我們說你有五道工序想發送的字符串:
Rank 0: "Hello" (len=5)
Rank 1: "world!" (len=6)
Rank 2: "Bonjour" (len=7)
Rank 3: "le" (len=2)
Rank 4: "monde!" (len=6)
你會想這是組裝成一個全球性的字符串:
Hello world! Bonjour le monde!\0
111111111122222222223
recvcounts={5,6,7,2,6}; /* just the lengths */
displs = {0,6,13,21,24}; /* cumulative sum of len+1 for padding */
你可以看到,位移0 0和位移i等於(recvcounts [j]的+1)對於j的總和= 0..i-1:
i count[i] count[i]+1 displ[i] displ[i]-displ[i-1]
------------------------------------------------------------
0 5 6 0
1 6 7 6 6
2 7 8 13 7
3 2 3 21 8
4 6 7 24 3
甲ND該真實直接地實現:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mpi.h"
#define nstrings 5
const char *const strings[nstrings] = {"Hello","world!","Bonjour","le","monde!"};
int main(int argc, char **argv) {
MPI_Init(&argc, &argv);
int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
/* Everyone gets a string */
int myStringNum = rank % nstrings;
char *mystring = (char *)strings[myStringNum];
int mylen = strlen(mystring);
printf("Rank %d: %s\n", rank, mystring);
/*
* Now, we Gather the string lengths to the root process,
* so we can create the buffer into which we'll receive the strings
*/
const int root = 0;
int *recvcounts = NULL;
/* Only root has the received data */
if (rank == root)
recvcounts = malloc(size * sizeof(int)) ;
MPI_Gather(&mylen, 1, MPI_INT,
recvcounts, 1, MPI_INT,
root, MPI_COMM_WORLD);
/*
* Figure out the total length of string,
* and displacements for each rank
*/
int totlen = 0;
int *displs = NULL;
char *totalstring = NULL;
if (rank == root) {
displs = malloc(size * sizeof(int));
displs[0] = 0;
totlen += recvcounts[0]+1;
for (int i=1; i<size; i++) {
totlen += recvcounts[i]+1; /* plus one for space or \0 after words */
displs[i] = displs[i-1] + recvcounts[i-1] + 1;
}
/* allocate string, pre-fill with spaces and null terminator */
totalstring = malloc(totlen * sizeof(char));
for (int i=0; i<totlen-1; i++)
totalstring[i] = ' ';
totalstring[totlen-1] = '\0';
}
/*
* Now we have the receive buffer, counts, and displacements, and
* can gather the strings
*/
MPI_Gatherv(mystring, mylen, MPI_CHAR,
totalstring, recvcounts, displs, MPI_CHAR,
root, MPI_COMM_WORLD);
if (rank == root) {
printf("%d: <%s>\n", rank, totalstring);
free(totalstring);
free(displs);
free(recvcounts);
}
MPI_Finalize();
return 0;
}
運行給出:
$ mpicc -o gatherstring gatherstring.c -Wall -std=c99
$ mpirun -np 5 ./gatherstring
Rank 0: Hello
Rank 3: le
Rank 4: monde!
Rank 1: world!
Rank 2: Bonjour
0: <Hello world! Bonjour le monde!>
有使用['MPI_Gatherv()'](http://www.mpich.org/static/docs/v3的一些例子.1/www3/MPI_Gatherv.html)[mpi-forum](http://www.mpi-forum.org/docs/mpi-1.1/mpi-11-html/node70.html)。你可以調用'MPI_Gather()'來從數組'recvcounts'中的每個進程收集每個字符串的長度,計算位移爲'displs [0] = 0,displs [i] = displs [i-1] + recvcounts [i-1]',爲'recvbuf'分配足夠的空間,調用'MPI_Gatherv()',最後設置'recvbuf'的空終止字符以確保有效的可打印字符串。 – francis