MPI非阻塞通信和pthreads的区别?

时间:2013-02-09 22:32:58

标签: client-server mpi p2p

在MPI中,有MPI_IsendMPI_Irecv等非阻止调用。

如果我正在开发一个p2p项目,服务器会收听许多客户端。

一种方法:

for(int i = 1; i < highest_rank; i++){
    MPI_Irecv(....,i,....statuses[i]); //listening to all slaves
}
while(true){
   for( int i = 1; i < highest_rank; i++){
         checkStatus(statuses[i])
         if true do somthing
}

我能做到的另一个老方法是:

Server creating many POSIX threads, pass in a function, 
that function will call MPI_Recv and loop forever.

理论上,哪一个在服务器端执行得更快?如果有另一种更好的方法来编写服务器,请告诉我。

3 个答案:

答案 0 :(得分:3)

后一种解决方案对我来说似乎并不高效,因为在MPI流程中管理pthreads会产生所有开销。

无论如何,我会把你的MPI代码重写为:

for(int i = 1; i < highest_rank; i++){
   MPI_Irev(....,i,....requests[i]); //listening to all slaves
}
while(true){
   MPI_waitany(highest_rank, request[i], index, status);
   //do something useful

}

更好的是,你可以使用MPI_Recv和MPI_ANY_SOURCE作为消息来源的等级。看起来您的服务器除了服务请求之外没有任何操作,因此不需要使用异步recv。 代码是:

while(true){
    MPI_Recv(... ,MPI_ANY_SOURCE, REQUEST_TAG,MPI_comm,status)
    //retrieve client id from status and do something
}

答案 1 :(得分:1)

调用MPI_Irecv时,在调用并成功完成AFTER MPI_Test *或MPI_Wait *之前测试recv缓冲区是不安全的。在不进行这些调用的情况下直接测试缓冲区的行为取决于实现(范围从非如此差到段错误)。

可以使每个远程等级的一个MPI_Irecv设置1:1映射。根据发送的数据量以及收到数据的生命周期,此方法可能会消耗不可接受的系统资源量。使用MPI_Testany或MPI_Testall可能会在消息处理和CPU负载之间提供最佳平衡。如果在等待传入消息时不需要进行非MPI处理,则MPI_Waitany或MPI_Waitall可能更可取。

如果有未完成的MPI_Irecv调用,但应用程序已经到了正常处理的结束,那么MPI_Cancel那些未完成的调用是“必要的”。如果不这样做,可能会在MPI_Finalize中将其作为错误捕获。

MPI_ANY_SOURCE上的单个MPI_Irecv(或者只是MPI_Recv,取决于消息处理需要多大程度)也提供了合理的解决方案。如果接收的数据量“大”并且可以在处理之后安全地丢弃,则该方法也是有用的。一次处理单个传入缓冲区可以减少所需的总系统资源,但代价是序列化处理。

答案 2 :(得分:0)

让我简单评论一下您使用POSIX线程(或者其他任何可能的线程机制)的想法。同时从多个线程进行MPI调用需要使用MPI_THREAD_MULTIPLE的最高级别的线程支持来初始化MPI实现:

int provided;

MPI_Init_thread(&argv, &argc, MPI_THREAD_MULTIPLE, &provided);
if (provided != MPI_THREAD_MULTIPLE)
{
    printf("Error: MPI does not provide full thread support!\n");
    MPI_Abort(MPI_COMM_WORLD, 1);
}

尽管很久以前MPI标准中引入了支持来自不同线程的并发调用的选项,但仍有MPI实现难以提供完全可用的多线程支持。 MPI就是写便携式,至少在理论上是应用程序,但在这种情况下,现实生活与理论的差别很大。例如,最广泛使用的开源MPI实现之一 - 开放式MPI - 在MPI_THREAD_MULTIPLE初始化时仍然不支持本机InfiniBand通信(InfiniBand是非常快速的低延迟结构,现在在大多数HPC集群中使用)。因此,通过常规以太网或IP-over-InfiniBand,可以切换到不同的,通常更慢且具有更高延迟的传输,如TCP / IP。还有一些超级计算机供应商,其MPI实现根本不支持MPI_THREAD_MULTIPLE,通常是因为硬件的工作方式。

此外,MPI_Recv是一个阻塞调用,它会导致正确的线程取消问题(如果需要)。你必须确保所有线程以某种方式逃脱无限循环,例如通过让每个工作人员发送带有适当标签或其他协议的终止消息。