加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

MPI 的死锁

(2011-04-15 20:22:44)
标签:

杂谈

分类: 随笔
以下是一段MPI的并行测试程序:

#include <stdio.h>
#include "mpi.h"


int main (int argc, char **argv)
{
    int  rank,  size,  next,  prev,  message,  tag = 200;
   
    MPI_Init (&argc,  &argv);

    MPI_Comm_rank (MPI_COMM_WORLD,  &rank);
    MPI_Comm_size (MPI_COMM_WORLD,  &size);

    next = (rank + 1) % size;
    prev = (rank + size - 1) % size;

//    if (rank == 0)
//    {
//        MPI_Send (&msg_buf,  msg_count,  msg_type,  i,  tag,  MPI_COMM_WORLD);
//    }
       
    while (1)
    {
        MPI_Recv (&message, 1, MPI_INIT, prev, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
       
        if (rank == 0)
        {
            --message;
        }

        MPI_Send (&message, 1, MPI_INT, next, tag, MPI_COMM_WOLRD);

        if (message == 0)
        {
            printf ("Process %d exiting\n", rank);
            break;
        }
    }

    if (rank == 0)
    {
        MPI_Recv (&msg_buf, msg_count, msg_type, prev, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    }

//    if (rank == 0)
//    {
//        MPI_Recv (&msg_buf, msg_count, msg_type, prev, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
//    }

    MPI_Finialize ();

    return 0;
}



这段代码的 while 语句块中,首先是每个进程都要接收数据,但没有发送方,必须等待后面的发送语句生效。而阻塞通信完成的条件是只有接受方接受到数据,通信才结束。由于这时每个进程都在等待接受数据,从而通信还没有结束,也就不会发送。这时候出现了死锁。现在以两个进程为例说明:

也就是,每个进程都在等待别的进程给自己发送数据,而此时又没有发送方

假设从其中任意取出两个进程 i 和进程 j

i --> j 表示 i 向 j 发送消息,用MPI表示为:

// if (rand == i)
    MPI_Send (&msg_buf, msg_count,  msg_type,  j tag,  MPI_COMM_WORLD);

本函数结束的条件是进程 j 接受到消息

i <-- j 表示 i 从 j 接收消息

// if (rank == j)
    MPI_Recv (&msg_buf,  msg_count,  msg_type,  i tag,  MPI_COMM_WORLD);

本函数结束的条件是 i 接收到消息

i 等待 j 接受到自己发给它的消息,同时 j 等待自己发出的消息被 i 接受。两个进程都在等待对方接受,显然就死锁了。在阻塞通信的过程中,这种死锁是很常见的。解除死锁的方法是在群发之前,有一个独立的进程发送消息给群发进程中的某一个进程

例如在上述代码中加入如下代码:


if (rank == 0)
{
    MPI_Send (&msg_buf,  msg_count,  msg_type,  i,  tag,  MPI_COMM_WORLD);
}

也就是把代码中的绿色部分解除注释。现在来分析是否会死锁:

     0 进程发送出消息给 i 进程,当进入 while 循环后,所有进程都接受数据,i 进程也不例外。此时 i 首先接受到数据,i 进程的通信过程就绪,而其他的进程仍然在等待接收。当运行到MPI_Send语句时,i 进程可以发送,其他进程无法发送。此时,i 进程的死锁解除,其他进程仍然死锁。

    如果 i 只是发给自己,而不发给其他进程,i 进程解除死锁,而其他进程还是没有解除死锁。从而,只有 i 与自己通信而已,其他进程仍然不能通信。

例如

if (rank == 0)
{
    MPI_Send (&msg_buf, msg_count, msg_type, 0, tag, MPI_COMM_WORLD);
}

这时,整个MPI_COMM_WORLD中,只有 0 进程是活动的,其他都是死锁的。

上面的过程只有形成一个消息传递环,则环中的进程才是活动的,而环外的进程是死锁的。例如:


#include <stdio.h>
#include "mpi.h"


int main (int argc, char **argv)
{
    int  rank,  size,  next,  prev,  message,  tag = 200;
   
    MPI_Init (&argc,  &argv);

    MPI_Comm_rank (MPI_COMM_WORLD,  &rank);
    MPI_Comm_size (MPI_COMM_WORLD,  &size);

    next = (rank + 1) % size;
    prev = (rank + size - 1) % size;

    if (rank == 0)
    {
        MPI_Send (&msg_buf,  msg_count,  msg_type,  next,  tag,  MPI_COMM_WORLD);
    }
       
    while (1)
    {
        MPI_Recv (&message, 1, MPI_INIT, prev, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
       
        if (rank == 0)
        {
            --message;
        }

        MPI_Send (&message, 1, MPI_INT, next, tag, MPI_COMM_WOLRD);

        if (message == 0)
        {
            printf ("Process %d exiting\n", rank);
            break;
        }
    }

    MPI_Finialize ();

    return 0;
}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有