【问题标题】:Huge difference in MPI_Wtime() after using MPI_Barrier()?使用 MPI_Barrier() 后 MPI_Wtime() 的巨大差异?
【发布时间】:2013-06-26 20:14:02
【问题描述】:

这是代码的一部分。

    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 秒(所有进程的最小值。例如根进程)。请解释一下?

【问题讨论】:

  • 如何以及在哪里初始化t1

标签: c++ c ipc mpi openmpi


【解决方案1】:

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

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

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

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

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

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

【讨论】:

【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

    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?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-18
      • 2020-01-22
      • 2019-04-21
      • 2010-10-15
      相关资源
      最近更新 更多