Как работает директива SECTIONS в OpenMP? - PullRequest
39 голосов
/ 05 мая 2010

В OpenMP при использовании omp sections будут ли потоки распределены по блокам внутри секций , или каждый поток будет назначен для каждой секции?

Когда nthreads == 3:

#pragma omp sections
{
    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }

    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }
}

Выход:

id=1
id=1

Но когда я выполняю следующий код:

#pragma omp sections
{
    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }

    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }
}

#pragma omp sections
{
    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }

    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }
}

Выход:

id=1
id=1

id=2
id=2

Из этих выводов я не могу понять, какова концепция разделов в OpenMP.

Ответы [ 8 ]

92 голосов
/ 10 октября 2013

Код, публикуемый OP, никогда не будет выполняться параллельно, , поскольку ключевое слово parallel не отображается . Тот факт, что ОП получил идентификаторы, отличные от 0, показывает, что, вероятно, его код был встроен в параллельную директиву. Однако это не ясно из его поста и может запутать новичков.

Минимальный разумный пример (для первого примера, опубликованного ОП):

#pragma omp parallel sections
{
    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }

    #pragma omp section
    { 
        printf ("id = %d, \n", omp_get_thread_num());
    }
}

На моей машине это печатает

id = 0,
id = 1,

показывает, что эти два раздела выполняются разными потоками.

Стоит отметить, что, однако, этот код не может извлечь больше параллелизма, чем два потока: если он выполняется с большим количеством потоков, другие потоки не имеют никакой работы и будут просто сидеть без дела.

26 голосов
/ 05 мая 2010

Идея параллельных секций состоит в том, чтобы дать компилятору подсказку, что различные (внутренние) секции могут выполняться параллельно, например:

#pragma omp parallel sections
{
   #pragma omp section
   {
      /* Executes in thread 1 */
   } 
   #pragma omp section
   {
      /* Executes in thread 2 */
   } 
   #pragma omp section
   {
      /* Executes in thread 3 */
   } 
   /* ... */
}

Это подсказка компилятору, и она не гарантируется, хотя это и должно произойти. Ваш вывод - это то, что ожидается; он говорит, что есть # секции, выполняемые в потоке с идентификатором 1 и в потоке 2. Порядок вывода недетерминирован, так как вы не знаете, какой поток будет выполняться первым.

12 голосов
/ 16 ноября 2013

Изменить первую строку с

# прагма omp секции

в

# параллельные секции pragma omp

«параллельная» директива гарантирует, что две секции назначаются двум потокам. Затем вы получите следующий вывод id = 0, id = 1,

9 голосов
/ 09 мая 2014

Вам не хватает ключевого слова parallel. Ключевое слово parallel запускает параллельный запуск openmp.

4 голосов
/ 11 октября 2013

Согласно стандарт OpenMP 3.1 , раздел 2.5.2 (выделено):

Конструкция section является неитеративной конструкцией разделения рабочих мест, которая содержит набор структурированных блоков, которые должны быть распределены между и выполняется потоками в команде . Каждый структурированный блок выполняется один раз одним из потоков в команде в контексте ее неявная задача.

...

Каждому структурированному блоку в конструкции разделов предшествует директива раздела, за исключением, возможно, первого блока, для которого Директива предыдущего раздела не является обязательной. Метод планирования структурированные блоки среди потоков в команде это реализация определен . В конце секций есть неявный барьер конструкция, если не указано предложение nowait.

Итак, применяя эти правила к вашему делу, мы можем утверждать, что:

  1. различные структурированные блоки, определенные в директиве sections, выполняются один раз, одним потоком . Другими словами, у вас всегда четыре отпечатка, в зависимости от количества нитей
  2. блоки в первом sections будут выполнены (в недетерминированном порядке) до блоков во втором sections (также выполнены в недетерминированном порядке). Это из-за неявного барьера в конце конструкций разделения работы
  3. планирование реализация определена , так что вы не можете контролировать, какой поток был назначен данному разделу

Таким образом, ваш вывод связан с тем, как планировщик решил назначить разные блоки потокам в команде.

2 голосов
/ 29 декабря 2013

Может быть полезно добавить дополнительную информацию в строку вывода и добавить дополнительные секции (если у вас есть счетчик потоков)

#pragma omp parallel sections
{
    #pragma omp section
    {
        printf ("section 1 id = %d, \n", omp_get_thread_num()); 
    }
    #pragma omp section
    {
        printf ("section 2 id = %d, \n", omp_get_thread_num());
    }
    #pragma omp section
    {
        printf ("section 3 id = %d, \n", omp_get_thread_num());
    }
}

Тогда вы можете получить более интересный вывод:

section 1 id = 4,
section 3 id = 3,
section 2 id = 1,

, который показывает, как разделы могут быть выполнены в любом порядке, любым доступным потоком.

0 голосов
/ 14 сентября 2013

Обратите внимание, что nowait сообщает компилятору, что потокам не нужно ждать выхода раздела. В Фортране nowait идет в конце цикла или раздела, что делает это более очевидным.

0 голосов
/ 08 ноября 2012

Если вы действительно хотите запускать разные потоки в разных разделах, предложение nowait сообщает компилятору, что потокам не нужно ждать, чтобы войти в раздел.

#pragma omp parallel sections nowait
{
   ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...