Отключите OpenMP
-
20-09-2019 - |
Вопрос
В моей программе на C++ я хотел бы запускать ее исполняемый файл иногда с использованием OpenMP, а иногда и без него (т.многопоточность или однопоточность).Я рассматриваю любой из следующих двух случаев использования OpenMP в моем коде:
(1) Предположим, что мой код имеет только #include <omp.h>
и директивы OpenMP.
(2) То же, что и (1), и мой код дополнительно вызывает функции OpenMP, например omp_get_thread_num()
.
Чтобы не иметь разного кода для разных запусков, является ли это единственным способом использовать некоторую самоопределяемую переменную прекомпилятора для защиты того, где OpenMP появляется в моем коде?
Спасибо и привет!
Решение
Привет, самый простой способ сделать это
omp_set_num_threads(m_iUseableProcessors);
где m_iUseableProcessors
— это количество процессоров, на которые вы хотите разделить вычисления.Я не знаю, как это сделать без функций OpenMP.Вы могли бы, вероятно, #ifdef
их, но это заставляет вас отключать OpenMP во время компиляции.
Другие советы
Вы можете использовать переменную среды:
set OMP_NUM_THREADS=1
На самом деле OpenMP не отключается.Это заставит OpenMP создавать только один поток для приложения.Работает без перекомпиляции.Я использую эту переменную для проверки масштабируемости в 1, 2, 3, 4 и т. д. потоках.
Вы можете включить включение следующим образом:
#ifdef _OPENMP_
#include<omp.h>
#endif
Теперь, если вы запустите свою программу без флага -fopenmp, она будет игнорировать директивы openmp.
В дополнение к предложению _OPENMP
, возможно, вам будет полезно использовать C99 _Pragma
(или __pragma
, если вы используете компиляторы C++ — см. этот вопрос StackOverflow подробнее), чтобы предотвратить засорение вашего кода #ifdef _OPENMP
и #endif
, тем самым сокращая количество строк, связанных с условной компиляцией, в 3 раза и, в противном случае, предоставляя вам O(1) контроль над O(n) экземплярами аннотаций OpenMP.
Например, я использую следующий стиль в своих кодах OpenMP C99.Изменения для поддержки C++ должны быть довольно скромными, хотя, возможно, специфичными для компилятора (в этом случае макросы типа __GNUC__
, __clang__
, __INTEL_COMPILER
, и т. д.может быть полезно).
#ifndef PRAGMA_OPENMP_H
#define PRAGMA_OPENMP_H
#if defined(_OPENMP) && ( __STDC_VERSION__ >= 199901L )
#define PRAGMA(x) _Pragma(#x)
#define OMP_PARALLEL PRAGMA(omp parallel)
#define OMP_PARALLEL_FOR PRAGMA(omp parallel for schedule(static))
#define OMP_FOR PRAGMA(omp for schedule(static))
#define OMP_PARALLEL_FOR_COLLAPSE(n) PRAGMA(omp parallel for collapse(n) schedule(static))
#define OMP_PARALLEL_FOR_COLLAPSE2 OMP_PARALLEL_FOR_COLLAPSE(2)
#define OMP_PARALLEL_FOR_COLLAPSE3 OMP_PARALLEL_FOR_COLLAPSE(3)
#define OMP_PARALLEL_FOR_COLLAPSE4 OMP_PARALLEL_FOR_COLLAPSE(4)
#define OMP_PARALLEL_FOR_REDUCE_ADD(r) PRAGMA(omp parallel for reduction (+ : r) schedule(static))
#else
#warning No OpenMP, either because compiler does not understand OpenMP or C99 _Pragma.
#define OMP_PARALLEL
#define OMP_PARALLEL_FOR
#define OMP_FOR
#define OMP_PARALLEL_FOR_COLLAPSE(n)
#define OMP_PARALLEL_FOR_COLLAPSE2
#define OMP_PARALLEL_FOR_COLLAPSE3
#define OMP_PARALLEL_FOR_COLLAPSE4
#define OMP_PARALLEL_FOR_REDUCE_ADD(r)
#endif
#endif // PRAGMA_OPENMP_H