6

朋友们,我正在努力学习 openMP 范式。我使用以下代码来理解 #omp for pragma。

int main(void){
int tid;
int i;

omp_set_num_threads(5);
#pragma omp parallel \
    private(tid)
{
    tid=omp_get_thread_num();
    printf("tid=%d started ...\n", tid);
    fflush(stdout);

    #pragma omp for
    for(i=1; i<=20; i++){
        printf("t%d - i%d \n",
                omp_get_thread_num(), i);
        fflush(stdout);
    }

    printf("tid=%d work done ...\n", tid);
}

return 0;

}

在上面的代码中,#pragma omp parallel 的末尾有一个隐式屏障,这意味着所有线程 0、1、2、3、4 必须到达那里才能进入下一条语句。

所以,为了检查这个障碍,我在条件 if(tid!=0) 中包含了这个“pragma for”,这意味着除了线程 0 (即 1、2、3、4)之外的所有线程都应该在循环中完成它们的工作并等待线程 0无限期地。但是,令我惊讶的是,这并没有发生。每个线程都在进行迭代并成功完成。即 t1 完成迭代 5,6,7,8 ---- t2 完成 9,10,11,12 ---- t3 完成 13,14,15,16 和 t4 完成 17,18,19,20。请注意:迭代 1、2、3、4 从未完成。

为了更深入地挖掘,我在 tid!=1 中包含了相同的 #pragma for in tid!=1,而不是 tid!=0,意思是 thread0,thread1 绕过了障碍。令我惊讶的是,程序现在挂起,所有线程都在等待 thread1。

有人可以告诉我这种意外行为的解释。挂起的最终代码:

int main(void){
int tid;
int i;

omp_set_num_threads(5);
#pragma omp parallel \
    private(tid)
{
    tid=omp_get_thread_num();
    printf("tid=%d started ...\n", tid);
    fflush(stdout);

    if(tid!=1){
        /* worksharing */
        #pragma omp for
        for(i=1; i<=20; i++){
            printf("t%d - i%d \n", 
                omp_get_thread_num(), i);
            fflush(stdout);
        }
    }else{
        printf("t1 reached here. \n");
    }

    printf("tid=%d work done ...\n", tid);
}

return 0;

}

我尝试设置我共享或私有,但它并没有改变程序的行为。

4

1 回答 1

6

这里的问题是标准未定义行为。从 OpenMP 3.1规范的第 2.5 节第 21 行开始(但文本从一开始就或多或少保持不变):

• 团队中的所有线程都必须遇到每个工作共享区域,或者根本不遇到。

omp for工作共享结构在哪里。所以是的,我通常也希望您的代码挂起,但编译器有权假设您正在做的事情永远不会发生,因此最终结果 - 它有时会挂起,但有时不会,具体取决于细节你坚持哪些线程——也许并不令人惊讶。

于 2012-01-25T13:34:09.440 回答