1

我正在尝试使用 MPI 和非阻塞通信在 C 中实现 Cannon 的矩阵乘法算法。我已经在http://siber.cankaya.edu.tr/ozdogan/GraduateParallelComputing.old/ceng505/node133.html尝试了示例代码,但我无法让它工作。

使用单个节点执行时它工作正常,但不仅如此,它还没有完成。

我正在尝试在 4 个节点上使用随机 4*4 矩阵。从我所能收集到的信息中,除了 0 级的 printf 进程完成了函数的执行之外,我完全没有调试工具,但是其他进程在第 68 行的 MPI_Wait 处卡住了。我对 C 和并行编程很陌生,不知道是什么错误的。

编辑:在调试过程中,我发现了一件令人难以置信的莫名其妙的事情——调用 MPI_Barrier 似乎会挂起整个程序。

乘法函数完成后,我在 main 中调用 MPI_Barrier。为了使调试更容易一点,我决定将函数代码分成几部分,并用屏障将它们分开。将屏障放置在主计算循环的末尾(这样每个进程都必须完成一次迭代才能开始下一个进程)导致循环甚至没有达到第二次迭代。

似乎当单个进程在非阻塞发送/接收和随后对 MPI_Wait 的调用之后到达屏障时,它会导致其他进程无限期地等待并且永远不会到达屏障。

这是一个示例代码:

void generateArray(int * vector, int size){
int i;
for (i = 0; i < size; i ++){
    vector[i] = rand()%10 + 1;
}
}

int test_size = 4;

int main( int argc, char **argv )
{
MPI_Init (&argc, &argv); 

int comm_size, myrank;
int my2drank, mycoords[2]; 
MPI_Comm_size(MPI_COMM_WORLD, &comm_size); 
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);


MPI_Request requests[4];
MPI_Status status[4];

MPI_Comm comm_2d;
int dims[2], periods[2];
dims[0] = dims[1] = sqrt(comm_size);
periods[0] = periods[1] = 1; 
MPI_Cart_create(MPI_COMM_WORLD, 2, dims, periods, 1, &comm_2d);

int sizelocal = test_size/dims[0];

srand(time(NULL));
int a[sizelocal*sizelocal], b[sizelocal*sizelocal];
generateArray(a, sizelocal*sizelocal);                              
generateArray(b, sizelocal*sizelocal);

MPI_Comm_rank(comm_2d, &my2drank); 
MPI_Cart_coords(comm_2d, my2drank, 2, mycoords); 

int uprank, downrank, leftrank, rightrank; 
MPI_Cart_shift(comm_2d, 0, -1, &rightrank, &leftrank);
MPI_Cart_shift(comm_2d, 1, -1, &downrank, &uprank); 

int *buffersA[2], *buffersB[2];

buffersA[0] = a; 
buffersA[1] = (int *)malloc(sizelocal*sizelocal*sizeof(int)); 
buffersB[0] = b; 
buffersB[1] = (int *)malloc(sizelocal*sizelocal*sizeof(int));

int shiftsource, shiftdest; 
MPI_Cart_shift(comm_2d, 0, -mycoords[0], &shiftsource, &shiftdest); 
MPI_Sendrecv_replace(buffersA[0], sizelocal*sizelocal, MPI_INT,shiftdest, 1, shiftsource, 1, comm_2d, &status[0]); 

MPI_Cart_shift(comm_2d, 1, -mycoords[1], &shiftsource, &shiftdest); 
MPI_Sendrecv_replace(buffersB[0], sizelocal*sizelocal, MPI_INT,shiftdest, 1, shiftsource, 1, comm_2d, &status[0]);

printf("Rank %d at point 1\n", my2drank);    

int i;
for (i = 0; i < 2; i ++){
    printf("Rank %d started iteration %d\n", my2drank, i);
    MPI_Isend(buffersA[i%2], sizelocal*sizelocal, MPI_INT,leftrank, 1, comm_2d, &requests[0]); 
    MPI_Isend(buffersB[i%2], sizelocal*sizelocal, MPI_INT,uprank, 1, comm_2d, &requests[1]); 
    MPI_Irecv(buffersA[(i+1)%2], sizelocal*sizelocal, MPI_INT,rightrank, 1, comm_2d, &requests[2]); 
    MPI_Irecv(buffersB[(i+1)%2], sizelocal*sizelocal, MPI_INT,downrank, 1, comm_2d, &requests[3]);

    MPI_Waitall(4, requests, status);
    printf("Rank %d stopped waiting in iteration %d\n", my2drank, i);
    MPI_Barrier(comm_2d);
}

printf("Rank %d at point 2\n", my2drank);

MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize();
return 0;
}

这是输出:

Rank 0 at point 1
Rank 0 started iteration 0
Rank 1 at point 1
Rank 1 started iteration 0
Rank 2 at point 1
Rank 2 started iteration 0
Rank 3 at point 1
Rank 3 started iteration 0
Rank 0 stopped waiting in iteration 0
4

0 回答 0