2011-01-23 81 views
3

所以这里的代码:OpenMP的线程“违” OMP屏障

#pragma omp parallel private (myId) 
{ 
    set_affinity(); 

    myId = omp_get_thread_num(); 

    if (myId<myConstant) 
    { 
    #pragma omp for schedule(static,1) 
    for(count = 0; count < AnotherConstant; count++) 
     { 
     //Do stuff, everything runs as it should 
     } 
    } 

#pragma omp barrier //all threads wait as they should 
#pragma omp single 
{ 
    //everything in here is executed by one thread as it should be 
} 
    #pragma omp barrier //this is the barrier in which threads run ahead 
    par_time(cc_time_tot, phi_time_tot, psi_time_tot); 
    #pragma omp barrier 
} 
//do more stuff 

我们解释一下怎么回事。在我的并行区域开始时,myId被设置为private,以便每个线程都有其正确的线程ID。 set_affinity()控制哪个线程在哪个内核上运行。我遇到的问题涉及计划的#pragma omp(静态,1)。

块:

if (myId<myConstant) 
    { 
    #pragma omp for schedule(static,1) 
    for(count = 0; count < AnotherConstant; count++) 
     { 
     //Do stuff, everything runs as it should 
     } 
    } 

表示了一些工作,我想通过myConstant-1分发超过一定数目的线程,0。在这些线程上,我想均匀地(以调度(静态,1)的方式)分配循环的迭代。这一切都正确执行。

然后代码进入一个区域,那里的所有命令都按照它们应该执行的方式执行。但是,如果我指定myConstant为2,那么如果我使用3个或更多线程运行,则通过单个材质执行的所有操作都将正确执行,但id为3或更大的线程不会等待单个内部的所有命令完成。

在单个内部调用一些函数,创建由所有线程执行的任务。 id为3或更多的线程(通常为myConstant或更多)继续执行,执行par_time(),而其他线程仍在执行由单个执行的函数创建的任务。 par_time()只是为每个线程打印一些数据。例如,如果我注释掉schedule(static,1)的编译指示omp,并且只让一个线程执行for循环(例如将if语句更改为if(myId == 0)),那么一切正常。所以我只是不确定为什么上述线程继续前进。

让我知道如果有什么困惑,这是一个特定的问题。我正在查看是否有人看到我的OMP流量控制缺陷。

+0

嗯,好吧,我发现有一个修复,但我不知道为什么。注释掉if语句似乎解决了这个问题,只有通过AnotherConstant的线程0似乎在for循环中被使用。这是保证吗?在for循环中可以使用带有任何id的线程,或者通过AnotherConstant它将始终为0。 – WtLgi 2011-01-23 01:09:39

回答

6

如果你看的OpenMP V3.0规范,2.5节工作分享结构,规定:

以下限制适用于 工作分享结构:

  • 每个工作共享区域必须由遇到团队中的所有主题 或根本没有。
  • 遇到的工作共享区域和屏障区域的序列必须 对于 团队中的每个线程都是相同的。

通过具有工作共享的内如果您违反了这两个限制,使你的程序不符合要求。根据规范,不符合要求的OpenMP程序具有“未指定”行为。

至于哪些线程将用于执行for循环,调度类型为“static,1”,第一个工作块 - 在本例中为count = 0 - 将分配给线程0.下一个块(count = 1)将被分配给线程1等,直到所有块被分配为止。如果块的数量多于线程,则分配将以循环方式在线程0重新启动。您可以阅读OpenMP规范中2.5.1循环结构的详细说明,并在说明中讨论计划子句。