Игнорировать OpenMP на компьютере, у которого его нет
У меня есть программа на С++, использующая OpenMP, которая будет работать на нескольких машинах, которые могут иметь или не иметь OpenMP.
Как я могу сообщить своей программе, нет ли в машине OpenMP и игнорировать те #include <omp.h>
, директивы OpenMP (например, #pragma omp parallel ...
) и/или библиотечные функции (например, tid = omp_get_thread_num();
)?
Ответы
Ответ 1
OpenMP - это среда выполнения компилятора, а не платформа.
т. Если вы скомпилируете свое приложение с помощью Visual Studio 2005 или выше, у вас всегда есть OpenMP, доступный по мере его поддержки. (и если у конечного пользователя не установлена среда исполнения Visual Studio C, ваше приложение не будет работать вообще).
Итак, вам не нужно беспокоиться, если вы можете использовать его, он всегда будет рядом с такими функциями, как strcmp. Чтобы убедиться, что у них есть CRT, вы можете установить распространяемую визуальную студию.
изменить:
ok, но GCC 4.1 не сможет скомпилировать ваше приложение openMP, поэтому проблема не является целевой машиной, а целевым компилятором. Поскольку у всех компиляторов есть предопределенные макросы, дающие их версию, оберните ваши вызовы OpenMP блоками #ifdef. например, GCC использует 3 макроса для идентификации версии компилятора, __GNUC__, __GNUC_MINOR__ and __GNUC_PATCHLEVEL__
Ответ 2
Компиляция OpenMP добавляет определение препроцессора "_OPENMP", поэтому вы можете сделать:
#if defined(_OPENMP)
#pragma omp ...
#endif
В некоторых примерах см. http://bisqwit.iki.fi/story/howto/openmp/#Discussion и следующий код.
Ответ 3
Составители должны игнорировать директивы #pragma
, которые они не понимают; что вся суть синтаксиса. И функции, определенные в openmp.h
, имеют простые четко определенные значения в непараллельной системе - в частности, файл заголовка проверяет, определяет ли компилятор ENABLE_OPENMP
и, если он не включен, предоставляет правильные резервные копии.
Итак, все, что вам нужно, это копия openmp.h
для ссылки. Здесь один: http://cms.mcc.uiuc.edu/qmcdev/docs/html/OpenMP_8h-source.html.
Соответствующая часть кода, однако, заключается в следующем:
#if defined(ENABLE_OPENMP)
#include <omp.h>
#else
typedef int omp_int_t;
inline omp_int_t omp_get_thread_num() { return 0;}
inline omp_int_t omp_get_max_threads() { return 1;}
#endif
В худшем случае вы можете просто взять эти три строки и поместить их в фиктивный openmp.h
файл и использовать это. Остальное будет работать.
Ответ 4
Как я могу сделать так, чтобы моя программа знала, что на машине нет OpenMP, и игнорирую эти директивы #include <omp.h>
, OpenMP (например, #pragma omp parallel...
) и/или библиотечные функции (например, tid = omp_get_thread_num();
) tid = omp_get_thread_num();
?
Здесь поздний ответ, но мы только что получили сообщение об ошибке из-за использования #pragma omp simd
на компиляторах Microsoft.
Согласно Спецификации OpenMP, раздел 2.2:
Условная компиляция
В реализациях, которые поддерживают препроцессор, имя макроса _OPENMP определено с десятичным значением yyyymm, где yyyy и mm обозначают год и четвертое обозначение версии API OpenMP, поддерживаемой реализацией.
Похоже, что современные компиляторы Microsoft поддерживают OpenMP только в период между 2000 и 2005 годами. Я могу сказать только "иногда", потому что OpenMP 2.0 был выпущен в 2000 году, а OpenMP 2.5 был выпущен в 2005 году. Но Microsoft рекламирует версию с 2002 года.
Вот несколько _OPENMP
номеров...
- Visual Studio 2012 - OpenMP 200203
- Visual Studio 2017 - OpenMP 200203
- IBM XLC 13.01 - OpenMP 201107
- Clang 7.0 - OpenMP 201107
- GCC 4.8 - OpenMP 201107
- GCC 8.2 - OpenMP 201511
Поэтому, если вы хотите использовать, скажем, #pragma omp simd
для защиты цикла, и #pragma omp simd
доступен в OpenMP 4.0, тогда:
#if _OPENMP >= 201307
#pragma omp simd
for (size_t i = 0; i < 16; ++i)
data[i] += x[i];
#else
for (size_t i = 0; i < 16; ++i)
data[i] += x[i];
#endif
который будет работать на нескольких машинах, на которых может быть установлен или не установлен OpenMP.
И чтобы быть ясным, вам, вероятно, нужно собрать свою программу на каждой из этих машин. ABI x86_64 не гарантирует, что OpenMP доступен на машинах x86, x32 или x86_64. И я не читал, вы можете построить на одной машине, а затем запустить на другой машине.
Ответ 5
Есть еще один подход, который мне нравится, заимствованный из Bisqwit:
#if defined(_OPENMP)
#include <omp.h>
extern const bool parallelism_enabled = true;
#else
extern const bool parallelism_enabled = false;
#endif
Затем запустите ваш OpenMP параллель для таких циклов:
#pragma omp parallel for if(parallelism_enabled)
Примечание: есть веские причины не использовать pragma
, что является нестандартным, поэтому Google и другие не поддерживают ее.