2014-02-17 87 views
0

我有一個數組,它是按照我的計算過程在列之間分開的。之後我想在一個進程(0)中收集這個數組。MPI_Gather的列

每個進程的列都保存在數組A中,進程0有一個用於收集數據的數組F. F數組的大小爲n * n,每個進程都有part_size列,所以本地數組A是n * part_size。列被髮送到交替進程 - c0再次到達p0,c1到p1,c2到p0,依此類推。

我創建了新的數據類型用於發送和接收列。

上的所有進程:

MPI_Type_vector(n, 1, part_size, MPI::FLOAT, &col_send); 
MPI_Type_commit(&col_send); 

工藝0:

MPI_Type_vector(n, 1, n, MPI::FLOAT, &col_recv); 
MPI_Type_commit(&col_recv); 

現在我想收集陣列如下:

MPI_Gather(&A, part_size, col_send, &F, part_size, col_recv, 0, MPI::COMM_WORLD); 

但是結果不作爲預期。我的例子有n = 4和兩個進程。結果,來自p0的值應該在F的第0列和第2列中,p1應該存儲在第1和第3列中。相反,p0的兩列都存儲在0和1中,而p1的值根本不存在。

0: F[0][0]: 8.31786 
0: F[0][1]: 3.90439 
0: F[0][2]: -60386.2 
0: F[0][3]: 4.573e-41 
0: F[1][0]: 0 
0: F[1][1]: 6.04768 
0: F[1][2]: -60386.2 
0: F[1][3]: 4.573e-41 
0: F[2][0]: 0 
0: F[2][1]: 8.88266 
0: F[2][2]: -60386.2 
0: F[2][3]: 4.573e-41 
0: F[3][0]: 0 
0: F[3][1]: 0 
0: F[3][2]: -60386.2 
0: F[3][3]: 4.573e-41 

我承認我對這件事沒有想法。我明顯誤解了Gather或Type_vector如何工作並保存其值。有人能指出我正確的方向嗎?任何幫助將非常感激。

+0

我已重新發布答案。之前它是凌亂/錯誤 - 對不起,但現在爲如此巨大的抱歉.....:P希望它有幫助。 – Sigismondo

回答

1

我看到的問題是用MPI_Type_vector()創建的數據類型的範圍從第一個項目到最後一個項目。例如:

col_recv數據類型的程度><(我希望面具的這種表示是非常明顯的)之間:

>x . . . 
x . . . 
x . . . 
x<. . . 

也就是說13個MPI_FLOAT項目(必須按行讀取,這是C排序)。 接收他們兩個會導致:

>x . . . 
x . . . 
x . . . 
x y . . 
. y . . 
. y . . 
. y . . 

這顯然不是你想要的。

要讓MPI_Gather()正確跳過你需要設置的col_recv大的程度究竟一個元素接收數據。您可以通過使用MPI_Type_create_resized()做到這一點:

>x<. . . 
x . . . 
x . . . 
x . . . 

使接收連續的數據塊被正確地交錯:

x y . . 
    x y . . 
    x y . . 
    x y . . 

但是接收兩列,而不是一個會導致:

x x y y 
    x x y y 
    x x y y 
    x x y y 

那再次不是你想要的,即使更接近。

由於要交織的列,則需要創建更復雜的數據類型,能夠描述的所有列的,具有1項-程度之前:每一列分離

(步幅)爲一個元件(這是程度 - 而不是大小,即4種元素 - 先前定義的列):

>x<. x . 
    x . x . 
    x . x . 
    x . x . 

接收每個處理器的其中之一,你會得到你想要的東西:

x y x y 
    x y x y 
    x y x y 
    x y x y 

您也可以用MPI_Type_create_darray()來做到這一點,因爲它允許創建數據類型,適合與scalapack的塊循環分配一起使用,這是您的一個1D子類型。

我也試過了。這裏是一個工作代碼,在兩個處理器上:

#include <mpi.h> 

#define N  4 
#define NPROCS 2 
#define NPART (N/NPROCS) 

int main(int argc, char **argv) { 
    float a_send[N][NPART]; 
    float a_recv[N][N] = {0}; 
    MPI_Datatype column_send_type; 
    MPI_Datatype column_recv_type; 
    MPI_Datatype column_send_type1; 
    MPI_Datatype column_recv_type1; 
    MPI_Datatype matrix_columns_type; 
    MPI_Datatype matrix_columns_type1; 

    MPI_Init(&argc, &argv); 
    int my_rank; 
    MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); 

    for(int i=0; i<N; ++i) { 
    for(int j=0; j<NPART; ++j) { 
     a_send[i][j] = my_rank*100+10*(i+1)+(j+1); 
    } 
    } 

    MPI_Type_vector(N, 1, NPART, MPI_FLOAT, &column_send_type); 
    MPI_Type_commit(&column_send_type); 

    MPI_Type_create_resized(column_send_type, 0, sizeof(float), &column_send_type1); 
    MPI_Type_commit(&column_send_type1); 

    MPI_Type_vector(N, 1, N, MPI_FLOAT, &column_recv_type); 
    MPI_Type_commit(&column_recv_type); 

    MPI_Type_create_resized(column_recv_type, 0, sizeof(float), &column_recv_type1); 
    MPI_Type_commit(&column_recv_type1); 

    MPI_Type_vector(NPART, 1, NPROCS, column_recv_type1, &matrix_columns_type); 
    MPI_Type_commit(&matrix_columns_type); 

    MPI_Type_create_resized(matrix_columns_type, 0, sizeof(float), &matrix_columns_type1); 
    MPI_Type_commit(&matrix_columns_type1); 

    MPI_Gather(a_send, NPART, column_send_type1, a_recv, 1, matrix_columns_type1, 0, MPI_COMM_WORLD); 

    if (my_rank==0) { 
    for(int i=0; i<N; ++i) { 
     for(int j=0; j<N; ++j) { 
     printf("%4.0f ",a_recv[i][j]); 
     } 
     printf("\n"); 
    } 
    } 

    MPI_Finalize(); 
} 
+0

經過努力解釋...評論如果不清楚或者upvote真的會受到歡迎:( – Sigismondo

+0

對不起,因爲延遲 - 我打算再次回到你身邊,再一次忘記了它。謝謝你的幫助! – asto