我有一个包含 10x10(M = 10)个元素的矩阵 (c),其中我将矩阵按行划分,由 5 个不同的进程(slaves = 5)执行,每个进程对应于该矩阵的 2 行。
offset = 0;
rows = (M / slaves);
MPI_Send(&c[offset][0], rows*M, MPI_DOUBLE, id_slave,0,MPI_COMM_WORLD);
offset= offset+rows;
现在我想按列划分矩阵。我通过更改数组索引但不工作进行了如下测试:
MPI_Send(&c[0][offset], rows*M, MPI_DOUBLE, id_slave,0,MPI_COMM_WORLD);
你知道怎么做吗?谢谢。
最佳答案
您使用了错误的数据类型。正如 Jonathan Dursi 所指出的,您需要创建一个 strided 数据类型,它告诉 MPI 如何以匹配一列或一组连续列的数据布局的方式访问内存。
在你的情况下,而不是
MPI_Send(&c[0][offset], rows*M, MPI_DOUBLE, id_slave, 0, MPI_COMM_WORLD);
你必须做的:
MPI_Datatype dt_columns;
MPI_Type_vector(M, rows, M, MPI_DOUBLE, &dt_columns);
MPI_Type_commit(&dt_columns);
MPI_Send(&c[0][offset], 1, dt_columns, id_slave, 0, MPI_COMM_WORLD);
MPI_Type_vector(M, rows, M, MPI_DOUBLE, &dt_columns)
创建一个新的 MPI 数据类型,它由 M
block 的 rows
元素组成MPI_DOUBLE
每个连续 block 的头部 M
元素分开(跨度 M
)。像这样:
|<------------ stride = M ------------->|
|<---- rows --->| |
+---+---+---+---+---+---+---+---+---+---+--
| x | x | x | x | | | | | | | ^
+---+---+---+---+---+---+---+---+---+---+ |
| x | x | x | x | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+
. . . . . . . . . . . M blocks
+---+---+---+---+---+---+---+---+---+---+
| x | x | x | x | | | | | | | |
+---+---+---+---+---+---+---+---+---+---+ |
| x | x | x | x | | | | | | | v
+---+---+---+---+---+---+---+---+---+---+--
>> ------ C stores such arrays row-wise ------ >>
如果将 rows
设置为 1,则创建了一个对应于单个列的类型。但是,这种类型不能用于发送多列,例如两列,因为 MPI 将在那里寻找第二列,第一列结束的地方位于矩阵的底部。您必须告诉 MPI 假装一列只有一个元素宽,即调整数据类型的大小。这可以使用 MPI_Type_create_resized
来完成:
MPI_Datatype dt_temp, dt_column;
MPI_Type_vector(M, 1, M, MPI_DOUBLE, &dt_temp);
MPI_Type_create_resized(dt_temp, 0, sizeof(double), &dt_column);
MPI_Type_commit(&dt_column);
您可以使用此类型发送任意数量的列:
// Send one column
MPI_Send(&c[0][offset], 1, dt_column, id_slave, 0, MPI_COMM_WORLD);
// Send five columns
MPI_Send(&c[0][offset], 5, dt_column, id_slave, 0, MPI_COMM_WORLD);
您还可以在 MPI_Scatter[v]
和/或 MPI_Gather[v]
中使用 dt_column
来分散和/或聚集整个列。
关于C-MPI : Parallel Processing of Column Arrays,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41493350/