使用MPI_Gatherv收集子集进程数据的调用规则疑问
MPI_Gatherv实现子集进程数据收集的方案 通信子内所有进程是否必须调用MPI_Gatherv
是。所有传入通信子(即你当前使用的MPI_COMM_WORLD)覆盖的进程,必须全部参与调用MPI_Gatherv。这是MPI集合通信的基础规则:所有集合操作都要求通信域内的进程全员参与,只要有一个进程未调用,其余进程会永久阻塞触发死锁,或直接产生未定义行为——哪怕你不需要某个进程收发数据,它也必须调用这个函数。
recvcounts数组是否支持部分元素取0
完全支持,这就是你当前场景下最简洁的标准解法,根本不需要新建通信子,参数按以下规则设置即可:
- 根进程侧:不需要接收哪个进程的数据,就把
recvcounts数组对应该进程rank的位置设为0,同位置的displs值随便填个合法整数即可(一般填0就行,count为0时MPI不会真的访问接收缓冲区的对应偏移位置,不存在内存越界问题)。MPI标准明确规定,某rank对应的recvcount为0时,根进程不会从该rank接收任何数据。 - 非根进程侧:不需要发送数据的进程,把自己调用
MPI_Gatherv时传入的sendcount参数设为0就行,此时sendbuf传任意合法指针都可以(部分老版本MPI实现会校验指针合法性,传个无意义的dummy变量地址比传空指针更稳妥),MPI识别到sendcount为0时,不会读取该进程的发送缓冲区,也不会向根进程传输有效数据。
其他标记忽略进程的方式
不需要额外的标记逻辑。recvcounts[i] = 0本身就是MPI标准原生支持的语义,作用就是告知根进程忽略rank为i的进程的发送数据,没有任何额外开销。反倒是你提到的新建通信子方案,需要额外执行一次集合通信完成通信域拆分,开销比直接设0 count大得多,在这个场景下完全没必要。
注意事项:根进程设置的
recvcounts0值项,必须和对应非根进程的sendcount=0设置一一匹配,否则会触发通信计数不匹配的运行时错误。该用法完全符合MPI官方规范,OpenMPI、MPICH、Intel MPI等所有主流MPI实现都原生支持,不存在兼容性问题。
内容的提问来源于stack exchange,提问作者bob.sacamento
相关产品推荐
相关产品推荐

