Omp num threads linux

Основные конструкции OpenMP

В этом разделе рассмотрим некоторые специфические особенности реализации директив OpenMP.

Количество потоков в параллельной программе определяется либо значением переменной окружения OMP_NUM_THREADS , либо специальными функциями, вызываемыми внутри самой программы. Задание переменной окружения OMP_NUM_THREADS в операционной системе Linux осуществляется следующим образом с помощью команды

export OMP_NUM_THREADS=256

Здесь было задано 256 параллельных потоков.

Просмотреть состояние переменной окружения OMP_NUM_THREADS можно, например, с помощью следующей команды:

export | grep OMP_NUM_THREADS

Каждый поток имеет свой номер thread_number , начинающийся от нуля (для главного потока) и заканчивающийся OMP_NUM_THREADS-1 . Определить номер текущего потока можно с помощью функции omp_get_thread_num() .

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

Пример ветвления во фрагменте программы, написанной на языке C/C++, в зависимости от номера параллельного потока показан в примере 2.8.

В этом примере в первой строке параллельного блока вызывается функция omp_get_thread_num , возвращающая номер параллельного потока. Этот номер сохраняется в локальной переменной myid .Далее в зависимости от значения переменной myid вызывается либо функция do_something() в первом параллельном потоке с номером 0, либо функция do_something_else(myid) во всех остальных параллельных потоках.

В OpenMP существуют различные режимы выполнения ( Execution Mode ) параллельных структурных блоков. Возможны следующие режимы:

  • Динамический режим (Dynamic Mode). Этот режим установлен по умолчанию и определяется заданием переменной окружения OMP_DYNAMIC в операционной системе Linux. Задать эту переменную можно, например, с помощью следующей команды операционной системы Linux:

Кроме того, существует возможность задать этот режим и саму переменную внутри программы, вызвав функцию

Отметим, что на компьютерах Silicon Graphics S350 и Kraftway G-Scale S350 вторая возможность отсутствует. В динамическом режиме количество потоков определяется самой операционной системой в соответствии со значением переменной окружения OMP_NUM_THREADS .В процессе выполнения параллельной программы при переходе от одной области распараллеливания к другой эта переменная может изменять свое значение;

Читайте также:  Настройка cisco anyconnect vpn linux

Кроме того, существует возможность задать этот режим и саму переменную внутри программы, вызвав функцию

Кроме того, существует возможность задать этот режим и саму переменную внутри программы, вызвав функцию

omp_set_nested( TRUE | FALSE )

Директивы OpenMP

Теперь перейдем к подробному рассмотрению директив OpenMP и механизмов их реализации.

Директивы shared, private и default

Эти директивы (предложения OpenMP) используются для описания типов переменных внутри параллельных потоков.

определяет переменные var1, var2, …, varN как общие переменные для всех потоков. Они размещаются в одной и той же области памяти для всех потоков.

определяет переменные var1, var2, …, varN как локальные переменные для каждого из параллельных потоков. В каждом из потоков эти переменные имеют собственные значения и относятся к различным областям памяти: локальным областям памяти каждого конкретного параллельного потока.

В качестве иллюстрации использования директив OpenMP shared и private рассмотрим фрагмент программы (Пример 2.9). В этом примере переменная a определена как общая и является идентификатором одномерного массива. Переменные myid и x определены как локальные переменные для каждого из параллельных потоков. В каждом из параллельных потоков локальные переменные получают собственные значения. После чего при выполнении условия x

c$omp parallel shared (a) c$omp& private (myid, x) myid = omp_get_thread_num ( ) x = work (myid) if (x < 1.0) then a (myid) = x endif
default ( shared | private | none )

задает тип всех переменных, определяемых по умолчанию в последующем параллельном структурном блоке как shared , private или none . Например, если во фрагменте программы (примере 2.9) вместо

то определяемые далее по умолчанию переменные myid и x будут автоматически определены как private .

Директивы firstprivate и lastprivate

Директивы (предложения) OpenMP firstprivate и lastprivate используются для описания локальных переменных, инициализируемых внутри параллельных потоков. Переменные, описанные как firstprivate , получают свои значения из последовательной части программы. Переменные, описанные как lastprivate , сохраняют свои значения при выходе из параллельных потоков при условии их последовательного выполнения.

firstprivate( var1, var2, . varN )

определяет переменные var1, var2, . varN как локальные переменные для каждого из параллельных потоков, причем инициализация значений этих переменных происходит в самом начале параллельного структурного блока по значениям из предшествующего последовательного структурного блока программы.

В качестве иллюстрации рассмотрим фрагмент программы (Пример 2.10). В этом примере в каждом параллельном потоке используется своя переменная c , но значение этой переменной перед входом в параллельный блок программы берется из предшествующего последовательного блока.

program first integer :: myid, c integer, external :: omp_get_thread_num c=98 !$omp parallel private (myid) !$omp& firstprivate (c) myid = omp_get_thread_num ( ) write (6, *) 'T: ', myid, 'c=', c !$omp end parallel end program first
T:1 с=98 T:3 с=98 T:2 с=98 T:0 с=98
lastprivate( var1, var2, . varN )

определяет переменные var1, var2, . varN как локальные переменные для каждого из параллельных потоков, причем значения этих переменных сохраняются при выходе из параллельного структурного блока при условии, что параллельные потоки выполнялись в последовательном порядке.

Читайте также:  Линукс время блокировки экрана

В качестве иллюстрации рассмотрим фрагмент программы (Пример 2.11). В этом примере локальная переменная i принимает различные значения в каждом потоке параллельного структурного блока. После завершения параллельного структурного блока переменная i сохраняет свое последнее значение, полученное в последнем параллельном потоке, при условии последовательного выполнения всех параллельных потоков, т. е. n=N+1 .

c$omp do shared ( x ) c$omp& lastprivate ( i) do i = 1, N x (i) = a enddo n = i

Источник

How can I set the number of OpenMP threads from within the program?

from main before calling any OpenMP-enabled functions, this seems to have no effect. Why is this happening? How can I set the number of OpenMP threads from within the program, if it's possible at all?

1 Answer 1

There are two ways 1 one can use to set the number of threads from within the program:

Option #1

Use num_threads clause in a directive that opens a parallel region:

#pragma omp parallel num_threads(number_of_threads) 

Option #2

Use omp_set_num_threads API function before a parallel region begins:

#include // . omp_set_num_threads(number_of_threads); #pragma omp parallel 

Note: Both options take priority over OMP_NUM_THREADS environment variable, but num_threads clause has precedence over omp_set_num_threads .

This is covered in the OpenMP specification (emphasis mine):

Chapter 4

Environment Variables

[. ] Modifications to the environment variables after the program has started, even if modified by the program itself, are ignored by the OpenMP implementation. However, the settings of some of the ICVs can be modified during the execution of the OpenMP program by the use of the appropriate directive clauses or OpenMP API routines. [. ]

1) There is a third run-time option that allows to alter the number of threads executing a parallel region that follows by resetting it to 1 (master thread only) or to the number from num_threads clause or omp_set_num_threads call, which is an if clause in a directive the clause belongs to.

Читайте также:  Linux create new user command

Источник

Компиляция и запуск приложений с OpenMP

OpenMP подключается опцией, соответствующей установленному компиляторy:

gcc/gfortran -fopenmp GNU icc/ifort -openmp Intel (по умолчанию на umt) pgcc/pgCC/pgf77/pgfortran -mp PGI 

Так, компиляция файла exam.c на umt компилятором Intel (с учетом умолчания) выполняется командой

icc -openmp exam_omp.c -o exam_omp 
mpicc -openmp exam_omp.c -o exam_omp 

Число параллельных нитей OpenMP задается с помощью переменной окружения OMP_NUM_THREADS. Как правило, она устанавливается перед запуском программы из командной строки командой вида

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

При запуске приложения пользователю необходимо указать число ядер (cpus) для каждого из процессов (task) с помощью опции --cpus-per-task= . При этом система предоставляет узел для процесса, если на нем имеется указанное число свободных ядер. Максимальное число ядер, равное 36, содержат узлы раздела apollo (см. Кластер "Уран"). Пусть задано export OMP_NUM_THREADS=12 , тогда в результате выполнения команды интерактивного запуска

srun --cpus-per-task=6 exam_omp > exam_omp.out 

одному (n=1 по умолчанию) процессу (task), т.е. задаче, пользователя будет выделено 6 ядер на узле и при вычислениях будет задействовано 12 нитей; результаты вычислений будут записаны в указанный пользователем файл exam_omp.out .

Если программе нужен запуск на узле с большим объёмом оперативной памяти, то надо добавить опцию --mem= , где - требуемый объём памяти на узле. Например, команда

srun --mem=48G --cpus-per-task=12 exam_omp > exam_omp.out 

запустит один процесс на узле с оперативной памятью не меньшей, чем 48 GB (о типах узлов см. Кластер "Уран"). Для заказа памяти из расчета на одно ядро используется опция --mem-per-cpu= , например,

srun --mem-per-cpu=4G --cpus-per-task=12 exam_omp > exam_omp.out 

В пакетном режиме соответствующий запуск может выглядеть так:

sbatch --mem-per-cpu=4G --cpus-per-task=12 mybat_omp 

где файл mybat_omp содержит строки

#!/bin/sh srun exam_omp > exam_omp.out 

В качестве примера программы с OpenMP можно использовать pi_omp.c.

Возможен запуск гибридных MPI/OpenMP приложений с помощью опции --ntasks-per-node= , где - число процессов на узле. Например, для запуска на двух 36-ядерных узлах 6 процессов с 12 нитями каждый можно выполнить команду:

sbatch -N 2 --cpus-per-task=12 --ntasks-per-node=3 my_bat_omp 

Источник

Оцените статью
Adblock
detector