MPI_Scatter - 发送2D数组的列

Way*_*int 2 c mpi

我想发送2D数组的列,每个列都是单独的进程.我现在有一个完整的2d阵列,我被MPI_Scatter困住了.如何将整列作为字段发送?

谢谢

编辑:

我有阵列 - 浮动[100] [101]

我试图通过以下方式发送数组:

float send;
MPI_Scatter ((void *)a, n, MPI_FLOAT,(void *)&send  , 1, MPI_INT,0, MPI_COMM_WORLD);
Run Code Online (Sandbox Code Playgroud)

EDIT2:

我创建了新的type_vector:

               MPI_Datatype newtype;

               MPI_Type_vector(n,       /* # column elements */
                   1,           /* 1 column only */
                   n+1,         /* skip n+1 elements */
                   MPI_FLOAT,       /* elements are float */
                   &newtype);       /* MPI derived datatype */

               MPI_Type_commit(&newtype);
Run Code Online (Sandbox Code Playgroud)

现在我试图将它发送到我的其他进程.矩阵由浮点数填充,我的矩阵是nx n + 1,因为测试是n = 5,所以它是矩阵5 x 6. Scatter的调用是什么,我应该从其他进程的方面采取什么方法?我的意思是,如何获取由散射发送的数据?

Jon*_*rsi 6

这与此问题非常相似:如何从处理器MPI_Gatherv列,其中每个进程可以发送不同数量的列.问题是列在内存中不连续,所以你必须玩.

在C中总是如此,缺少真正的多维数组,你必须对内存布局有点小心.我相信 C就是这样一个静态声明的数组

float a[nrows][ncols]
Run Code Online (Sandbox Code Playgroud)

在记忆中是连续的,所以你现在应该没事.但是,请注意,一旦进入动态分配,就不再是这种情况; 你必须一次分配所有数据,以确保你获得连续的数据,例如

float **floatalloc2d(int n, int m) {
    float *data = (float *)malloc(n*m*sizeof(float));
    float **array = (float **)calloc(n*sizeof(float *));
    for (int i=0; i<n; i++)
        array[i] = &(data[i*m]);

    return array;
}

float floatfree2d(float **array) {
    free(array[0]);
    free(array);
    return;
}

/* ... */
float **a;
nrows = 3;
ncols = 2;
a = floatalloc2d(nrows,ncols);
Run Code Online (Sandbox Code Playgroud)

但我觉得你现在还好.

现在你有了这样或那样的二维数组,你必须创建你的类型.如果您只发送一列,您所描述的类型就可以了; 但这里的诀窍是,如果你发送多个列,每个列只会在前一个列的开头之前启动一个浮点数,即使列本身几乎跨越整个数组!所以你需要移动类型的上限才能工作:

       MPI_Datatype col, coltype;

       MPI_Type_vector(nrows,    
           1,                  
           ncols,         
           MPI_FLOAT,       
           &col);       

       MPI_Type_commit(&col);
       MPI_Type_create_resized(col, 0, 1*sizeof(float), &coltype);
       MPI_Type_commit(&coltype); 
Run Code Online (Sandbox Code Playgroud)

会做你想做的.请注意,接收进程的类型与发送进程的类型不同,因为它们存储的列数较少; 因此元素之间的步幅较小.

最后,您现在可以进行分散,

MPI_Comm_size(MPI_COMM_WORLD,&size);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
if (rank == 0) {
    a = floatalloc2d(nrows,ncols);
    sendptr = &(a[0][0]);
} else {
    sendptr = NULL;
}
int ncolsperproc = ncols/size;  /* we're assuming this divides evenly */
b = floatalloc(nrows, ncolsperproc);

MPI_Datatype acol, acoltype, bcol, bcoltype;

if (rank == 0) {
    MPI_Type_vector(nrows,    
               1,                  
               ncols,         
               MPI_FLOAT,       
               &acol);       

     MPI_Type_commit(&acol);
     MPI_Type_create_resized(acol, 0, 1*sizeof(float), &acoltype);
}
MPI_Type_vector(nrows,    
               1,                  
               ncolsperproc,         
               MPI_FLOAT,       
               &bcol);       

MPI_Type_commit(&bcol);
MPI_Type_create_resized(bcol, 0, 1*sizeof(float), &bcoltype);
MPI_Type_commit(&bcoltype);

MPI_Scatter (sendptr, ncolsperproc, acoltype, &(b[0][0]), ncolsperproc, bcoltype, 0, MPI_COMM_WORLD);
Run Code Online (Sandbox Code Playgroud)