我有一个由多个进程并行操作的2D双精度数组。每个进程操作数组的一部分,在每次迭代结束时,我需要确保所有进程都具有相同的二维数组副本。
假设一个大小为10*10和2个进程(或处理器)的数组。进程1 (P1)操作2D行的前5行(总共5*10=50元素),P2操作最后5行(总共50个元素)。在每次迭代的末尾,我需要P1有(它自己的前5行+P2的最后5行)。P2应该有(P1的前5行+它自己的最后5行)。我希望场景是清晰的。
我正在尝试使用下面给出的代码进行广播。但是我的程序仍然退出,并返回这个错误:"APPLICATION TERMINATED with THE EXIT STRING: Hangup (signal 1)“。
我已经使用了一个连续的2D内存分配器,正如这里所指出的: Jonathan的MPI_Bcast a dynamic 2d array。但我仍然收到相同的错误。
有人能帮帮我吗?
我的代码:
double **grid, **oldgrid;
int gridsize; // size of grid
int rank, size; // rank of current process and no. of processes
int rowsforeachprocess, offset; // to keep track of rows that need to be handled by each process
/* allocation, MPI_Init, and lots of other stuff */
rowsforeachprocess = ceil((float)gridsize/size);
offset = rank*rowsforeachprocess;
/* Each process is handling "rowsforeachprocess" #rows.
* Lots of work done here
* Now I need to broadcast these rows to all other processes.
*/
for(i=0; i<gridsize; i++){
MPI_Bcast(&(oldgrid[i]), gridsize-2, MPI_DOUBLE, (i/rowsforeachprocess), MPI_COMM_WORLD);
}第2部分:上面的代码是使用一维分解的拉普拉斯方程的并行求解器的一部分,我不想使用Master-worker模型。如果我使用Master-worker模型,我的代码会更容易吗?
发布于 2011-12-02 06:36:21
这里导致崩溃的问题是2d数组指针问题-- &(oldgridi)是指向双精度数的指针,而不是双精度数的指针,它指向数组的第i行的指针,而不是数组的第i行。你想要MPI_Bcast(&(oldgrid[i][0]),..还是MPI_Bcast(oldgrid[i],...。
还有另一种方法可以做到这一点,它只使用一个昂贵的集合通信器,而不是每行一个;如果需要每个人都拥有整个数组的副本,可以使用MPI_Allgather将数据收集在一起,并将其分发给每个人;或者,在一般情况下,如果进程的行数不相同,可以使用MPI_Allgatherv。与广播上的循环不同,这看起来有点像:
{
int *counts = malloc(size*sizeof(int));
int *displs = malloc(size*sizeof(int));
for (int i=0; i<size; i++) {
counts[i] = rowsforeachprocess*gridsize;
displs[i] = i*rowsforeachprocess*gridsize;
}
counts[size-1] = (gridsize-(size-1)*rowsforeachprocess)*gridsize;
MPI_Allgatherv(oldgrid[offset], mynumrows*gridsize, MPI_DOUBLE,
oldgrid[0], counts, displs, MPI_DOUBLE, MPI_COMM_WORLD);
free(counts);
free(displs);
}其中count是每个任务发送的项数,displs是位移。
但最后,您确定每个进程都必须有整个数组的副本吗?如果你只是在计算拉普拉斯,你可能只需要相邻的行,而不是整个数组。
这看起来像这样:
int main(int argc, char**argv) {
double **oldgrid;
const int gridsize=10; // size of grid
int rank, size; // rank of current process and no. of processes
int rowsforeachprocess; // to keep track of rows that need to be handled by each process
int offset, mynumrows;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
rowsforeachprocess = (int)ceil((float)gridsize/size);
offset = rank*rowsforeachprocess;
mynumrows = rowsforeachprocess;
if (rank == size-1)
mynumrows = gridsize-offset;
rowsforeachprocess = (int)ceil((float)gridsize/size);
offset = rank*rowsforeachprocess;
mynumrows = rowsforeachprocess;
if (rank == size-1)
mynumrows = gridsize-offset;
malloc2ddouble(&oldgrid, mynumrows+2, gridsize);
for (int i=0; i<mynumrows+2; i++)
for (int j=0; j<gridsize; j++)
oldgrid[i][j] = rank;
/* exchange row data with neighbours */
int highneigh = rank+1;
if (rank == size-1) highneigh = 0;
int lowneigh = rank-1;
if (rank == 0) lowneigh = size-1;
/* send data to high neibhour and receive from low */
MPI_Sendrecv(oldgrid[mynumrows], gridsize, MPI_DOUBLE, highneigh, 1,
oldgrid[0], gridsize, MPI_DOUBLE, lowneigh, 1,
MPI_COMM_WORLD, &status);
/* send data to low neibhour and receive from high */
MPI_Sendrecv(oldgrid[1], gridsize, MPI_DOUBLE, lowneigh, 1,
oldgrid[mynumrows+1], gridsize, MPI_DOUBLE, highneigh, 1,
MPI_COMM_WORLD, &status);
for (int proc=0; proc<size; proc++) {
if (rank == proc) {
printf("Rank %d:\n", proc);
for (int i=0; i<mynumrows+2; i++) {
for (int j=0; j<gridsize; j++) {
printf("%f ", oldgrid[i][j]);
}
printf("\n");
}
printf("\n");
}
MPI_Barrier(MPI_COMM_WORLD);
}https://stackoverflow.com/questions/8337269
复制相似问题