【问题标题】:how to scatter two arrays in one message in MPI如何在 MPI 的一条消息中分散两个数组
【发布时间】:2017-10-12 03:35:03
【问题描述】:

我正在做一个大学作业,其中有一个问题是使用单列策略进行矩阵向量乘法,基本上每个进程都会得到矩阵的一列 - 我们称之为 A - ,因为矩阵 -向量定义每个进程都获得向量的一个元素-我们称之为x-,这是我拥有的函数:

double *mpiSingleColumn(const double *A,const double *x,const int size,const int rank){
    double *col=calloc(size,sizeof(double)),xi=0.0,*cols=calloc(size,sizeof(double)),*y=NULL;
    MPI_Request request;
    MPI_Iscatter(x,1,MPI_DOUBLE,&xi,1,MPI_DOUBLE,0,MPI_COMM_WORLD,&request);
    MPI_Datatype vectype,resizedvectype;
    MPI_Type_vector(size,1,size,MPI_DOUBLE,&vectype);
    MPI_Type_commit(&vectype);
    MPI_Type_create_resized(vectype,0,sizeof(double),&resizedvectype);
    MPI_Type_commit(&resizedvectype);
    MPI_Scatter(A,1,resizedvectype,col,size,MPI_DOUBLE,0,MPI_COMM_WORLD);
    MPI_Type_free(&vectype);
    MPI_Type_free(&resizedvectype);
    MPI_Wait(&request,MPI_STATUS_IGNORE);
    for(int i=0;i<size;i++)
        cols[i]=xi*col[i];
    free(col);
    if(rank==0)
        y=calloc(size,sizeof(double));
    MPI_Reduce(cols,y,size,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);
    free(cols);
    return y;
}

A 是矩阵,x 是向量,sizeA 的维度,它等于 x 的大小,对于这个问题等于进程数,rank 是进程的等级。

上述功能完美运行并产生所需的结果。但是,现在我将xA 分散在两条消息中,我希望(如果可能的话)将它们分散在一个中,是的,我知道第一个分散是异步的,但它仍然是一条消息.

我想到了派生类型,特别是MPI_Type_create_struct,但是当我有一个我没有的结构数组时,它会起作用。

我还研究了MPI_Scatterv,它也适用于一个数组,我研究了MPI_Pack,这似乎与我想要的最接近,但我不知道如何将它与Scatter ,不过我知道怎么写Send

我知道 MPI-2 RMA 和 MPI-3 共享内存,但我想知道是否有办法以消息传递方式进行。

那么怎么做(如果可能的话)?

顺便解释一下上面的函数,每一列都乘以x[i],其中i是列数,然后将结果列相加,如果你做数学你会发现结果确实是@ 987654339@ :) .

【问题讨论】:

  • 附带说明,您确实不需要需要MPI_Type_commit(&amp;vectype);

标签: c mpi


【解决方案1】:

MPI_Type_create_struct 是正确的,但您需要一个处理绝对内存地址的地址:MPI_Type_create_hindexed

但是,考虑到I 变体可以重叠和流水线等,这是一个足够有效的解决方案。

【讨论】:

    【解决方案2】:

    您(或 MPI)需要将矩阵的每一列和相关的值 x 放入一个连续的内存块中。 无论您是自己执行此操作还是通过 MPI_Pack() 执行此操作都无关紧要。 下面是手动执行的示例,但使用 MPI_Pack() 的结构相同:

    int i;
    double * buf;
    double * extendedCol;
    if (rank == 0) {
      buf = malloc(sizeof(*buf)*(size+1));
      // this will need to change if you don't have 1 process per column
      for (i = 0; i < size; ++i) {
        memcpy(buf+(i*(size+1)), A+(i*size),(size+1)*sizeof(*buf));
      }
    }
    
    extendedCol=malloc((size+1)*sizeof(*extendedCol));
    
    MPI_Scatter(buf,1,resizedvectype,extendedCol,size+1,MPI_DOUBLE,0,MPI_COMM_WORLD);
    
    for(i=0;i<size;i++) {
      cols[i]=extendedCol[size]*extendedCol[i];
    }
    

    注意,许多 MPI 程序的内存有限,因此这种内存混洗通常不是一个选项/好主意。但是,由于您已经将所有 A 存储在单个进程中,因此我们假设内存不是问题(如果您需要将数据读入已经交错的数据结构中,或者使用两条消息)。

    编辑:修复col -> extendedCol

    【讨论】:

    • 猜猜那么没有办法从两个内存位置分散数据,顺便说一下extendedCol应该是col我认为
    • 在传输过程中的某个时刻,内存必须位于一个位置(否则它不是真正的单个消息)。有许多研究论文建议在 MPI 中添加“流”,这将接近于完成您想要的(但这并不是真正的“消息传递”)。
    • 我不喜欢这个答案。这会浪费很多内存。
    猜你喜欢
    • 1970-01-01
    • 2014-06-23
    • 1970-01-01
    • 1970-01-01
    • 2017-03-22
    • 2014-03-10
    • 2013-08-15
    • 2016-09-24
    • 2021-09-24
    相关资源
    最近更新 更多