【问题标题】:MPI_Scatter - sending columns of 2D arrayMPI_Scatter - 发送二维数组的列
【发布时间】:2011-07-27 14:27:37
【问题描述】:

我想发送二维数组的列,每个列单独处理。我现在有一个完整的二维数组,我被 MPI_Scatter 困住了。如何将整列作为字段发送?

谢谢

编辑:

我有数组 - 浮动 a[100][101]

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

float send;
MPI_Scatter ((void *)a, n, MPI_FLOAT,(void *)&send  , 1, MPI_INT,0, MPI_COMM_WORLD);

编辑2:

我制作了新的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);

现在我正在尝试将其发送到我的其他进程。矩阵由浮点数填充,我的矩阵是 n x n+1,用于测试是 n = 5,所以它是矩阵 5 x 6。 Scatter 的什么调用会起作用,我应该从其他进程方面采取什么方法?我的意思是,如何获取由 scatter 发送的数据?

【问题讨论】:

  • 你的数组是怎么定义的,你是怎么调用Scatter的?

标签: c mpi


【解决方案1】:

这与这个问题非常相似:How to MPI_Gatherv columns from processor, where each process may send different number of columns。问题是列在内存中不是连续的,所以你必须玩弄。

在 C 语言中总是如此,缺少真正的多维数组,您必须对内存布局稍加小心。我相信在 C 中,静态声明的数组就像

float a[nrows][ncols]

在内存中是连续的,所以你现在应该没问题。但是,请注意,一旦您进行动态分配,情况将不再如此;您必须一次分配所有数据以确保获得连续数据,例如

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);

但我认为你现在还好。

现在您已经以一种或另一种方式拥有了二维数组,您必须创建您的类型。如果您只发送一列,您描述的类型就可以了;但这里的技巧是,如果您要发送多列,则每列仅从前一列的开头开始浮动,即使列本身几乎跨越整个数组!因此,您需要移动类型的上限才能使其正常工作:

       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); 

会做你想做的事。请注意,receiving 进程将具有与 sending 进程不同的类型,因为它们存储的列数较少;所以元素之间的步幅更小。

最后,你现在可以做散布了,

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);

【讨论】:

  • 感谢您这么长的回复!我一定会尝试的。与此同时,我正在思考我的整个问题。我正在做并行高斯消除。所以一开始我想发送到所有其他进程列以计算枢轴。但现在我将整个矩阵发送给他们所有人,所以我有点希望整个矩阵会更好......进程将在行之间进行计数,所以我认为在所有进程上都有矩阵是有用的。跨度>
【解决方案2】:

这有很多问题,但您的主要问题是内存布局。在a 表示的内存位置,没有一个float:只有float*s 指向内存中其他地方的float 的各种数组。由于这些数组不一定是连续的,因此您不能对它们使用Scatter

最简单的解决方案是将矩阵存储在单个数组中:

float a[100*101];

并以列优先顺序填写。然后像这样简单地分散:

MPI_Scatter(a, 100*101, MPI_FLOAT, send, 10*101, MPI_FLOAT, 0, MPI_COMM_WORLD);

这是假设您分散在 10 个进程之间,并且 send 在每个进程中定义为 float[10*101]。请注意,在您发布的代码中,Scatter 的参数 4-6 肯定存在缺陷。如果send是一个数组,那么你不需要传递&amp;send(出于同样的原因你不需要在第一个参数中传递&amp;a),并且你想要匹配的数量和类型您收到的数据项到您发送的数据项。

【讨论】:

  • 感谢您的评论,但我会使用列进行一些计算,因此无法使用 [100*101] 字段。
【解决方案3】:

好吧,Scatter 尝试以相等的比例发送它必须发送的数据。不幸的是,C 中的数据是按行存储的,而不是按列存储的。因此,您的调用将导致 Scatter 获取 n 个元素,然后发送每个进程 m = n/(进程数)浮点数。

创建一个新的 MPI 向量数据类型的常用方法(参见函数 MPI_Type_vector),您将能够克服 C 数组的行数据存储问题(因为您可以定义到向量中的元素,这将是一条线的长度)。

我没有以这种方式将 scatter 与向量一起使用,所以我不确定这是否有助于调用 Scatter,但至少您可以轻松地按列访问数据。然后,通过使用循环将这些数据传递给相应的进程将是一种简单的方法

【讨论】:

  • 嗨,看我的编辑2。我已经制作了新的 MPI_type_vector,但现在我很困惑,如何将正确的值传递给 scatter 甚至发送......你能帮我吗?
猜你喜欢
  • 2013-11-30
  • 1970-01-01
  • 2016-02-20
  • 1970-01-01
  • 2012-06-03
  • 2019-08-12
  • 2016-11-05
  • 1970-01-01
  • 2020-01-25
相关资源
最近更新 更多