#pragma结束时的隐含障碍

pra*_*kar 6 parallel-processing openmp openmpi

朋友们,我正在尝试学习openMP范例.我使用以下代码来理解pragma的#omp.

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;
Run Code Online (Sandbox Code Playgroud)

}

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

所以,为了检查这个障碍,我在条件if(tid!= 0)中包含了这个"pragma for",这意味着除了线程0之外的所有线程,即1,2,3,4应该在循环中完成它们的工作并等待thread0无限期.但是,令我惊讶的是,这种情况并没有发生.每个线程都在进行迭代并成功完成.即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!= 0,我在tid中包含了相同的#pragma!= 1意味着而不是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;
Run Code Online (Sandbox Code Playgroud)

}

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

Jon*_*rsi 6

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

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

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

  • 并希望:"我从中学到的是:"我将来不会使用未定义的行为,因为它会导致各种意想不到的行为. (3认同)