2014-12-19 73 views
1

我想從MPI配置中的節點收集一些不同的矩陣行。到目前爲止,我已經有了一個程序來接收另一個進程的代碼,下面是代碼,即代碼將recv更改爲數字1..7,但理想情況下,我想要的是更改前兩行,第一行的編號爲1..7,第二行的編號爲8..14,但當我更改第55/57行的發送/接收計數時,不會發生這種情況。這些塊應該在內存中連續佈置,所以我不確定我目前出錯的地方,任何幫助將不勝感激。MPI gatherv多個向量

代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include <mpi.h> 
#include <math.h> 
#include <string.h> 
#include <unistd.h> 
double **allocMatrix(int dim) { 
    int i; 
    double **matrix; 
    matrix = (double **)malloc(dim*sizeof(double *)); 
    for(i=0; i < dim; i++) { 
     matrix[i] = (double *)malloc(dim*sizeof(double)); 
    } 
    return matrix; 
} 
void printMatrix(double **values, int size) { 
    int i, j; 

    for (i = 0; i < size; i++) { 
     for (j = 0; j < size; j++) { 
      printf("%10lf ", values[i][j]); 
     } 
     printf("\n"); 
    } 
} 
int main(int argc, char* argv[]) { 
    MPI_Init(&argc, &argv); 
    int size, rank, i, j; 
    int dimensions = 7; 
    MPI_Comm_size(MPI_COMM_WORLD, &size);//number of processes 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);//rank for each process 

    double **send = allocMatrix(dimensions); 
    double **recv = allocMatrix(dimensions); 
    int count = 0; 
    for (i=0; i<dimensions; i++) { 
     for (j=0; j<dimensions; j++) { 
      if (rank == 0) { 
       recv[i][j] = 0; 
      } else { 
       send[i][j] = ++count; 
      } 
     } 
    } 

    MPI_Datatype arrType; 
    MPI_Type_vector(1, dimensions, 0, MPI_DOUBLE, &arrType); 
    MPI_Type_commit(&arrType); 
    int recvCounts[size]; 
    int displs[size]; 
    recvCounts[0] = 0; 
    displs[0] = 0; 
    recvCounts[1] = 1; 
    displs[1] = 0; 
    MPI_Gatherv(&(send[0][0]), 1, arrType, 
     &(recv[0][0]), recvCounts, displs, arrType, 
     0, MPI_COMM_WORLD); 

    if (rank == 0) { 
     printMatrix(recv, dimensions); 
    } 


    MPI_Finalize(); 
    return 0; 
} 

輸出:

make gatherv 
mpicc -Wall -o gatherv gatherv.c && ./gather 
    1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 
    0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 
    0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 
    0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 
    0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 
    0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 
    0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 

希望的輸出:

1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 
    8.000000 9.000000 10.00000 11.00000 12.00000 13.00000 14.00000 
    0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 
    0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 
    0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 
    0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 
    0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 
+0

運行的代碼我想你可能有一個邏輯錯誤在你的'MPI_Gatherv',所有的進程發送陣列的相同部分,它在非零排序過程中以完全相同的方式初始化。 – struct 2014-12-19 11:15:35

+0

@RichardTownsend對不起,忘了添加我只在這兩個進程上運行這個 - 我知道如何進一步擴展它,但我想知道如何在繼續之前先發送多行。 – micr0sub 2014-12-19 11:23:05

回答

0

有兩點可以在本代碼進行修改:

  • 矩陣的分配工作良好,有時可能有用,但由於malloc()被稱爲dim+1次,因此行在內存中不連續。您可以通過爲所有值一次性分配空間like in this answer和其他許多值來確保行在內存中連續。這種二維數組是可以用於像lapack和fftw這樣的圖書館...並且MPI_Gatherv()也會喜歡它。 malloc()將被調用兩次:一次用於指向行的指針,一次用於值。

  • 如果更改recvCounts[]中的值,則發送的項目數量必須相應更改。由於所有進程都以相同方式填充recvCounts[],並且由於接收類型和發送類型相同(arrType),因此使用recvCounts[rank]作爲MPI_Gatherv()的第二個參數是一個很好的技巧。

順便說一下,這是第一個非常好的問題!

這裏去,可以通過mpicc main.c -o main編譯和mpirun -np 42 main

#include <stdio.h> 
#include <stdlib.h> 
#include <mpi.h> 
#include <math.h> 
#include <string.h> 
#include <unistd.h> 
double **allocMatrix(int dim) { 
    int i; 
    double **matrix; 
    //allocate space for values at once, so as to be contiguous in memory 
    matrix = (double **)malloc(dim*sizeof(double *)); 
    matrix[0] = (double *)malloc(dim*dim*sizeof(double)); 
    for(i=1; i < dim; i++) { 
     matrix[i]=&matrix[0][dim*i]; 
     //matrix[i] = (double *)malloc(dim*sizeof(double)); 
    } 
    return matrix; 
} 
void printMatrix(double **values, int size) { 
    int i, j; 

    for (i = 0; i < size; i++) { 
     for (j = 0; j < size; j++) { 
      printf("%10lf ", values[i][j]); 
     } 
     printf("\n"); 
    } 
} 
//function to free the matrix 
void freeMatrix(double **values) { 
    free(values[0]); 
    free(values); 
} 

int main(int argc, char* argv[]) { 
    MPI_Init(&argc, &argv); 
    int size, rank, i, j; 
    int dimensions = 7; 
    MPI_Comm_size(MPI_COMM_WORLD, &size);//number of processes 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);//rank for each process 

    double **send = allocMatrix(dimensions); 
    double **recv = allocMatrix(dimensions); 
    int count = 0; 
    for (i=0; i<dimensions; i++) { 
     for (j=0; j<dimensions; j++) { 
      if (rank == 0) { 
       recv[i][j] = 0; 
      } else { 
       send[i][j] = ++count; 
      } 
     } 
    } 

    MPI_Datatype arrType; 
    MPI_Type_vector(1, dimensions, 0, MPI_DOUBLE, &arrType); 
    MPI_Type_commit(&arrType); 
    int recvCounts[size]; 
    int displs[size]; 
    // a loop to initialize counts and displacements 
    for(i=0;i<size;i++){ 
     recvCounts[i]=0; 
     displs[i]=0; 
    } 
    recvCounts[0] = 0; 
    displs[0] = 0; 
    if(size>1){ 
     recvCounts[1] = 2;// two lines sent 
     displs[1] = 0;//to the start of matrix 
    } 
    //second argument of mpi_gatherv() is now recvCounts[rank] 
    MPI_Gatherv(&(send[0][0]), recvCounts[rank], arrType, 
      &(recv[0][0]), recvCounts, displs, arrType, 
      0, MPI_COMM_WORLD); 

    if (rank == 0) { 
     printMatrix(recv, dimensions); 
    } 

    //free the matrices 
    freeMatrix(recv); 
    freeMatrix(send); 

    MPI_Finalize(); 
    return 0; 
} 
+0

這是完美的,謝謝!現在只需要找出如何將它從n x n - > n x n轉換爲n x n - > m x n .... – micr0sub 2014-12-21 02:47:52