2011-09-21 238 views
1

MPI_Gatherv是MPI像這樣的接口:我發現自己無法理解MPI_Gatherv的參數「recvcounts」

int MPI_Gatherv(
    void* sendbuf, 
    int sendcount, 
    MPI_Datatype sendtype, 
    void* recvbuf, 
    int *recvcounts, 
    int *displs, 
    MPI_Datatype recvtype, 
    int root, 
    MPI_Comm comm) 

「recvcounts」的類型是「int *」這樣我們就可以設置的計分別爲每個進程接收的項目;然而,我發現這是不可能做到這一點:

時recvcounts [I] < sendcount個,根進程將只接收sendcount個項目;

當recvcounts [I]> sendcount個,則程序將崩潰,錯誤消息是某事像這樣:

Fatal error in PMPI_Gatherv: Message truncated, error stack: 
PMPI_Gatherv(386).....: MPI_Gatherv failed(sbuf=0012FD34, scount=2, MPI_CHAR, rbuf=0012FCC8, rcnts=0012FB30, displs=0012F998, MPI_CHAR, root=0, MPI_COMM_WORLD) failed 
MPIR_Gatherv_impl(199): 
MPIR_Gatherv(103).....: 
MPIR_Localcopy(332)...: Message truncated; 2 bytes received but buffer size is 1 

因此,這意味着根有從每個處理和接收物品的固定數量參數recvcount是沒有意義的?或者我誤解了某事?

這裏是我的代碼:

#include <mpi.h> 
#include <iostream> 

int main(int argc, char* argv[]) 
{ 
    MPI_Init(&argc, &argv); 

    int n, id; 
    MPI_Comm_size(MPI_COMM_WORLD, &n); 
    MPI_Comm_rank(MPI_COMM_WORLD, &id); 

    char x[100], y[100]; 
    memset(x, '0' + id, sizeof(x)); 
    memset(y, '%', sizeof(y)); 
    int cnts[100], offs[100] = {0}; 
    for (int i = 0; i < n; i++) 
    { 
     cnts[i] = i + 1; 
     if (i > 0) 
     { 
      offs[i] = offs[i - 1] + cnts[i - 1]; 
     } 
    } 
    MPI_Gatherv(x, 1, MPI_CHAR, y, cnts, offs, MPI_CHAR, 0, MPI_COMM_WORLD); // receive only 1 item from each process 
    //MPI_Gatherv(x, 2, MPI_CHAR, y, cnts, offs, MPI_CHAR, 0, MPI_COMM_WORLD); // crash 
    if (id == 0) 
    { 
     printf("Gatherv:\n"); 
     for (int i = 0; i < 100; i++) 
     { 
      printf("%c ", y[i]); 
     } 
     printf("\n"); 
    } 

    MPI_Finalize(); 

    return 0; 
} 

回答

2

由於@Alexander Molodih指出,sendcount個= recvcount,sendtype = recvtype永遠是可行的;但是當你開始創建自己的MPI類型,你往往有不同的發送和接收類型,這就是爲什麼recvcount可能從sendcount個不同。

舉個例子,看看最近問MPI partition matrix into blocks;那裏有一個二維數組被分解成塊並散開。那裏發送類型(其具有挑出只能從全局陣列所必需的數據)和接收類型(這是數據的只是一個連續塊)是不同的,因此是計數。

是一般的原因,發送和接收的類型和支數是不同的,等東西SENDRECV,聚集/分散,或發生其他任何操作,其中,發送和recieving。

在你gatherv情況下,每個進程可以有自己不同的sendcount個,但recvcount []數組必須是所有這些計數的列表,以便接收器可以正確放置接收到的數據。如果你不知道前手的值(每個等級只知道自己的計數,cnts[id]),你可以先做一個收集:

MPI_Gather(&(cnts[id]), 1, MPI_INT, cnts, 1, MPI_INT, 0, MPI_COMM_WORLD): 
for (int i = 1; i < n; i++) { 
    offs[i] = offs[i - 1] + cnts[i - 1]; 
} 
MPI_Gatherv(x, cnts[id], MPI_CHAR, y, cnts, offs, MPI_CHAR, 0, MPI_COMM_WORLD); 
+0

我似乎發現了什麼,我誤會了:聲明「sendcount個= recvcount 「意思是,」sendcount = recvcounts [id]「對於每個過程都是正確的,不僅對於收集過程,我是對的嗎?對, – Sam

+0

是的,沒錯。 –