我试图使用MPI_Gather将单个二维数组收集到主进程中,然后打印出整个矩阵的内容。我将工作负载分配给了 num_processes
进程,并让每个进程在自己的私有矩阵上工作。我将给出一段我的代码和一些伪代码来演示我在做什么。请注意,我创建了自己的MPI_Datatype,因为我正在转移结构类型。
Point **matrix = malloc(sizeof(Point *) * (num_rows/ num_processes));
for (i = 0; i < num_rows/num_processes; i++)
matrix [i] = malloc(sizeof(Point) * num_cols);
for( i = 0; i< num_rows/num_processes; i++)
for (j = 0; j < num_cols; j++)
matrix[i][j] = *Point type*
if (processor == 0) {
full_matrix = malloc(sizeof(Point *) * num_rows);
for (i = 0; i < num_rows/num_processes; i++)
matrix [i] = malloc(sizeof(Point) * num_cols);
MPI_Gather(matrix, num_rows/num_processes*num_cols, MPI_POINT_TYPE, full_matrix, num_rows/num_processes*num_cols, MPI_POINT_TYPE, 0, MPI_COMM_WORLD);
} else {
MPI_Gather(matrix, num_rows/num_processes*num_cols, MPI_POINT_TYPE, NULL, 0, MPI_DATATYPE_NULL, 0, MPI_COMM_WORLD);
}
// ...print full_matrix...
正如我自己的测试所显示的那样,收集之前的double for-loop计算出了正确的值,但是收集到了 full_matrix
只包含自己的进程,即主进程的数据,因为它后来的打印显示。
我很难理解为什么会这样,因为主进程正确地传输了数据。问题是我如何为每个进程分配内存吗?
问题是 MPI_Gather
希望缓冲区的内容在内存中是相邻的,但是反复调用malloc并不能保证这一点,因为每次调用都可能返回一个指向任意内存位置的指针。
解决办法是将Matrix存储在一整块内存中,像这样。
Point *matrix = malloc(sizeof(Point) * (num_rows / num_processes) * num_cols);
用这种方法,你必须以这样的形式来访问数据。matrix[i * N + j]
. 如果你想保留当前的代码,你可以像以前一样创建相邻的内存,并使用另一个向量来存储每行的指针。
Point *matrixAdj = malloc(sizeof(Point) * (num_rows / num_processes) * num_cols);
Point **matrix = malloc(sizeof(Point *) * num_rows);
for (int i = 0; i < num_rows; ++i) {
matrix[i] = &matrixAdj[i * num_rows];
}