2013-07-13 67 views
1

MPI标准3.0表示在第5.13节该MPI_Bcast使用线程(OpenMP的)在MPI

最后,在多线程实现中,一个可以在一个过程中多于一个, 同时执行,集体通信呼叫。在 这些情况下,用户有责任确保在同一进程中通过两个不同的集体 通信调用同时使用相同的通信器。

我写了下面的程序不正确地执行(但编译)和转储芯

void main(int argc, char *argv[]) 
{ 
int required = MPI_THREAD_MULTIPLE, provided, rank, size, threadID, threadProcRank ; 
MPI_Comm comm = MPI_COMM_WORLD ; 

MPI_Init_thread(&argc, &argv, required, &provided); 
MPI_Comm_size(comm, &size); 
MPI_Comm_rank(comm, &rank); 

int buffer1[10000] = {0} ; 
int buffer2[10000] = {0} ; 

#pragma omp parallel private(threadID,threadProcRank) shared(comm, buffer1) 
{ 
    threadID = omp_get_thread_num(); 
    MPI_Comm_rank(comm, &threadProcRank); 
    printf("\nMy thread ID is %d and I am in process ranked %d", threadID, threadProcRank); 

    if(threadID == 0) 
     MPI_Bcast(buffer1, 10000, MPI_INTEGER, 0, comm); 

    If (threadID == 1) 
     MPI_Bcast(buffer1, 10000, MPI_INTEGER, 0, comm); 
} 

    MPI_Finalize(); 
} 

我的问题是:两个线程中的每个进程具有线程ID 0和线程ID 1柱的可以在根进程(即进程0)中作为MPI_Send()进行广播调用。我将它解释为MPI_Send()的两个循环,其中目标是其余进程。目标进程还会在线程ID 0和线程ID 1中发布MPI_Bcast()。这些可以被两个线程中的每个进程发布为两个MPI_Recv()。由于MPI_Bcast()是相同的 - 在接收由进程0(根)发送的消息时,应该没有匹配的问题。但是这个程序仍然不起作用。为什么?是否有可能在同一个传播者上的不同/相同的集体上混淆了信息?而且由于MPI(mpich2)认为这种可能性,它不允许同一个通信器上的两个集体同时等待吗?

回答

3

首先,您没有检查provided的值,其中MPI实现返回实际提供的线程支持级别。该标准允许这个水平比所要求的一个正确的MPI应用程序宁愿做这样的事情下:

MPI_Init_thread(&argc, &argv, required, &provided); 
if (provided < required) 
{ 
    printf("Error: MPI does not provide the required thread support\n"); 
    MPI_Abort(MPI_COMM_WORLD, 1); 
    exit(1); 
} 

其次,这行代码是多余的:

MPI_Comm_rank(comm, &threadProcRank); 

主题在MPI 不要有单独的行列 - 只有过程有排名。有人建议在MPI 3.0中引入所谓的端点,这将允许单个进程拥有多个等级并将它们绑定到不同的线程,但它并没有将其纳入到标准的最终版本中。

第三,您在两个集体中都使用相同的缓冲区变量。我想你的意图是在线程0中的调用中使用buffer1,并且在线程1中的调用中使用buffer2。另外,MPI_INTEGER是与Fortran中的INTEGER相对应的数据类型。对于C int,键入相应的MPI数据类型为MPI_INT

第四,MPI_BCAST作为MPI_SEND和相应的MPI_RECV循环的解释就是这样一种解释。实际上,实施方式有很大不同 - 请参阅here。例如,对于初始网络建立延迟远高于物理数据传输时间的较小消息,使用二进制和二叉树以最小化集体的等待时间。较大的消息通常会分成许多段,然后使用管道将段从根级传递到所有其他段。即使在树分布情况下,消息仍然可以被分割。

问题在于,实际上每个集体操作都是使用具有相同标签的消息来实现的,通常带有负值标签值(应用程序员不允许使用这些标签值)。这意味着在你的情况下MPI_Bcast调用将使用相同的标签来传输他们的消息,并且由于队伍将是相同的,并且沟通者是相同的,所以消息将全部混合起来。因此只有在不同的传播者之间进行并发集体的要求。

你的程序崩溃有两个原因。原因之一是MPI库不提供MPI_THREAD_MULTIPLE。第二个原因是如果消息被分成两个大小不一的块,例如一个较大的第一部分和一个较小的第二部分。两个集体调用之间的干扰可能导致第二个线程在等待第二个较小的块时接收指向第一个线程的较大的第一个块。结果将是消息截断,并且中止MPI错误处理程序将被调用。这通常不会导致段错误和核心转储,所以我会假设您的MPICH2不会被编译为线程安全的。

这不是MPICH2特有的。开放MPI和其他实现也容易受到相同的限制。

+0

谢谢您抽出时间详细回答。 –

+0

第一:我检查了提供的值,它是MPI_THREAD_MULTIPLE。第二:我故意看到哪个线程在哪个进程中THIRD:再次故意,因为我想MPI_Bcast()看起来相同。第四:你对二进制和二叉树的实现是正确的,但我期望2进程只有他们会直接去做一个简单的SEND和RECV。您对碎片做了一个很好的说明 - 我已经将它添加到了我的想法中:) FIFTH:某处MPI_Bcast()使用标记,因为我可以通过MPI_ANY_TAG发布MPI_Back()和MPI_Recv()。非常感谢! –