我看到的問題是用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();
}
我已重新發布答案。之前它是凌亂/錯誤 - 對不起,但現在爲如此巨大的抱歉.....:P希望它有幫助。 – Sigismondo