2016-07-20 2 views
0

Я пишу параллельный код, который использует некоторый параллелизм на внешнем уровне. По существу, есть две отдельные подпрограммы (очень дорогие), которые могут выполняться одновременно. Это большой код, и, как таковой, внутри каждой подпрограммы есть другие вызовы, а также многие области параллельных/do omp. Таким образом, чтобы выполнить свои две подпрограммы я хочу использовать вложенной параллельности, так что они оба могут называться во внешней области, как, например:Объявление другого вложенного количества потоков для двух отдельных задач (OpenMP)

!$omp parallel 

    !$omp single 
     ! Do the first expensive task (contains more omp parallel regions) 
    !$omp end single nowait 

    !$omp single 
     ! Do the second expensive task (contains more omp parallel regions) 
    !$omp end single nowait 

!$omp end parallel 

Если оба этих дорогостоящих задач принимали равное количество времени, я бы не проблема. Но во время моделирования на каждом временном шаге количество, которое каждый должен делать, изменяется. Таким образом, переменная среды для установки вложенного числа потоков, таких как export OMP_NUM_THREADS=16,8, где у меня 16 на первом уровне параллелизма и 8 в вложенных регионах (внутри двух дорогих подпрограмм), не работает. У меня есть схема для распределения правильного количества потоков в их соответствующей задаче, я просто не знаю, как установить разные количества потоков для вложенного уровня в соответствующие подпрограммы. Конечно, я мог бы пойти в каждую дорогую подпрограмму и все подпрограммы внутри них и на самом деле жестко указать количество потоков, которые мне бы хотелось, но, как я уже говорил, это очень большой код, и это уродливое решение. Я бы предпочел сделать это в виде переменной среды. На эту тему нет информации. Кто-нибудь знает, как можно это сделать?

Заранее спасибо.

ответ

0

Я не уверен, правильно ли я понимаю, чего вы пытаетесь достичь, но вы можете установить размер команды по умолчанию для вложенных параллельных областей, просто позвонив omp_set_num_threads(). Если вы вызовете его из последовательной части приложения, он установит размер команды по умолчанию для параллельных регионов верхнего уровня. Если вы вызовете его из параллельного региона, это повлияет на вложенные параллельные области, порожденные вызывающим потоком. И разные потоки могут устанавливать разные размеры команд для своих вложенных регионов. Так, в двух словах, вы можете сделать что-то вроде:

!$omp parallel 

    !$omp single 
     call omp_set_num_threads(nn) 
     ! Do the first expensive task (contains more omp parallel regions) 
    !$omp end single nowait 

    !$omp single 
     call omp_set_num_threads(mm) 
     ! Do the second expensive task (contains more omp parallel regions) 
    !$omp end single nowait 

!$omp end parallel 

Параллельные регионы порожден от нити, выполняющей первый сингл конструкции будет выполняться с nn нитями. Параллельные области, порожденные потоком, выполняющим вторую одиночную конструкцию, выполняются с потоками mm.

Кроме того, рассмотрели ли вы использование явных задач OpenMP (!$omp task) вместо single + nowait?

+0

@Hristo_lliev Спасибо за ваш быстрый ответ. То, что вы предложили, это то, что перешло мне в голову, но я не верил, что это будет эффективно. Я должен был попробовать его перед публикацией, но я думал, что переменная окружения переопределит эти операторы вызова omp_set_num_threads. Надеюсь, это так просто, и я попробую это сейчас. Что касается явной конструкции задачи, у меня были смешанные результаты, используя это в более простых кодах. Считаете ли вы, что динамическое планирование работы, выполненное конструкцией задачи, поможет решить проблему балансировки нагрузки без вмешательства пользователя? – teamzissouv2

+0

Предложение 'num_threads' (как в'! $ Omp parallel num_threads (x) ') переопределяет значение, заданное' omp_set_num_threads() ', что переопределяет значение, заданное в среде. Что касается второго вопроса, я понятия не имею - это зависит от того, какая работа выполняется. –

+0

Еще раз спасибо. – teamzissouv2