Selective use of OpenMP features

Selective use of OpenMP features

Is there a standard/recommended way to use OpenMP features selectively depending on

  • capabilities of the compiler
  • capabilities of the hardware

What I mean is the following. If I write a code that should be usable on several systems which different compiler versions installed then I would like to use, say

!$omp parallel do simd
do i=1:n
  y(i) = y(i) + a * x(i)
end do
!$omp end parallel do

if the compiler supports the OpenMP 4.0 standard. However, for older versions the following code needs to be used

!$omp parallel do
do i=1:n
  y(i) = y(i) + a * x(i)
!$omp end parallel do

Another example is the use of devices such as Intel MIC. If it is present then I would like to use it. Otherwise, I just run the code on the CPU.

At the moment, I am separating the different capabilities via #ifdef HAS_OPENMPXY at the cost of poor readability of the code. Moreover, this completely contradicts the original idea of OpenMP to have one code that works sequentially and in parallel.


5 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

The OpenMP standard includes the _OPENMP predefine for conditional compilation based on its value which should reflect the compiler’s capabilities in terms of OpenMP support for specific standards. The OpenMP 4.0 specification (July 2013) introduced the target and simd constructs so conditional compilation/use of those could be pre-conditioned based on something like:  #if _OPENMP .GE. 201307

Use of _OPENMP likely does not help with code readability but it is something standard among compilers supporting OpenMP.

As for capabilities of the hardware and use at execution time, by design the target construct defaults to “optional”, so when the target device is present/available the designated construct executes on the target device otherwise the code executes on the host CPU.

You can use the preprocessor, test the value of the _OPENMP macro (which is a numeric representation of the month of publication of the OpenMP spec supported) and then conditionally compile the relevant directive.

There was a series of Intel compiler 13.1 releases where the value of _OPENMP was inherited from gcc rather than set to reflect when Intel began full support of OpenMP 3.1 (except for supporting OpenMP 2.5 only by quietly inserting omp single).  I continue to use _OPENMP value to detect compilers which don't support OpenMP 3 (more of a problem with C++).  In compiler 14.x, Intel supplies the date 201107 corresponding to OpenMP 3.1 (which gcc/gfortran set at least since version 4.7).

As announced plans from Intel specifically exclude OpenMP 4.0 user defined reduction, there is no standard macro to detect  the useful degree of OpenMP 4.0 support in compilers to be released this year.  I've heard that a future OpenMP standard may include categories rather than standard release dates.

Although numeric values for __INTEL_COMPILER aren't mentioned in current documentation, we've been assured on these forums that pre-processor tests based on e.g. __INTEL_COMPILER >= 1500 (meaning 15.x series or later) should continue to work.  So I'm using that to choose between OpenMP 4 (without UDR) and prior unsafe usage of  !dir simd, as well as cases where ifort still requires !dir$ simd even though current gfortran optimizes with !$omp simd.

I avoid using simd clause in !$omp parallel do simd since ifort does a good job on my examples without it, and gfortran simply ignores it (but often requires a different loop nesting to optimize).

There are a bunch of cases where directives controlling vectorization have to be conditional on __MIC___ as the compiler is too aggressive in default simd vectorization for host or not enough so for MIC.  I don't believe there is an OpenMP directive to suggest not vectorizing, but omp simd directive may be used to replace the Intel specific nofusion directive.

My examples are posted at

Intel 15.0 released compilers self-report as OpenMP 3.1, as did the 14.0, although OpenMP 4 support is substantially complete with the expected exception of user defined reduction. 

15.0 corrected a case which previously required Intel-specific !dir$ simd (not the Open 4 version) but there remain a few such cases.

The original question appeared to ask about suppressing omp target and non-openmp offload directives in the case of compilers which don't support them, but no one gave an answer, other than Kevin's about the facility for optional offload in the compilers which support offload.

I think it would be difficult to find an example as simple as the one posed where one would want optional simd facility.

I posted some just a bit more complicated at

and a discussion of pros and cons of OpenMP 4 at

In the Fortran cases posted, ifort doesn't rely much on the parallel do simd (it adapts well without that simd), so you might have to look at the C and C++ versions.  Current gfortran accepts parallel do simd but ignores the simd when targeting AVX, as far as I can tell.

Leave a Comment

Please sign in to add a comment. Not a member? Join today