结合MPI_Allgather和openmp并行

时间:2013-09-26 16:30:01

标签: mpi openmp

我试图在openmp线程中使用MPI_Allgather类功能。也就是说,所有线程将共同拥有一个数据副本(但每个都只生成一部分数据)。

通过在"标记"中使用线程ID来实际上在MPI_SEND和MPI_RECV的字段中,openmp线程之间的通信是可能的。但MPI_Allgather似乎并没有这样做。

实施例

我有2个MPI进程。每个进程都有2个openmp线程。现在,这4个线程中的每一个都计算数据的一部分。我想使用MPI_Allgather,以便所有线程组合他们的数据并拥有组合数据的副本。但似乎MPI_Allgather仅适用于MPI流程的粒度。

我将很感激有关如何做的任何建议。

谢谢!

1 个答案:

答案 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代替。