1

MPI_Isend在 MPI 中,有诸如和之类的非阻塞调用MPI_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.

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

4

3 回答 3

3

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

无论如何,我会将您的 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 作为消息源的等级。似乎您的服务器除了服务请求之外没有任何事情可做,因此无需使用异步接收。代码将是:

while(true){
    MPI_Recv(... ,MPI_ANY_SOURCE, REQUEST_TAG,MPI_comm,status)
    //retrieve client id from status and do something
}
于 2013-02-09T23:06:24.853 回答
1

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

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

如果有未完成的 MPI_Irecv 调用,但应用程序已到达正常处理的末尾,则 MPI_Cancel 那些未完成的调用是“必要的”。未能做到这一点可能会在 MPI_Finalize 中被捕获为错误。

MPI_ANY_SOURCE 上的单个 MPI_Irecv(或只是 MPI_Recv,取决于消息处理的积极程度)也提供了一个合理的解决方案。如果接收到的数据量“大”并且可以在处理后安全丢弃,这种方法也很有用。一次处理单个传入缓冲区可以减少所需的总系统资源,但会以串行化处理为代价。

于 2013-02-10T05:01:50.270 回答
0

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

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 实现之一 - Open MPI - 在MPI_THREAD_MULTIPLE级别初始化时仍然不支持本机 InfiniBand 通信(InfiniBand 是非常快速的低延迟结构,目前在大多数 HPC 集群中使用),因此切换到不同的,通常更慢且延迟更高的传输,例如常规以太网上的 TCP/IP 或 InfiniBand 上的 IP。还有一些超级计算机供应商,其 MPI 实现不支持MPI_THREAD_MULTIPLE根本上,通常是因为硬件的工作方式。

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

于 2013-02-10T11:21:22.047 回答