这是LU分解的MPI代码。
我使用了以下策略 -
有一个主人(等级0),其他人是奴隶。主设备向每个从设备发送行。 由于每个从站可能会收到多个行,因此我将所有收到的行存储在a中 缓冲,然后对其执行LU分解。做完之后我发回去了 缓冲到主人。主人不做任何计算。它只是发送和接收。
for(i=0; i<n; i++)
map[i] = i%(numProcs-1) + 1;
for(i=0; i<n-1; i++)
{
if(rank == 0)
{
status = pivot(LU,i,n);
for(j=0; j<n; j++)
row1[j] = LU[n*i+j];
}
MPI_Bcast(&status, 1, MPI_INT, 0, MPI_COMM_WORLD);
if(status == -1)
return -1;
MPI_Bcast(row1, n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
int tag1 = 1, tag2 = 2, tag3 = 3, tag4 = 4;
if(rank == 0)
{
int pno, start, index, l, rowsReceived = 0;
MPI_Request req;
MPI_Status stat;
for(j=i+1; j<n; j++)
MPI_Isend(&LU[n*j], n, MPI_DOUBLE, map[j], map[j], MPI_COMM_WORLD, &req);
if(i>=n-(numProcs-1))
cnt++;
for(j=0; j<numProcs-1-cnt; j++)
{
MPI_Recv(&pno, 1, MPI_INT, MPI_ANY_SOURCE, tag2, MPI_COMM_WORLD, &stat);
//printf("1. Recv from %d and j : %d and i : %d\n",pno,j,i);
MPI_Recv(&rowsReceived, 1, MPI_INT, pno, tag3, MPI_COMM_WORLD, &stat);
MPI_Recv(rowFinal, n*rowsReceived, MPI_DOUBLE, pno, tag4, MPI_COMM_WORLD, &stat);
/* Will not go more than numProcs anyways */
for(k=i+1; k<n; k++)
{
if(map[k] == pno)
{
start = k;
break;
}
}
for(k=0; k<rowsReceived; k++)
{
index = start + k*(numProcs-1);
for(l=0; l<n; l++)
LU[n*index+l] = rowFinal[n*k+l];
}
}
}
else
{
int rowsReceived = 0;
MPI_Status stat, stats[3];
MPI_Request reqs[3];
for(j=i+1; j<n; j++)
if(map[j] == rank)
rowsReceived += 1;
for(j=0; j<rowsReceived; j++)
{
MPI_Recv(&rowFinal[n*j], n, MPI_DOUBLE, 0, rank, MPI_COMM_WORLD, &stat);
}
for(j=0; j<rowsReceived; j++)
{
double factor = rowFinal[n*j+i]/row1[i];
for(k=i+1; k<n; k++)
rowFinal[n*j+k] -= (row1[k]*factor);
rowFinal[n*j+i] = factor;
}
if(rowsReceived != 0)
{
//printf("Data sent from %d iteration : %d\n",rank,i);
MPI_Isend(&rank, 1, MPI_INT, 0, tag2, MPI_COMM_WORLD, &reqs[0]);
MPI_Isend(&rowsReceived, 1, MPI_INT, 0, tag3, MPI_COMM_WORLD, &reqs[1]);
MPI_Isend(rowFinal, n*rowsReceived, MPI_DOUBLE, 0, tag4, MPI_COMM_WORLD, &reqs[2]);
}
//MPI_Waitall(3,reqs,stats);
}
}
我面临的问题是有时程序会挂起。我的猜测是 发送和接收没有匹配,但我无法匹配 找出问题所在。
我在大小为1000x1000,2000x2000,3000x3000,5000x5000的矩阵上运行测试用例 和7000x7000。 目前代码挂起7000x7000 。请有人帮忙 我出去了吗?
注意事项: -
map 实现了映射方案,哪一行转到哪个slave。
rowsReceived 告诉每个从属设备它将接收的行数。我不需要 每次计算,但我稍后会修复它。
row1 是存储活动行的缓冲区。
rowFinal 是正在接收和修改的行的缓冲区。
cnt 并不重要,可以忽略。为此检查 rowReceived!= 0需要删除。
答案 0 :(得分:0)
看起来你永远不会完成非阻塞操作。在整个代码中,您有大量的MPI_Isend
和MPI_Irecv
来电,但您永远不会进行MPI_Wait
或MPI_Test
(或其中一次类似的通话)。如果没有完成调用,那些非阻塞调用将永远不会完成。