Post

OpenMP Code, unknown pragma Compilerwarnung unterdrücken und unnötige _OPENMP ifdefs vermeiden

OpenMP Code, unknown pragma Compilerwarnung unterdrücken und unnötige _OPENMP ifdefs vermeiden

Wenn man Code mit OpenMP parallelisiert, will man zwecks Debugging den Code auch mal ohne OpenMP parallelisieren. Außerdem können Compiler ohne OpenMP mitunter sequentiellen Code besser optimieren. Die Möglichkeit, mit dem gleichen Code und nur minimalen Erweiterungen durch #pragma omp ... Statements die Parallelisierung nachzurüsten, ist ja eine der Stärken der OpenMP-Parallelisierung.

Allerdings gibt es da zwei Dinge, die mich häufig nerven.

Nervige Compiler-Warnungen entfernen, wenn ich ohne OpenMP baue

Wenn man OpenMP-parallelisierten Code ohne OpenMP compiliert, geben die Compiler Warnungen wie unknown pragma aus. Je nach Compiler kann man das unterschiedlich abschalten.

Beim GCC unter Linux/Unix muss man dazu die Compileroption -Wunknown-pragmas einschalten.

Unter Windows mit Visual Studio geht das nicht über Compileroptionen, sondern nur über

1
#pragma warning (disable : 4068 )

im Quelltext vor der Verwendung der pragmas. Analog schaltet man die Warnung beim Intel Compiler aus. Man muss nun aber diese Zeilen in jeder CPP-Datei einfügen, was man besser durch eine einheitliche Header-Datei macht.

Funktionen wie omp_get_num_threads() oder omp_get_thread_num() auch ohne Prüfung auf _OPENMP verfügbar haben

Manchmal muss man im Code prüfen, ob der aktuelle Thread gerade der Masterthread mit Thread-Nummer 0 ist. Dazu ruft man normalerweise die Funktion omp_get_thread_num() auf. Diese ist aber nur verfügbar, wenn OpenMP eingeschaltet ist. Häufig schreibt man dann im Quelltext Code wie:

1
2
3
4
5
int threadNum = 0; // always 0 in single-threaded code

#ifdef _OPENMP
threadNum = omp_get_thread_num();
#endif

Das bläht den Code auf und erschwert die Lesbarkeit. Dabei kann man diese Funktionen einfach in nicht-OpenMP-Code selbst deklarieren und dann darauf ohne #ifdef _OPENMP checks zugreifen. Auch diese Deklarationen kommen besser in eine einheitliche Headerdatei.

Bequemlichkeits Include-Datei für OpenMP Code

Ich habe das alles mal in einer Header-Datei zusammengestellt, die man in OpenMP-Code verwendet. Also statt

1
2
3
#ifdef _OPENMP
#include <omp.h>
#endif

schreibt man einfach

1
#include <IBK_openMP.h>

und die nervigen Dinge oben sind verschwunden. Hier ist die Headerdatei:

IBK_openMP.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#ifndef IBK_openMPH
#define IBK_openMPH

#if defined(_OPENMP)

// we have openmp
#include <omp.h>

#else

// no openmp, disable warnings

#	if defined(__GNUC__)

#pragma GCC diagnostic ignored "-Wunknown-pragmas"

#	 elif  defined(__ICC) || defined(__INTEL_COMPILER)

// icc warning disabling works with icc version 14.0 - what is the switch for this?
#pragma warning ( disable : 3180 )

#	elif defined(_MSC_VER)

#pragma warning (disable : 4068 ) /* disable unknown pragma warnings */

#	endif

// in case of no openmp, define the functions used for single-thread
#ifdef __cplusplus

constexpr int omp_get_num_threads() { return 1; }
constexpr int omp_get_thread_num() { return 0; }

#else //  __cplusplus

inline int omp_get_num_threads() { return 1; }
inline int omp_get_thread_num() { return 0; }

#endif //  __cplusplus

#endif // _OPENMP

/*! \file IBK_openMP.h
	\brief Replacement include file for OpenMP-based library code that includes omp.h and also sets defines to disable
			compiler warnings if not compiling with OpenMP support.
*/

#endif // IBK_openMPH
This post is licensed under CC BY 4.0 by the author.