Ignora OpenMP sulla macchina che non ce l'ha
Domanda
Ho un programma C ++ usando OpenMP, che si svolgerà su più macchine che possono avere o non avete installato OpenMP.
Come potrei fare il mio programma di sapere se una macchina non ha OpenMP e ignorare quelli #include <omp.h>
, direttive OpenMP (come #pragma omp parallel ...
) e / o funzioni di libreria (come tid = omp_get_thread_num();
)?
Soluzione
OpenMP è una cosa compilatore runtime e non una cosa piattaforma.
es. Se si compila la vostra applicazione utilizzando Visual Studio 2005 o superiore, allora si ha sempre OpenMP disponibile come il runtime supporta. (E se l'utente finale non ha il runtime di Visual Studio C installato, allora la vostra applicazione non funzionerà affatto).
Quindi, non c'è bisogno di preoccuparsi, se è possibile utilizzarlo, sarà sempre lì, proprio come funzioni quali strcmp. Per assicurarsi che essi hanno il CRT, è possibile installare lo studio ridistribuibile visivo.
modifica:
ok, ma GCC 4.1 non sarà in grado di compilare l'openMP app, in modo che il problema non è la macchina di destinazione, ma il compilatore di destinazione. macro che danno la loro versione, come tutti i compilatori hanno pre-definito, avvolgere il vostro OpenMP chiamate con #ifdef blocchi. per esempio, GCC utilizza 3 macro per identificare la versione del compilatore, __GNUC__, __GNUC_MINOR__ and __GNUC_PATCHLEVEL__
Altri suggerimenti
compilation OpenMP aggiunge la definizione di preprocessore "_OPENMP", in modo da poter fare:
#if defined(_OPENMP)
#pragma omp ...
#endif
Per alcuni esempi, vedere http://bisqwit.iki.fi/story/ howto / OpenMP / # Discussione e il codice che segue.
I compilatori sono tenuti a ignorare le direttive #pragma
che non capiscono; questo è il punto di tutta la sintassi. E le funzioni definite in openmp.h
hanno semplici significati ben definiti su un sistema non in parallelo - in particolare, il file di intestazione controllerà per se il compilatore definisce ENABLE_OPENMP
e, se non è abilitata, fornire le ricadute destra
Quindi, tutto ciò che serve è una copia di openmp.h
a cui collegarsi. Eccone uno: http://cms.mcc.uiuc.edu/ qmcdev / docs / html / OpenMP_8h-source.html .
La parte rilevante del codice, però, è proprio questo:
#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
Nel peggiore dei casi, si può semplicemente prendere quelle tre righe e metterli in un file openmp.h
fittizio, e usare quella. Il resto sarà solo di lavoro.
C'è un altro approccio che mi piace, preso in prestito da Bisqwit :
#if defined(_OPENMP)
#include <omp.h>
extern const bool parallelism_enabled = true;
#else
extern const bool parallelism_enabled = false;
#endif
Quindi, avviare l'OpenMP parallelo per i loop come questo:
#pragma omp parallel for if(parallelism_enabled)
Nota: ci sono validi motivi per non usare pragma
, che è non standard, quindi, perché Google e gli altri non lo supportano.
Come potrei fare il mio programma di sapere se una macchina non ha OpenMP e ignorare quelli
#include <omp.h>
, direttive OpenMP (come#pragma omp parallel ...
) e / o funzioni di libreria (cometid = omp_get_thread_num();
)?
Ecco una risposta in ritardo, ma abbiamo appena ricevuto una bug report causa di un uso di #pragma omp simd
sui compilatori Microsoft.
OpenMP Specification , sezione 2.2:
Compilazione Condizionale
In implementazioni che supportano un preprocessore, il _OPENMP macro nome è definito per avere il valore decimale AAAAMM dove aaaa e mm sono i anno e ese designazioni della versione delle API OpenMP che la implementazione supporta.
Sembra moderni compilatori Microsoft supportano solo OpenMP da qualche tempo tra il 2000 e il 2005. Posso solo dire "a volte tra il" perché OpenMP 2.0 è stato rilasciato nel 2000, ed OpenMP 2.5 è stato rilasciato nel 2005. Ma Microsoft pubblicizza una versione a partire dal 2002.
Ecco alcuni numeri _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 201.511
Quindi, se si desidera utilizzare, ad esempio #pragma omp simd
per custodire un ciclo, e #pragma omp simd
è disponibile in OpenMP 4.0, quindi:
#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
, che verrà eseguito su diverse macchine che possono avere o non avete installato OpenMP.
E per essere chiari, probabilmente è necessario per costruire il tuo programma su ciascuna di quelle macchine. Il x86_64 ABI non garantisce OpenMP è disponibile su x86, x32 o x86_64 macchinari. E io non ho letto si può costruire su una macchina, e quindi eseguire su un'altra macchina.