【发布时间】:2020-03-30 18:08:51
【问题描述】:
我目前正在学习使用 MPI 并尝试将我的数组块分散到我的其余处理器。
我的根处理器是最后一个 (nproc-1),我正在该处理器中生成数组。在我的代码的下一次迭代中,它将是一个随机数组。
对于我的所有处理器,我都使用 calloc 为“array”和“grain”分配连续内存。 Grain 存储要处理的数据,由于我需要原始数组中的上下行,因此我将其设置为 grain_length+2。
我的问题是我从原始数组 except 中获得了最后两个值的正确数据(请参见下面的输出示例)。
int main(int argc, char** argv)
{
int i, j, m;
int array_size, grain_length;
int rc, rank, nproc;
MPI_Status status;
rc = MPI_Init(&argc, &argv);
if (rc != MPI_SUCCESS)
{
printf("Error starting MPI Program.\n");
MPI_Abort(MPI_COMM_WORLD, rc);
}
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
array_size = 8;
grain_length = array_size / nproc;
double **array= (double **) calloc(array_size, sizeof (double *));
for (i = 0; i < array_size; i++)
array[i] = (double *) calloc(array_size, sizeof (double));
double **grain = (double **) calloc(grain_length+2, sizeof (double *));
for (i = 0; i < grain_length + 2; i++)
grain[i] = (double *) calloc(array_size, sizeof (double));
if (array == NULL || grain == NULL)
{
printf("Memory could not be allocated for the arrays.");
exit(EXIT_FAILURE);
}
if (rank == nproc-1)
{
for (i = 0; i < array_size; i++)
{
for (j = 0; j < array_size; j++)
{
//array[i][j] = rand() % 10;
array[i][j] = i+j;
}
}
}
MPI_Scatter(
&array[0][0], grain_length*array_size, MPI_DOUBLE,
&grain[1][0], grain_length*array_size, MPI_DOUBLE,
nproc-1, MPI_COMM_WORLD);
for (m = 0; m < nproc; m++)
{
if (rank == m)
{
printf("Grain from processor %d:\n", rank);
for (i = 0; i < grain_length+2; i++)
{
for (j = 0; j < array_size; j++)
{
printf("%f\t", grain[i][j]);
}
printf("\n");
}
printf("\n");
}
MPI_Barrier(MPI_COMM_WORLD);
}
if (rank == nproc-1)
{
printf("Array from processor %d:\n", rank);
for (i = 0; i < array_size; i++)
{
for (j = 0; j < array_size; j++)
{
printf("%f\t", array[i][j]);
}
printf("\n");
}
printf("\n");
}
MPI_Finalize();
return 0;
}
这是输出。在 Grain 0 中,第一行和最后一行是预期的 0,因为上面和下面的行将被发送并放置在那里。然后第二行是正确的,但第三行缺少 7 和 8 值,它们是 Grain 1 中的第一个值。
Grain 0 中的两个 0 是数组的两个指针地址吗?我不明白为什么当内存中的数组连续存储时,我得到的数据不完整。
我尝试将 scatterv 与位移一起使用,但我不确定我是否理解它是如何工作的。 我也尝试创建一个 MPI 类型,但也没有成功。
我设法将数组的每一行广播到所有其他处理器。但我认为这是非常低效的。我就是这样做的。
for (i=0; i < array_size; i++)
MPI_Bcast(&array[i][0], array_size, MPI_DOUBLE, nproc-1, MPI_COMM_WORLD);
非常感谢您的帮助!!
Grain from processor 0:
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000
1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
Grain from processor 1:
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
7.000000 8.000000 0.000000 0.000000 2.000000 3.000000 4.000000 5.000000
8.000000 9.000000 0.000000 0.000000 3.000000 4.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
Grain from processor 2:
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
5.000000 6.000000 7.000000 8.000000 9.000000 10.000000 0.000000 0.000000
6.000000 7.000000 8.000000 9.000000 10.000000 11.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
Grain from processor 3:
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 5.000000 6.000000 7.000000 8.000000 9.000000 10.000000
0.000000 0.000000 6.000000 7.000000 8.000000 9.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
Array from processor 3:
0.000000 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000
1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000
2.000000 3.000000 4.000000 5.000000 6.000000 7.000000 8.000000 9.000000
3.000000 4.000000 5.000000 6.000000 7.000000 8.000000 9.000000 10.000000
4.000000 5.000000 6.000000 7.000000 8.000000 9.000000 10.000000 11.000000
5.000000 6.000000 7.000000 8.000000 9.000000 10.000000 11.000000 12.000000
6.000000 7.000000 8.000000 9.000000 10.000000 11.000000 12.000000 13.000000
7.000000 8.000000 9.000000 10.000000 11.000000 12.000000 13.000000 14.000000
【问题讨论】:
-
您的二维数组必须在连续内存中。现代 C 最简单的选择是声明
double array[array_size][array_size]。如果这不是一个选项,快速搜索 SO 将为您指明如何在连续内存中动态分配 2D 数组的正确方向。
标签: multidimensional-array mpi scatter calloc contiguous