3. Функции библиотеки времени выполнения

В этом разделе описываются функции библиотеки времени выполнения OpenMP C и C++. Заголовок <omp.h> объявляет два типа, несколько функций, которые можно использовать для управления и запроса параллельной среды выполнения, а также функции блокировки, которые можно использовать для синхронизации доступа к данным.

Тип omp_lock_t является типом объекта, способным представлять, что блокировка доступна или что поток владеет блокировкой. Эти блокировки называются простыми блокировками.

Тип omp_nest_lock_t является типом объекта, способным представлять либо доступную блокировку, либо удостоверение потока, которому принадлежит блокировка, и число вложений (описано ниже). Эти блокировки называются вложенными блокировками.

Функции библиотеки — это внешние функции с компоновкой "C".

Описания в этой главе разделены на следующие разделы:

3.1 Функции среды выполнения

Функции, описанные в этом разделе, влияют на потоки, процессоры и параллельную среду:

Функция 3.1.1 omp_set_num_threads

Функция omp_set_num_threads задает число потоков по умолчанию для использования для последующих параллельных регионов, которые не указывают num_threads предложение. Используется следующий формат:

#include <omp.h>
void omp_set_num_threads(int num_threads);

Значение параметра num_threads должно быть положительным целым числом. Его влияние зависит от того, включена ли динамическая корректировка количества потоков. Полный набор правил взаимодействия между omp_set_num_threads функцией и динамической корректировкой потоков см . в разделе 2.3.

Эта функция имеет эффекты, описанные выше при вызове из части программы, где omp_in_parallel функция возвращает ноль. Если он вызывается из части программы, в которой omp_in_parallel функция возвращает ненулевое значение, поведение этой функции не определено.

Этот вызов имеет приоритет над переменной OMP_NUM_THREADS среды. Значение по умолчанию для количества потоков, которое может быть установлено путем вызова omp_set_num_threads или задания OMP_NUM_THREADS переменной среды, можно явно переопределить для одной parallel директивы, указав num_threads предложение.

Дополнительные сведения см. в omp_set_dynamic.

Перекрестные ссылки

  • функция omp_set_dynamic
  • функция omp_get_dynamic
  • переменная среды OMP_NUM_THREADS
  • предложение num_threads

Функция 3.1.2 omp_get_num_threads

Функция omp_get_num_threads возвращает количество потоков в команде, выполняющей параллельный регион, из которого он вызывается. Используется следующий формат:

#include <omp.h>
int omp_get_num_threads(void);

Предложение num_threads , omp_set_num_threads функция и OMP_NUM_THREADS переменная среды управляют количеством потоков в команде.

Если число потоков не было явно задано пользователем, значение по умолчанию определяется реализацией. Эта функция привязывается к ближайшей директиве включающей parallel . Если вызывается из последовательной части программы или из вложенного параллельного региона, сериализованного, эта функция возвращает значение 1.

Дополнительные сведения см. в omp_set_dynamic.

Перекрестные ссылки

Функция 3.1.3 omp_get_max_threads

Функция omp_get_max_threads возвращает целое число, которое гарантированно должно быть по крайней мере таким же большим, как количество потоков, которые будут использоваться для формирования команды, если параллельный регион без num_threads предложения должен был быть замечен в этом моменте в коде. Используется следующий формат:

#include <omp.h>
int omp_get_max_threads(void);

Ниже приведено выражение нижней границы для значения omp_get_max_threads:

threads-used-for-next-team<= omp_get_max_threads

Обратите внимание, что если другое параллельное регион использует num_threads предложение для запроса определенного количества потоков, гарантия на нижней границе результата omp_get_max_threads больше не содержится.

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

Перекрестные ссылки

Функция 3.1.4 omp_get_thread_num

Функция omp_get_thread_num возвращает номер потока в команде потока, выполняющего функцию. Число потока находится в диапазоне от 0 до omp_get_num_threads()–1, включительно. Главный поток команды — поток 0.

Используется следующий формат:

#include <omp.h>
int omp_get_thread_num(void);

При вызове из последовательного региона omp_get_thread_num возвращается значение 0. При вызове из вложенного параллельного региона, сериализованного, эта функция возвращает значение 0.

Перекрестные ссылки

  • функция omp_get_num_threads

Функция 3.1.5 omp_get_num_procs

Функция omp_get_num_procs возвращает количество процессоров, доступных программе во время вызова функции. Используется следующий формат:

#include <omp.h>
int omp_get_num_procs(void);

Функция 3.1.6 omp_in_parallel

Функция omp_in_parallel возвращает ненулевое значение, если оно вызывается в динамической степени параллельного региона, выполняемого параллельно; в противном случае возвращается значение 0. Используется следующий формат:

#include <omp.h>
int omp_in_parallel(void);

Эта функция возвращает ненулевое значение при вызове из региона, выполняющегося параллельно, включая вложенные регионы, сериализованные.

Функция 3.1.7 omp_set_dynamic

Функция omp_set_dynamic включает или отключает динамическую корректировку количества потоков, доступных для выполнения параллельных регионов. Используется следующий формат:

#include <omp.h>
void omp_set_dynamic(int dynamic_threads);

Если dynamic_threads оценивается как ненулевое значение, число потоков, используемых для выполнения предстоящих параллельных регионов, может быть автоматически скорректировано средой времени выполнения для оптимального использования системных ресурсов. В результате число потоков, указанных пользователем, является максимальным числом потоков. Число потоков в команде, выполняющей параллельный регион, остается фиксированным в течение этого параллельного региона и сообщается функцией omp_get_num_threads .

Если dynamic_threads оценивается как 0, то динамическая корректировка отключена.

Эта функция имеет эффекты, описанные выше при вызове из части программы, где omp_in_parallel функция возвращает ноль. Если он вызывается из части программы, в которой omp_in_parallel функция возвращает ненулевое значение, поведение этой функции не определено.

Вызов omp_set_dynamic имеет приоритет над переменной OMP_DYNAMIC среды.

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

Только для систем Майкрософт

Текущая поддержка omp_get_dynamic и omp_set_dynamic выглядит следующим образом:

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

Перекрестные ссылки

Функция 3.1.8 omp_get_dynamic

Функция omp_get_dynamic возвращает ненулевое значение, если включена динамическая корректировка потоков и возвращает значение 0 в противном случае. Используется следующий формат:

#include <omp.h>
int omp_get_dynamic(void);

Если реализация не реализует динамическую корректировку количества потоков, эта функция всегда возвращает значение 0. Дополнительные сведения см. в omp_set_dynamic.

Перекрестные ссылки

  • Описание динамической корректировки потока см. в omp_set_dynamic.

Функция 3.1.9 omp_set_nested

Функция omp_set_nested включает или отключает вложенный параллелизм. Используется следующий формат:

#include <omp.h>
void omp_set_nested(int nested);

Если вложенное значение равно 0, вложенный параллелизм отключен, то это значение по умолчанию, а вложенные параллельные области сериализуются и выполняются текущим потоком. В противном случае вложенный параллелизм включен, а вложенные регионы могут развертывать дополнительные потоки для формирования вложенная команда.

Эта функция имеет эффекты, описанные выше при вызове из части программы, где omp_in_parallel функция возвращает ноль. Если он вызывается из части программы, в которой omp_in_parallel функция возвращает ненулевое значение, поведение этой функции не определено.

Этот вызов имеет приоритет над переменной OMP_NESTED среды.

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

Перекрестные ссылки

Функция 3.1.10 omp_get_nested

Функция omp_get_nested возвращает ненулевое значение, если вложенный параллелизм включен и 0, если он отключен. Дополнительные сведения о вложенном параллелизме см. в omp_set_nested. Используется следующий формат:

#include <omp.h>
int omp_get_nested(void);

Если реализация не реализует вложенный параллелизм, эта функция всегда возвращает значение 0.

Функции блокировки 3.2

Функции, описанные в этом разделе, управляют блокировками, используемыми для синхронизации.

Для следующих функций переменная блокировки должна иметь тип omp_lock_t. Доступ к этой переменной должен осуществляться только с помощью этих функций. Для всех функций блокировки требуется аргумент, имеющий указатель на omp_lock_t тип.

  • Функция omp_init_lock инициализирует простую блокировку.
  • Функция omp_destroy_lock удаляет простую блокировку.
  • Функция omp_set_lock ожидает, пока не будет доступна простая блокировка.
  • Функция omp_unset_lock освобождает простую блокировку.
  • Функция omp_test_lock проверяет простую блокировку.

Для следующих функций переменная блокировки должна иметь тип omp_nest_lock_t. Доступ к этой переменной должен осуществляться только с помощью этих функций. Для всех вложенных функций блокировки требуется аргумент, имеющий указатель на omp_nest_lock_t тип.

  • Функция omp_init_nest_lock инициализирует вложенную блокировку.
  • Функция omp_destroy_nest_lock удаляет вложенную блокировку.
  • Функция omp_set_nest_lock ожидает, пока не будет доступна вложенная блокировка.
  • Функция omp_unset_nest_lock освобождает вложенную блокировку.
  • Функция omp_test_nest_lock проверяет вложенную блокировку.

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

Функции 3.2.1 omp_init_lock и omp_init_nest_lock

Эти функции предоставляют единственный способ инициализации блокировки. Каждая функция инициализирует блокировку, связанную с блокировкой параметра для использования в предстоящих вызовах. Используется следующий формат:

#include <omp.h>
void omp_init_lock(omp_lock_t *lock);
void omp_init_nest_lock(omp_nest_lock_t *lock);

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

Функции 3.2.2 omp_destroy_lock и omp_destroy_nest_lock

Эти функции позволяют неинициализировать блокировку переменной блокировки . Используется следующий формат:

#include <omp.h>
void omp_destroy_lock(omp_lock_t *lock);
void omp_destroy_nest_lock(omp_nest_lock_t *lock);

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

Функции 3.2.3 omp_set_lock и omp_set_nest_lock

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

#include <omp.h>
void omp_set_lock(omp_lock_t *lock);
void omp_set_nest_lock(omp_nest_lock_t *lock);

Для простой блокировки аргумент omp_set_lock функции должен указывать на инициализированную переменную блокировки. Владение блокировкой предоставляется потоку, выполняющего функцию.

Для вложенной блокировки аргумент функции omp_set_nest_lock должен указывать на инициализированную переменную блокировки. Число вложенных объектов увеличивается, и поток предоставляется или сохраняется владение блокировкой.

Функции 3.2.4 omp_unset_lock и omp_unset_nest_lock

Эти функции предоставляют средства освобождения владения блокировкой. Используется следующий формат:

#include <omp.h>
void omp_unset_lock(omp_lock_t *lock);
void omp_unset_nest_lock(omp_nest_lock_t *lock);

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

Для простой блокировки omp_unset_lock функция освобождает поток, выполняющий функцию от владения блокировкой.

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

Функции 3.2.5 omp_test_lock и omp_test_nest_lock

Эти функции пытаются задать блокировку, но не блокируют выполнение потока. Используется следующий формат:

#include <omp.h>
int omp_test_lock(omp_lock_t *lock);
int omp_test_nest_lock(omp_nest_lock_t *lock);

Аргумент должен указывать на инициализированную переменную блокировки. Эти функции пытаются задать блокировку таким же образом, как omp_set_lock и omp_set_nest_lock, за исключением того, что они не блокируют выполнение потока.

Для простой блокировки функция возвращает ненулевое значение, omp_test_lock если блокировка успешно задана; в противном случае возвращается ноль.

Для вложенной блокировки функция возвращает новое число вложений, omp_test_nest_lock если блокировка успешно задана; в противном случае возвращается ноль.

3.3 Подпрограммы времени

Функции, описанные в этом разделе, поддерживают переносимый часовой таймер:

  • Функция omp_get_wtime возвращает истекшее время часов.
  • Функция omp_get_wtick возвращает секунды между последовательными тиками часов.

Функция 3.3.1 omp_get_wtime

Функция omp_get_wtime возвращает значение с плавающей запятой двойной точности, равное истекшему времени часов стены в секундах, так как некоторое время в прошлом. Фактическое "время в прошлом" является произвольным, но оно гарантированно не изменится во время выполнения программы приложения. Используется следующий формат:

#include <omp.h>
double omp_get_wtime(void);

Предполагается, что функция будет использоваться для измерения истекшего времени, как показано в следующем примере:

double start;
double end;
start = omp_get_wtime();
... work to be timed ...
end = omp_get_wtime();
printf_s("Work took %f sec. time.\n", end-start);

Возвращаемые время — "время на поток", которое означает, что они не должны быть глобально согласованы во всех потоках, участвующих в приложении.

Функция 3.3.2 omp_get_wtick

Функция omp_get_wtick возвращает значение с плавающей запятой двойной точности, равное количеству секунд между последовательными галочками часов. Используется следующий формат:

#include <omp.h>
double omp_get_wtick(void);