MPI Scatter/Gather 变量范围
MPI Scatter/Gather scope of variables
我正在处理 BML 自动机的 MPI 版本,但 MPI_Scatter() 无法按预期工作。我读到 here 对于集体通信功能,每个进程都需要它的数组副本,只是分配的 space 没有初始化。在我的代码中,有一个每个进程都操作的子网格 local_grid
,以及一个只有 root 操作的起始大 grid
。我的意思是使用 MPI 数据类型的 Scatter-Gather 通信。我为每个网格和子网格分配space,然后只为根初始化网格。我哪里错了?
unsigned char*** local_grid;
unsigned char** grid;
MPI_Status stat;
MPI_Datatype rowtype;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
local_n = N / nproc;
MPI_Type_contiguous(N + 2, /* count */
MPI_UNSIGNED_CHAR, /* oldtype */
&rowtype /* newtype */
);
MPI_Type_commit(&rowtype);
/* Allocate space for 3D local grids*/
local_grid = (unsigned char***)malloc(2 * sizeof(unsigned char**));
for(i = 0; i < 2; i++) {
local_grid[i] = (unsigned char**)malloc((local_n + 2) * sizeof(unsigned char*));
for(j = 0; j < local_n + 2; j++) {
local_grid[i][j] = (unsigned char*)malloc((N + 2) * sizeof(unsigned char));
}
}
/* Initialize local grids*/
for(i = 0; i < local_n + 2; i++) {
for(j = 0; j < N + 2; j++) {
local_grid[0][i][j] = 0;
local_grid[1][i][j] = 0;
}
}
/* Allocate 2D starting grid */
grid = (unsigned char**)malloc(N * sizeof(unsigned char*));
for(i = 0; i < N + 2; i++) {
grid[i] = (unsigned char*)malloc((N + 2) * sizeof(unsigned char));
}
/* Root */
if(rank == 0) {
/* initialize 2D starting grid */
for(i = 0; i < N; i++) {
for(j = 0; j < N + 2; j++) {
grid[i][j] = (((float)rand())/RAND_MAX) > rho ? 0 : rand()%2 + 1;
grid[i][0] = grid[i][N+1] = 0;
printf("%2d ", grid[i][j]);
}
printf("\n");
}
}
/* All */
MPI_Scatter(grid[0], local_n, rowtype, local_grid[cur][1], local_n, rowtype, source, MPI_COMM_WORLD);
...
程序正确终止,但只有一个 rowtype 行从 Scatter() 传递到根进程,尽管它们的编号没有传递给任何其他进程。
问题来自于您 declare/allocate 二维数组的方式。
您将二维数组声明为数组指针数组(例如矩阵行),但 MPI 需要连续布局。
例如,您可以替换
grid = (unsigned char**)malloc(N * sizeof(unsigned char*));
for(i = 0; i < N; i++) {
grid[i] = (unsigned char*)malloc((N + 2) * sizeof(unsigned char));
}
和
grid = (unsigned char**)malloc(N * sizeof(unsigned char*));
grid[0] = (unsigned char*)malloc(N*(N+2)*sizeof(unsigned char));
for(i = 1; i < N; i++) {
grid[i] = grid[i-1] + N + 2;
}
然后使用 grid[0]
作为 MPI_Scatter()
或 MPI_Gather()
的缓冲区参数
同样的事情必须应用于 local_grid[0]
和 local_grid[1]
当您需要释放网格时,只需
free(grid[0]);
free(grid);
请注意,如果 N
不是 nproc
的倍数,我认为您的程序无法正常运行
我正在处理 BML 自动机的 MPI 版本,但 MPI_Scatter() 无法按预期工作。我读到 here 对于集体通信功能,每个进程都需要它的数组副本,只是分配的 space 没有初始化。在我的代码中,有一个每个进程都操作的子网格 local_grid
,以及一个只有 root 操作的起始大 grid
。我的意思是使用 MPI 数据类型的 Scatter-Gather 通信。我为每个网格和子网格分配space,然后只为根初始化网格。我哪里错了?
unsigned char*** local_grid;
unsigned char** grid;
MPI_Status stat;
MPI_Datatype rowtype;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
local_n = N / nproc;
MPI_Type_contiguous(N + 2, /* count */
MPI_UNSIGNED_CHAR, /* oldtype */
&rowtype /* newtype */
);
MPI_Type_commit(&rowtype);
/* Allocate space for 3D local grids*/
local_grid = (unsigned char***)malloc(2 * sizeof(unsigned char**));
for(i = 0; i < 2; i++) {
local_grid[i] = (unsigned char**)malloc((local_n + 2) * sizeof(unsigned char*));
for(j = 0; j < local_n + 2; j++) {
local_grid[i][j] = (unsigned char*)malloc((N + 2) * sizeof(unsigned char));
}
}
/* Initialize local grids*/
for(i = 0; i < local_n + 2; i++) {
for(j = 0; j < N + 2; j++) {
local_grid[0][i][j] = 0;
local_grid[1][i][j] = 0;
}
}
/* Allocate 2D starting grid */
grid = (unsigned char**)malloc(N * sizeof(unsigned char*));
for(i = 0; i < N + 2; i++) {
grid[i] = (unsigned char*)malloc((N + 2) * sizeof(unsigned char));
}
/* Root */
if(rank == 0) {
/* initialize 2D starting grid */
for(i = 0; i < N; i++) {
for(j = 0; j < N + 2; j++) {
grid[i][j] = (((float)rand())/RAND_MAX) > rho ? 0 : rand()%2 + 1;
grid[i][0] = grid[i][N+1] = 0;
printf("%2d ", grid[i][j]);
}
printf("\n");
}
}
/* All */
MPI_Scatter(grid[0], local_n, rowtype, local_grid[cur][1], local_n, rowtype, source, MPI_COMM_WORLD);
...
程序正确终止,但只有一个 rowtype 行从 Scatter() 传递到根进程,尽管它们的编号没有传递给任何其他进程。
问题来自于您 declare/allocate 二维数组的方式。
您将二维数组声明为数组指针数组(例如矩阵行),但 MPI 需要连续布局。
例如,您可以替换
grid = (unsigned char**)malloc(N * sizeof(unsigned char*));
for(i = 0; i < N; i++) {
grid[i] = (unsigned char*)malloc((N + 2) * sizeof(unsigned char));
}
和
grid = (unsigned char**)malloc(N * sizeof(unsigned char*));
grid[0] = (unsigned char*)malloc(N*(N+2)*sizeof(unsigned char));
for(i = 1; i < N; i++) {
grid[i] = grid[i-1] + N + 2;
}
然后使用 grid[0]
作为 MPI_Scatter()
或 MPI_Gather()
的缓冲区参数
同样的事情必须应用于 local_grid[0]
和 local_grid[1]
当您需要释放网格时,只需
free(grid[0]);
free(grid);
请注意,如果 N
不是 nproc