1

这是代码的一部分。

    if(rank==0) {   
        temp=10000; 
        var=new char[temp] ;
        MPI_Send(&temp,1,MPI_INT,1,tag,MPI_COMM_WORLD); 
        MPI_Send(var,temp,MPI_BYTE,1,tag,MPI_COMM_WORLD);
            //MPI_Wait(&req[0],&sta[1]);
    }
    if(rank==1) {
        MPI_Irecv(&temp,1,MPI_INT,0,tag,MPI_COMM_WORLD,&req[0]);
        MPI_Wait(&req[0],&sta[0]);
        var=new char[temp] ;
        MPI_Irecv(var,temp,MPI_BYTE,0,tag,MPI_COMM_WORLD,&req[1]);
        MPI_Wait(&req[0],&sta[0]);
    }
    //I am talking about this MPI_Barrier


    MPI_Barrier(MPI_COMM_WORLD);
    cout << MPI_Wtime()-t1 << endl ;
    cout << "hello " << rank  << " " << temp << endl ;
        MPI_Finalize();
}

1. 使用 MPI_Barrier 时 -正如预期的那样,所有过程都花费几乎相同的时间,大约为 0.02

2. 当不使用 MPI_Barrier() -根进程(发送消息)等待一些额外的时间。并且(MPI_Wtime -t1)变化很大,root进程花费的时间大约为2秒。

如果我没记错的话,MPI_Barrier 仅用于将所有正在运行的进程置于同一级别。那么为什么我使用 MPI_Barrier() 的时间不是 2 秒(所有进程的最小值。例如根进程)。请解释 ?

4

3 回答 3

3

感谢 Wesley Bland 注意到您在同一请求上等待了两次。这是对实际发生的情况的解释。

MPI 中有一种称为异步(非阻塞)操作的进展。那是实际转移发生的时候。在 MPI 库中的许多不同点上,可能会以许多不同的方式发生进展。当您发布一个异步操作时,它的进程可能会被无限期推迟,甚至直到有人调用MPI_WaitMPI_Test或者某些会导致新消息被推送到发送/接收队列或从发送/接收队列中拉出的调用。这就是为什么在启动非阻塞操作后尽快调用MPI_Wait或调用非常重要的原因。MPI_Test

Open MPI 支持后台进程线程,即使不满足上一段中的条件(例如,如果MPI_WaitMPI_Test从未在请求​​句柄上调用),该线程也会小心处理操作。这必须在构建库时显式启用。默认情况下不启用它,因为后台进程会增加操作的延迟。

在您的情况下发生的情况是,您在第二次呼叫MPI_Wait接收方时正在等待不正确的请求,因此第二次操作的进程MPI_Irecv被推迟。消息大小超过 40 KiB(10000 乘以 4 字节 + 信封开销),高于 Open MPI 中的默认急切限制 (32 KiB)。此类消息使用会合协议发送,该协议要求发送和接收操作都被发布和处理。接收操作不会进行,因此 rank 0 中的发送操作会阻塞,直到某个时间点,MPI_Finalizerank 1 调用的清理例程最终会进行接收。

当您调用 时MPI_Barrier,它会导致未完成接收的进程,其行为几乎就像对 的隐式调用MPI_Wait。这就是为什么 0 级发送快速完成并且两个过程都及时进行的原因。

请注意MPI_Irecv,紧跟其后MPI_Wait相当于简单地调用MPI_Recv。后者不仅更简单,而且更不容易出现像您所做的那样的简单拼写错误。

于 2013-06-30T10:32:34.943 回答
0

在我运行的测试中,我发现运行时几乎没有区别。主要区别在于您似乎只运行了一次代码,而我循环了您的代码数千次然后取平均值。我的输出如下:

With the barrier
[0]: 1.65071e-05
[1]: 1.66872e-05
Without the barrier
[0]: 1.35653e-05
[1]: 1.30711e-05

所以我会假设你看到的任何变化都是你的操作系统而不是你的程序的结果。

另外,为什么要使用 MPI_Irecv 和 MPI_wait 而不仅仅是使用 MPI_recv?

于 2013-06-30T04:37:22.350 回答
0

您正在为您的 Irecv 等待两次相同的请求。第二个是需要所有时间的,并且由于它被跳过,排名 0 正在领先。

可以实现 MPI_BARRIER,这样如果进程进入算法,一些进程可以先于其他进程离开算法。这可能就是这里发生的事情。

于 2013-06-30T01:58:19.453 回答