Неявный барьер в конце #pragma для

Друзья, пытаюсь изучить парадигму openMP. Я использовал следующий код, чтобы понять #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;

}

В приведенном выше коде есть неявный барьер в конце #pragma omp parallel, что означает, что все потоки 0,1,2,3,4 должны достичь его, прежде чем перейти к следующему оператору.

Итак, чтобы проверить этот барьер, я заключил эту «прагму для» в условие if (tid! = 0), что означает, что все потоки, кроме потока 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! = 0 я заключил ту же самую #pragma for в tid! = 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;

}

Я попытался установить общий или частный доступ, но это не повлияло на поведение программы.


person prathmesh.kallurkar    schedule 25.01.2012    source источник
comment
#pragma omp for предоставляет способ избавиться от неявного барьера в конце цикла с помощью ключевого слова nowait, но я его не использовал.   -  person prathmesh.kallurkar    schedule 25.01.2012
comment
1) i должен быть приватным. 2) omp for как конструкция разделения работы разделяет работу с уже существующими потоками. Поскольку поток 1 зависает для выполнения цикла for с разделением работы, вы блокируете себя. См. конструкции совместной работы   -  person Bort    schedule 25.01.2012
comment
Проверка основных и рабочих потоков и т.п. больше подходит для стиля mpi или pthread. Идея openmp состоит в том, чтобы избавиться от всей этой возни между мастером и остальными. Конечно, это можно сделать, но вы можете захотеть разделить задачи между разными потоками довольно сильно.   -  person Bort    schedule 25.01.2012
comment
@ Bort: даже я не хочу кодировать таким образом, когда я действительно решаю проблемы, но меня смущает реализация openmp. Я выполнил еще одну проверку, чтобы увидеть, зависала ли программа, есть ли разрыв между количеством потоков, входящих в цикл, то есть 0,2,3,4. Поэтому я заменил условие на if (tid == 1 || tid == 4 || tid == 5). Но программа теперь не зависает. Итак, в главном потоке есть что-то особенное, чего я не могу здесь понять.   -  person prathmesh.kallurkar    schedule 25.01.2012


Ответы (1)


Проблема здесь в том, что поведение не определено стандартом. Из раздела 2.5, строка 21 спецификации OpenMP 3.1 (но текст остался прежним) или меньше с начала):

• Каждый регион совместной работы должен встречаться всеми потоками в группе или вообще ни одним.

Где omp for - конструкция для совместной работы. Так что да, я тоже обычно ожидаю зависания с вашим кодом, но компилятор имеет право предполагать, что то, что вы делаете, никогда не произойдет, и поэтому конечный результат - иногда он зависает, а иногда нет, в зависимости от деталей на каких тредах вы держитесь - может быть, неудивительно.

person Jonathan Dursi    schedule 25.01.2012
comment
спасибо за ссылку. Даже я знал, что это имеет неопределенное поведение, но все же пошел дальше, чтобы узнать фактическую реализацию библиотеки openMP. Я извлек из этого урок: на каждый параллельный блок реализуется только один барьер. Таким образом, передача сигналов от одного потока к другому работает через разные барьеры в одном параллельном блоке. - person prathmesh.kallurkar; 25.01.2012
comment
и надеюсь: My learning from this was : Я не буду использовать неопределенное поведение в будущем, потому что это вызовет все виды неожиданного поведения. - person Bort; 26.01.2012