поддерживаю выше заданые вопросы
|
Введение в технологии параллельного программирования (OpenMP)
4.6. Распределение вычислительной нагрузки между потоками (распараллеливание по задачам при помощи директивы sections)
Напомним, что в рассмотренном ранее учебном материале для построения параллельных программ был изложен подход (см. разделы 5.2–5.3), обычно именуемый распараллеливанием по данным, в рамках которого обеспечивается одновременное (параллельное) выполнение одних и тех же вычислительных действий над разными наборами обрабатываемых данных (как, скажем, в нашем учебном примере, суммирование элементов разных строк матрицы). Другая также широко встречающаяся ситуация состоит в том, что для решения поставленной задачи необходимо выполнить разные процедуры обработки данных, при этом данные процедуры или полностью не зависят друг от друга, или же являются слабо связанными. В этом случае такие процедуры можно выполнить параллельно; такой подход обычно именуется распараллеливанием по задачам. Для поддержки такого способа организации параллельных вычислений в OpenMP для параллельного фрагмента программы, создаваемого при помощи директивы parallel, можно выделять параллельно выполняемые программные секции (директива sections).
Формат директивы sections имеет вид:
#pragma omp sections [<параметр> ...] { #pragma omp section <блок_программы> #pragma omp section <блок_программы> }
При помощи директивы sections выделяется программный код, который далее будет разделен на параллельно выполняемые секции. Директивы section определяют секции, которые могут быть выполнены параллельно (для первой по порядку секции директива section не является обязательной) – см. рис. 4.6.
В зависимости от взаимного сочетания количества потоков и количества определяемых секций, каждый поток может выполнить одну или несколько секций (вместе с тем, при малом количестве секций некоторые потоки могут оказаться без секций и окажутся незагруженными). Как результат, можно отметить, что использование секций достаточно сложно поддается масштабированию (настройке на число имеющихся потоков). Кроме того, важно помнить, что в соответствии со стандартом, порядок выполнения программных секций не определен, т. е. секции могут быть выполнены потоками в произвольном порядке.
В качестве примера использования директивы расширим нашу учебную задачу действиями по копированию обрабатываемой матрицы (в качестве исходного варианта используется пример 5.6):
total = 0; #pragma omp parallel shared(a,b) private(i,j) { #pragma omp sections /* Вычисление сумм строк и общей суммы */ for (i=0; i < NMAX; i++) { sum = 0; for (j=i; j < NMAX; j++) sum += a[i][j]; printf ("Сумма строки %d равна %f\n",i,sum); total = total + sum; } #pragma omp section /* Копирование матрицы */ for (i=0; i < NMAX; i++) { for (j=i; j < NMAX; j++) b[i][j] = a[i][j]; } } /* Завершение параллельного фрагмента */ printf ("Общая сумма матрицы равна %f\n",total);4.11.
Для обсуждения примера можно отметить, что выполняемые в программе вычисления (суммирование и копирование элементов) можно было бы объединить в рамках одних и тех же циклов, однако приведенное разделение тоже может оказаться полезным, поскольку в результате разделения данные вычисления могут быть легко векторизованы (конвейеризированы) компилятором. Важно отметить также, что сформированные подобным образом программные секции не сбалансированы по вычислительной нагрузке (первая секция содержит больший объем вычислений).
В качестве параметров директивы sections могут использоваться:
- private (list)
- firstprivate (list)
- lastprivate (list)
- reduction (operator: list)
- nowait
4.7. Расширенные возможности OpenMP
4.7.1 Определение однопотоковых участков для параллельных фрагментов (директивы single и master)
При выполнении параллельных фрагментов может оказаться необходимым реализовать часть программного кода только одним потоком (например, открытие файла). Данную возможность в OpenMP обеспечивают директивы single и master.
Формат директивы single имеет вид:
#pragma omp single <параметр> ...] < блок_программы>
Директива single определяет блок параллельного фрагмента, который должен быть выполнен только одним потоком; все остальные потоки ожидают завершения выполнения данного блока (если не указан параметр nowait) – см. рис. 4.7.
В качестве параметров директивы могут использоваться:
- private (list)
- firstprivate (list)
- copyprivate (list)
- nowait
Новым в приведенном списке является только параметр copyprivate, который обеспечивает копирование переменных, указанных в списке list, после выполнения блока директивы single в локальные переменные всех остальных потоков.
Формат директивы master имеет вид:
#pragma omp master <блок_программы>
Директива master определяет фрагмент кода, который должен быть выполнен только основным потоком; все остальные потоки пропускают данный фрагмент кода (завершение директивы по умолчанию не синхронизируется).