我试图在openmp线程中使用MPI_Allgather类功能。也就是说,所有线程将共同拥有一个数据副本(但每个都只生成一部分数据)。
通过在"标记"中使用线程ID来实际上在MPI_SEND和MPI_RECV的字段中,openmp线程之间的通信是可能的。但MPI_Allgather似乎并没有这样做。
我有2个MPI进程。每个进程都有2个openmp线程。现在,这4个线程中的每一个都计算数据的一部分。我想使用MPI_Allgather,以便所有线程组合他们的数据并拥有组合数据的副本。但似乎MPI_Allgather仅适用于MPI流程的粒度。
我将很感激有关如何做的任何建议。
谢谢!
答案 0 :(得分:0)
所有MPI通信调用称为 rank 的实体。目前,所有MPI实现都遵循 rank 等于 OS进程的解释,即不会共享内存空间的实体。原则上你可以通过制作消息标签来解决各个线程的问题是解决方法(或者更确切地说是黑客攻击) - 例如尝试为多个线程实现MPI_ANY_TAG
的模拟,没有无限循环和/或中央进程范围的调度机制。
在MPI-3.0的早期阶段有一个提议包括所谓的端点,它基本上是一种允许将一组排名分配给一组内部线程的机制。处理。该提案没有通过投票机制,文本必须进一步完善。
那就是说,以下是一种合理的方式来实现你想要的东西而不用pt2pt操作重新实现集体调用:
#pragma omp parallel shared(gbuf) private(buf,tid)
{
tid = omp_get_thread_num();
...
// Gather threads' data into the shared buffer 'gbuf'
// Data should start at gbuf[rank * num_threads * data_per_thread]
memcpy(gbuf + (rank*num_threads + tid)*data_per_thread,
buf, data_per_thread*size);
// Make sure all threads have finished copying their chunks
// then gather the data from all the other ranks
#pragma omp barrier
#pragma omp single
{
MPI_Allgather(MPI_IN_PLACE, 0, MPI_TYPE_NULL,
gbuf, num_threads*data_per_thread, data_type, comm);
}
...
}
首先将每个线程的本地缓冲区buf
中的数据收集到全局接收缓冲区gbuf
中。在此示例中,使用了简单的memcpy
,但如果使用复杂的派生数据类型,则可能涉及更多。正确收集本地数据后,就会使用就地MPI_Allgather
来收集其他进程的碎片。 single
构造确保每个进程只有一个线程可以进行聚合到所有的调用。
如果所有进程中的线程数不相同,则应使用MPI_Allgatherv
代替。