Matrix 散布矩阵-MPI

Matrix 散布矩阵-MPI,matrix,mpi,Matrix,Mpi,我试图将矩阵逐行分散到所有处理器,但这导致了分割错误。。我不知道我做错了什么。。这是我的密码 if(rank == 0) { A_row = 10; A_col = 10; /* calculate the strip size */ strip_size = A_row / size;

我试图将矩阵逐行分散到所有处理器,但这导致了分割错误。。我不知道我做错了什么。。这是我的密码

      if(rank == 0) {
                    A_row = 10;
                    A_col = 10;
                    /* calculate the strip size */
                    strip_size = A_row / size;

                    /* genarate Matrix A */
                    A = (double **)malloc(sizeof(double*) * 10);
                    int k = 0;
                    for(i = 0; i < 10; i++) {
                            A[i] = (double*)malloc(sizeof(double) * 10);
                            for(j = 0; j < 10; j++) {
                                    A[i][j] = k;
                                    k++;
                                    printf("%lf  ", A[i][j]);
                            }
                            printf("\n");
                    }
            }

            /* Broadcasting the row, column size of Matrix A as well as strip size and Matrix B*/
            MPI_Bcast(&A_row, 1, MPI_INT, 0, MPI_COMM_WORLD);
            MPI_Bcast(&A_col, 1, MPI_INT, 0, MPI_COMM_WORLD);
            MPI_Bcast(&strip_size, 1, MPI_INT, 0, MPI_COMM_WORLD);

            /* defining a datatype for sub-matrix */
            MPI_Type_vector(strip_size, A_col, A_col, MPI_DOUBLE, &strip);
            MPI_Type_commit(&strip);

            strip_A = (double **)malloc(sizeof(double*)*strip_size);
            for(i= 0; i< strip_size; i++) {
                    strip_A[i] = (double*)malloc(sizeof(double)*A_col);
            }

            MPI_Scatter(&A[0][0], 1, strip, &strip_A[0][0], 1, strip, 0, MPI_COMM_WORLD);

            for(i = 0; i < strip_size; i++) {
                    if(i == 0) {
                            printf("rank = %d\n", rank);
                    }
                    for(j = 0; j < A_col; j++) {
                            printf("%lf  ", strip_A[i][j]);
                    }
                    printf("\n");
            }

我认为最终,您所做的错误是将矩阵存储为数组数组。我想你会发现,如果你将它存储在一个数组中(按行主顺序或列主顺序,根据你的喜好),事情会变得容易得多。

这里有一些事情。好消息是最难的事情——创建mpi数据类型和mpi_分散调用的基本结构——是正确的

第一个问题是MPI_散点线使用&(A[0][0])——但是在除秩0之外的所有情况下,您没有将A设置为指向任何东西!所以你两次去引用一个随机指针,这就是你的错误

suszterpatt提出的一个更微妙的问题是,无法保证分配的内存行是连续的,因此即使修复了上述问题,分散操作也可能无法工作。您正试图将strip_size*A_col double从A中的某个位置发送到strip_A,但是strip_A可能不连续地包含那么多的double-它可能是A_col double,然后是一些padding,然后是A_col double-或者实际上,不同的行可能分散在内存中。三种修复方法是,为了方便起见(IMHO):(a)通过创建整个数组,然后创建指向正确位置的二维C数组,使内存中的数据连续;(b) 一次只发送一行;或者(c)创建一个MPI数据类型,它实际上反映了数据在内存中的映射方式(可能是随机的)

使用(a)的方法似乎有效(无论如何,对于按大小平均划分的_行),如下所示:

#include <stdio.h>
#include <mpi.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  int rank, size;
  int strip_size, A_row, A_col;
  double **A, **strip_A, *Adata, *stripdata;
  MPI_Datatype strip;
  int i,j;

  MPI_Init(&argc,&argv) ;

  MPI_Comm_rank(MPI_COMM_WORLD,&rank) ;
  MPI_Comm_size(MPI_COMM_WORLD,&size) ;

      if(rank == 0) {
                    A_row = 10;
                    A_col = 10;
                    /* calculate the strip size */
                    strip_size = A_row / size;

                    /* genarate Matrix A */
                    Adata = (double *)malloc(sizeof(double)*A_row*A_col);
                    A = (double **)malloc(sizeof(double*) * A_row);
                    for(i = 0; i < A_row; i++) {
                            A[i] = &(Adata[i*A_col]);
                    }
                    int k = 0;
                    for(i = 0; i < A_row; i++) {
                            for(j = 0; j < A_col; j++) {
                                    A[i][j] = k;
                                    k++;
                            }
                    }
            }

            /* Broadcasting the row, column size of Matrix A as well as strip size and Matrix B*/
            MPI_Bcast(&A_row, 1, MPI_INT, 0, MPI_COMM_WORLD);
            MPI_Bcast(&A_col, 1, MPI_INT, 0, MPI_COMM_WORLD);
            MPI_Bcast(&strip_size, 1, MPI_INT, 0, MPI_COMM_WORLD);

            /* defining a datatype for sub-matrix */
            MPI_Type_vector(strip_size, A_col, A_col, MPI_DOUBLE, &strip);
            MPI_Type_commit(&strip);

            stripdata = (double *)malloc(sizeof(double)*strip_size*A_col);
            strip_A = (double **)malloc(sizeof(double*)*strip_size);
            for(i= 0; i< strip_size; i++) {
                    strip_A[i] = &(stripdata[i*A_col]);
            }

            MPI_Scatter(Adata, 1, strip, &(strip_A[0][0]), 1, strip, 0, MPI_COMM_WORLD);
            //MPI_Scatter(Adata, A_col*strip_size, MPI_DOUBLE, &(strip_A[0][0]), A_col*strip_size, MPI_DOUBLE, 0, MPI_COMM_WORLD);

            for(i = 0; i < strip_size; i++) {
                    if(i == 0) {
                            printf("rank = %d\n", rank);
                    }
                    for(j = 0; j < A_col; j++) {
                            printf("%lf  ", strip_A[i][j]);
                    }
                    printf("\n");
            }

    MPI_Type_free(&strip);
    free(strip_A);
    free(stripdata);
    free(Adata);
    free(A);
    return 0;
}
#包括
#包括
#包括
int main(int argc,字符**argv){
int等级、大小;
整条尺寸,一行,一列;
双**A、**条带A、*数据、*条带数据;
MPI_数据类型条;
int i,j;
MPI_Init(&argc,&argv);
MPI通信等级(MPI通信世界和等级);
MPI_通信大小(MPI_通信世界和大小);
如果(秩==0){
一行=10;
A_col=10;
/*计算带钢尺寸*/
条带尺寸=行/尺寸;
/*再生基质A*/
Adata=(双精度*)malloc(双精度)*行数*列数);
A=(双**)malloc(sizeof(双*)*A_行);
对于(i=0;i
只需添加MPI_Finalize();听从你的命令 请参阅下面的代码和输出。输出正确,但由于存在障碍,无法正确打印。您可以使用MPI_Barrier()或使用MPI_Isend()和MPI_Irecv()。享受


首先,你把segfault放在哪一行?那么,我能把矩阵分散成一个数组吗。。。如果你能确保数据在内存中是连续的,那么实现它就不可能了,因为这是分散的要求,而不仅仅是分散的要求!在创建向量类型时,您声明该类型由一个_cols*strip_大小的连续双精度块组成(一个_cols double的strip_大小块,每个块由一个_cols double分隔)。因此,任何使用这种类型的通信(send、recv、allreduce,无论什么)都需要连续的数据。我认为代码的最后一行会有分段错误,因为每个进程或节点都会试图从原始矩阵中释放内存。如果(rank==0){free(Adata);free(A);}这应该是对已接受答案的(有效)注释,我可以这样写。
#include <stdio.h>
#include <mpi.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  int rank, size;
  int strip_size, A_row, A_col;
  double **A, **strip_A, *Adata, *stripdata;
  MPI_Datatype strip;
  int i,j;

  MPI_Init(&argc,&argv) ;

  MPI_Comm_rank(MPI_COMM_WORLD,&rank) ;
  MPI_Comm_size(MPI_COMM_WORLD,&size) ;

      if(rank == 0) {
                    A_row = 10;
                    A_col = 10;
                    /* calculate the strip size */
                    strip_size = A_row / size;

                    /* genarate Matrix A */
                    Adata = (double *)malloc(sizeof(double)*A_row*A_col);
                    A = (double **)malloc(sizeof(double*) * A_row);
                    for(i = 0; i < A_row; i++) {
                            A[i] = &(Adata[i*A_col]);
                    }
                    int k = 0;
                    for(i = 0; i < A_row; i++) {
                            for(j = 0; j < A_col; j++) {
                                    A[i][j] = k;
                                    k++;
                            }
                    }
            }

            /* Broadcasting the row, column size of Matrix A as well as strip size and Matrix B*/
            MPI_Bcast(&A_row, 1, MPI_INT, 0, MPI_COMM_WORLD);
            MPI_Bcast(&A_col, 1, MPI_INT, 0, MPI_COMM_WORLD);
            MPI_Bcast(&strip_size, 1, MPI_INT, 0, MPI_COMM_WORLD);

            /* defining a datatype for sub-matrix */
            MPI_Type_vector(strip_size, A_col, A_col, MPI_DOUBLE, &strip);
            MPI_Type_commit(&strip);

            stripdata = (double *)malloc(sizeof(double)*strip_size*A_col);
            strip_A = (double **)malloc(sizeof(double*)*strip_size);
            for(i= 0; i< strip_size; i++) {
                    strip_A[i] = &(stripdata[i*A_col]);
            }

            MPI_Scatter(Adata, 1, strip, &(strip_A[0][0]), 1, strip, 0, MPI_COMM_WORLD);
            //MPI_Scatter(Adata, A_col*strip_size, MPI_DOUBLE, &(strip_A[0][0]), A_col*strip_size, MPI_DOUBLE, 0, MPI_COMM_WORLD);

            for(i = 0; i < strip_size; i++) {
                    if(i == 0) {
                            printf("rank = %d\n", rank);
                    }
                    for(j = 0; j < A_col; j++) {
                            printf("%lf  ", strip_A[i][j]);
                    }
                    printf("\n");
            }

    MPI_Type_free(&strip);
    free(strip_A);
    free(stripdata);
    free(Adata);
    free(A);
    return 0;
}
#include <stdio.h>
#include <mpi.h>
#include <stdlib.h>

int main(int argc, char** argv) {
int rank, size;
int strip_size, A_row, A_col;
double **A, **strip_A, *Adata, *stripdata;
MPI_Datatype strip;
int i,j;

MPI_Init(&argc,&argv) ;

MPI_Comm_rank(MPI_COMM_WORLD,&rank) ;
MPI_Comm_size(MPI_COMM_WORLD,&size) ;

  if(rank == 0) {
                A_row = 10;
                A_col = 10;
                /* calculate the strip size */
                strip_size = A_row / size;

                /* genarate Matrix A */
                Adata = (double *)malloc(sizeof(double)*A_row*A_col);
                A = (double **)malloc(sizeof(double*) * A_row);
                for(i = 0; i < A_row; i++) {
                        A[i] = &(Adata[i*A_col]);
                }
                int k = 0;
                for(i = 0; i < A_row; i++) {
                        for(j = 0; j < A_col; j++) {
                                A[i][j] = k;
                                k++;
                        }
                }
        }

        /* Broadcasting the row, column size of Matrix A as well as strip size and Matrix B*/
        MPI_Bcast(&A_row, 1, MPI_INT, 0, MPI_COMM_WORLD);
        MPI_Bcast(&A_col, 1, MPI_INT, 0, MPI_COMM_WORLD);
        MPI_Bcast(&strip_size, 1, MPI_INT, 0, MPI_COMM_WORLD);

        /* defining a datatype for sub-matrix */
        MPI_Type_vector(strip_size, A_col, A_col, MPI_DOUBLE, &strip);
        MPI_Type_commit(&strip);

        stripdata = (double *)malloc(sizeof(double)*strip_size*A_col);
        strip_A = (double **)malloc(sizeof(double*)*strip_size);
        for(i= 0; i< strip_size; i++) {
                strip_A[i] = &(stripdata[i*A_col]);
        }

        MPI_Scatter(Adata, 1, strip, &(strip_A[0][0]), 1, strip, 0, MPI_COMM_WORLD);
        //MPI_Scatter(Adata, A_col*strip_size, MPI_DOUBLE, &(strip_A[0][0]), A_col*strip_size, MPI_DOUBLE, 0, MPI_COMM_WORLD);

        for(i = 0; i < strip_size; i++) {
                if(i == 0) {
                        printf("rank = %d\n", rank);
                }
                for(j = 0; j < A_col; j++) {
                        printf("%lf  ", strip_A[i][j]);
                }
                printf("\n");
        }
if(rank == 0){
MPI_Type_free(&strip);
free(strip_A);
free(stripdata);
free(Adata);
free(A);}

 MPI_Finalize();

 return 0;
}
rank = 0
0.000000  1.000000  2.000000  3.000000  4.000000  5.000000  6.000000  7.000000  8.000000  9.000000
rank = 2
 20.000000  21.000000  22.000000  23.000000  24.000000  25.000000  26.000000  27.000000  28.000000  29.000000  
rank = 6
60.000000  61.000000  62.000000  63.000000  64.000000  65.000000  66.000000  67.000000  68.000000  69.000000  
rank = 1
 10.000000  11.000000  12.000000  13.000000  14.000000  15.000000  16.000000  17.000000  18.000000  19.000000  
rank = 3
30.000000  31.000000  32.000000  33.000000  34.000000  35.000000  36.000000  37.000000  38.000000  39.000000  
rank = 5
50.000000  51.000000  52.000000  53.000000  54.000000  55.000000  56.000000  57.000000  58.000000  59.000000  
rank = 8
80.000000  81.000000  82.000000  83.000000  84.000000  85.000000  86.000000  87.000000  88.000000  89.000000  
rank = 7
70.000000  71.000000  72.000000  73.000000  74.000000  75.000000  76.000000  77.000000  78.000000  79.000000  
rank = 9
90.000000  91.000000  92.000000  93.000000  94.000000  95.000000  96.000000  97.000000  98.000000  99.000000  
rank = 4
40.000000  41.000000  42.000000  43.000000  44.000000  45.000000  46.000000  47.000000  48.000000  49.000000