openmp учебник
Начало работы с openmp
Поиск…
замечания
OpenMP (Open MultiProcessing) - это модель параллельного программирования, основанная на директивах компилятора, которая позволяет разработчикам приложений постепенно добавлять параллелизм к их кодам приложений.
Спецификация OpenMP API для параллельного программирования предоставляет интерфейс прикладного программирования (API), поддерживающий многопроцессорное многопроцессорное многопроцессорное программирование на C, C ++ и Fortran на большинстве платформ. Он состоит из набора директив компилятора, подпрограмм библиотеки и переменных среды, которые влияют на поведение во время выполнения.
Поскольку OpenMP фокусируется на параллелизме внутри узла (многопроцессорность с общей памятью), его можно комбинировать с моделями программирования передачи сообщений, такими как MPI, для выполнения на нескольких узлах.
Версии
Версия | язык | Дата выхода |
---|---|---|
4.5 | C / C ++ / Fortran | 2015-11-01 |
4,0 | C / C ++ / Fortran | 2013-07-01 |
3,1 | C / C ++ / Fortran | 2011-07-01 |
3.0 | C / C ++ / Fortran | 2008-05-01 |
2.5 | C / C ++ / Fortran | 2005-05-01 |
2.0c | C / C ++ | 2002-03-01 |
2.0f | Фортран | 2000-11-01 |
1.0c | C / C ++ | 1998-10-01 |
1.0f | Фортран | 1997-10-01 |
компиляция
Существует много компиляторов, которые поддерживают разные версии спецификации OpenMP. OpenMP поддерживает список здесь с компилятором, который поддерживает его и поддерживаемую версию. В общем случае для компиляции (и связывания) приложения с поддержкой OpenMP вам нужно только добавить флаг компиляции, и если вы используете OpenMP API, вам необходимо включить заголовок OpenMP (omp.h). Хотя заголовочный файл имеет фиксированное имя, флаг компиляции зависит от компилятора. Ниже приведен неисчерпывающий список компиляторов и флаг, который разрешает OpenMP.
- GCC (включая gcc, g ++ и gfortran):
-fopenmp
- LLVM: -fopenmp
- Intel compiler-suite (включая icc, icpc и ifort):
-qopenmp
(и-fopenmp
для совместимости с GCC / LLVM) - Набор компиляторов IBM XL (включая xlc, xlC и xlf):
-xlsmp=omp
- Компилятор PGI-пакета (включая pgcc pgc ++ pgfortran): '-mp'
Параллельный мир привет с использованием OpenMP
#include <omp.h>
#include <stdio.h>
int main (int argc, char *argv[])
{
#pragma omp parallel
{
printf ("Hello world! I'm thread %d out of %d threads.\n",
omp_get_thread_num(), omp_get_num_threads());
}
return 0;
}
Этот код просто создает группу потоков (в соответствии с переменной окружения OMP_NUM_THREADS
- и если не определен, будет создаваться по одному для каждого логического ядра в системе), и каждый поток идентифицирует себя, помимо печати типичного приветственного сообщения Hello.
Конструкция совместного использования - пример цикла for
double res[MAX]; int i;
#pragma omp parallel
{
#pragma omp for
for (i=0;i< MAX; i++) {
res[i] = huge();
}
}
Цикл for будет выполняться параллельно. Огромный () - это некоторый метод, который может занять слишком много времени, чтобы получить выполнение. OpenMP поддерживает ярлык для написания вышеуказанного кода как:
double res[MAX]; int i;
#pragma omp parallel for
for (i=0;i< MAX; i++) {
res[i] = huge();
}
Мы также можем иметь предложение расписания, которое влияет на то, как итерации цикла сопоставляются потокам. Например:
#pragma omp parallel
#pragma omp for schedule(static)
for(i=0;I<N;i++) {
a[i] = a[i] + b[i];
}
Различные стили планирования:
расписание (статический [, кусок])
Выделите блоки итераций размера «кусок» для каждой нити.
Если не указано: распределите как можно равномернее доступные потоки
График (динамический [, фрагмент])
Каждый поток захватывает итерации «chunk» с очереди, пока не будут обработаны все итерации.
График (руководствуясь [, фрагмент])
Темы динамически захватывают блоки итераций. Размер блока начинается с большого размера и уменьшается до размера «кусок» по мере того, как вычисление продолжается.
график (выполнения)
Расписание и размер блока, взятые из переменной среды OMP_SCHEDULE.
Пример сокращения
#include <omp.h>
void main ()
{
int i;
double ZZ, func(), res=0.0;
#pragma omp parallel for reduction(+:res) private(ZZ)
for (i=0; i< 1000; i++){
ZZ = func(I);
res = res + ZZ;
}
}
В последней строке: Фактически добавляется в частную копию, затем объединяется после цикла. Компилятор заботится о деталях.