我正在尝试编写一个程序的MPI版本,该程序在n个随机生成的元素上运行奇数/偶数比较分割操作。
进程0应该生成元素并将它们的nlocal发送给其他进程,(保留第一个nlocal本身)。从这里开始,进程0应该在运行CompareSplit算法后打印出它的结果。然后,从算法运行的其他进程接收结果。最后,打印出刚刚收到的结果。
我已经完成了很大一部分工作,但是我遇到了一个我似乎无法修复的僵局。我非常感谢人们给我的任何暗示。
这是我的代码http://pastie.org/3742474
现在我很确定死锁来自第134和151行的发送/接收。我已经尝试将标记参数更改为发送使用“标记”而不是myrank。但是当我这样做我只是因为某种原因继续得到“MPI_ERR_TAG:无效标签”。
显然我也会在处理器中运行算法> 0但我暂时把这部分拿出来,直到我弄清楚出了什么问题。
感谢任何帮助。
编辑:我编写了一个较小的测试用例,它不包含任何CompareSplit操作,但仍然是死锁。 http://pastie.org/3744691
我通过将第83行的标记从“myrank”更改为“tag”来修复上述测试用例。 那么测试用例是可行的,但是当我的程序中添加了实际的算法时,它会死锁..
所以,我认为我已经将僵局缩小到这段代码。 它看起来像是其他的Sendrecv。
for (i = 1; i <= npes; i++) {
if (i % 2 == 1) // odd phase
MPI_Sendrecv(elmnts, nlocal, MPI_INT, oddrank, 1, relmnts,
nlocal, MPI_INT, oddrank, 1, MPI_COMM_WORLD, &status);
else
MPI_Sendrecv(elmnts, nlocal, MPI_INT, evenrank, 1, relmnts,
nlocal, MPI_INT, evenrank, 1, MPI_COMM_WORLD, &status);
CompareSplit(nlocal, elmnts, relmnts, wspace,
myrank < status.MPI_SOURCE);
}
答案 0 :(得分:1)
标记错误是因为标记必须是正整数,范围从1到某个依赖于实现的最大值,保证至少为32k。
僵局很容易理解;看看非等级零流程在做什么:
else {
// The rest of the processes
// Receive nlocal randomly generated elements from process 0
MPI_Recv(elmnts, nlocal, MPI_INT, 0, tag, comm, &status);
qsort(elmnts, nlocal, sizeof(int), IncOrder); // does it matter where we sort at?
// Send results back to process 0
MPI_Send(elmnts, nlocal, MPI_INT, 0, myrank, comm);
}
所以他们正在做一次接收,一次发回。但处理器0的功能远不止于此;它向每个人发送他们的数据,然后执行一堆发送 - 接收到进程1(evenrank)和MPI_NULL_PROC(oddrank)。但是发送 - 接收到evenrank是noops,并且进程1的发送 - 接收将永远不会被回答,因为进程1没有做同样的事情。
我认为你需要将算法的那部分移到if (rank == 0)
测试之外。
答案 1 :(得分:0)
看起来您正在调用MPI_Sendrecv
[第113行],但没有oddrank
排名的流程可以回答它,因为oddrank eq -1
。