Игнорировать OpenMP на машине, на которой его нет - PullRequest
28 голосов
/ 19 августа 2009

У меня есть программа на C ++, использующая OpenMP, которая будет работать на нескольких машинах, на которых может быть установлен или не установлен OpenMP.

Как я могу сделать так, чтобы моя программа знала, если на машине нет OpenMP, и игнорирую эти #include <omp.h>, директивы OpenMP (например, #pragma omp parallel ...) и / или библиотечные функции (например, tid = omp_get_thread_num();)?

Ответы [ 5 ]

61 голосов
/ 09 декабря 2011

Компиляция OpenMP добавляет определение препроцессора "_OPENMP", так что вы можете сделать:

#if defined(_OPENMP)
   #pragma omp ...
#endif

Некоторые примеры см. http://bisqwit.iki.fi/story/howto/openmp/#Discussion и следующий код.

21 голосов
/ 02 марта 2010

Компиляторы должны игнорировать #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 и использовать их. Остальное будет просто работать.

2 голосов
/ 19 августа 2009

OpenMP - это среда выполнения компилятора, а не платформа.

т. Если вы компилируете свое приложение с использованием Visual Studio 2005 или более поздней версии, то у вас всегда будет доступен OpenMP, так как среда выполнения его поддерживает. (и если у конечного пользователя не установлена ​​среда выполнения Visual Studio C, ваше приложение вообще не будет работать).

Итак, вам не нужно беспокоиться, если вы можете использовать его, он всегда будет там, как функции, такие как strcmp. Чтобы убедиться, что у них есть CRT, вы можете установить распространяемый Visual Studio.

редактирование:

хорошо, но GCC 4.1 не сможет скомпилировать ваше приложение openMP, поэтому проблема не в целевой машине, а в целевом компиляторе. Поскольку все компиляторы имеют предопределенные макросы, предоставляющие свою версию, оберните ваши вызовы OpenMP блоками #ifdef. например, GCC использует 3 макроса для определения версии компилятора, __GNUC__, __GNUC_MINOR__ and __GNUC_PATCHLEVEL__

0 голосов
/ 22 января 2019

Как я могу сделать так, чтобы моя программа знала, если на машине нет OpenMP, и игнорирую эти #include <omp.h>, директивы OpenMP (например, #pragma omp parallel ...) и / или библиотечные функции (например, tid = omp_get_thread_num();)?

Вот поздний ответ, но мы только что получили сообщение об ошибке из-за использования #pragma omp simd в компиляторах Microsoft.

Согласно Спецификация OpenMP , раздел 2.2:

Условная компиляция

В реализациях, которые поддерживают препроцессор, имя макроса _OPENMP определяется как десятичное значение yyyymm, где yyyy и mm являются год и четвертое обозначения версии OpenMP API, которую Поддержка реализации.

Похоже, что современные компиляторы 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. И я не читал, вы можете собрать на одной машине, а затем запустить на другой машине.

0 голосов
/ 14 июня 2018

Мне нравится другой подход, заимствованный из 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 и другие не поддерживают его.

...