使用MPI,当存在连续数组时,用户定义的数据类型没有用吗?

时间:2018-07-10 09:39:59

标签: c arrays mpi contiguous row-major-order

在我的程序中,我将Matrix的某些行发送给其他处理器,我使用C进行编码,并且我知道C是行优先的。 矩阵被分配为一维数组。

matrixInArrayB = malloc(height * width * sizeof(int));
matrixB = malloc(height * sizeof(int*));
for (int y = 0; y < height; y++) {
    matrixB[y] = &matrixInArrayB[y * width];
}

我以这种方式发送他们

MPI_Isend(&matrixB[0][0], width * height, MPI_INT, dest, tag,
          MPI_COMM_WORLD, &requestesForB[k]);

我的疑问是我是否必须临时使用某些数据类型来确保行的连续性,例如:

 int MPI_Type_contiguous(int count,
                      MPI_Datatype oldtype,
                      MPI_Datatype *newtype)

1 个答案:

答案 0 :(得分:2)

否,如果您不需要,则不需要定义自己的数据类型。但是,如果使用得当,它们会非常有用。


假设您具有以下结构来描述矩阵,而不是指向数据行的指针数组:

typedef struct {
    int      rows;
    int      cols;
    ssize_t  rowstep;
    ssize_t  colstep;
    int     *data;
} matrix;

其中矩阵r的行c,列m上的数据元素是m.data[r*rowstep + c*colstep]。我已经概述了该结构in this answer的更好版本。

然后,您可以使用MPI_Type_create_hvector()创建与特定类型的矩阵(特定的大小和步长)对应的行,列或主对角线的类型:

int  n = (m.rows <= m.cols) ? m.rows : m.cols; /* min(m.rows, m.cols) */

MPI_Type_create_hvector(m.rows, 1, m.rowstep * sizeof m.data[0],
                        MPI_INT, &row_vector_type);
MPI_Type_create_hvector(m.cols, 1, m.colstep * sizeof m.data[0],
                        MPI_INT, &col_vector_type);
MPI_Type_create_hvector(n, 1, (m.rowstep + m.colstep) * sizeof m.data[0],
                        MPI_INT, &diag_vector_type);

要引用第r行,请使用m.data + r*m.rowstep
要引用列c,请使用m.data + c*m.colstep
要引用主对角线,请使用m.data
size字段始终为1,因为您发送/接收单独的行或列。

也可以定义与矩阵的任何连续矩形部分相对应的数据类型。

然后,MPI库将在发送时收集数据,并在接收时分散数据。实际数据项在内存中不必连续。


在上面的示例中,可以使用相同的代码发送和接收任何行,列或对角矢量。使用自定义数据类型,除了如上所述定义类型外,无需区分它们。

简化代码往往会产生更健壮的代码,并且错误更少。 (您可以说错误是一种不合一的类型,即很难发现但并不复杂,或者是复杂的类型,其中代码的不同方面以意外或无意的方式相互作用而导致错误。)

因此,我想说,即使数据位于连续数组中,用户定义的MPI数据类型也不是没有用,因为它们可用于简化代码,从而使其更健壮和易于维护。

显然,并非所有MPI代码都很好地使用了用户定义的MPI数据类型。绝对不可能使用用户定义的数据类型。

我的意思是,您要根据情况决定是否有用,具体取决于是否可以使代码更简单,更易于阅读且更可靠。