1

My C++ code uses OpenMP directives and needs to compile with GCC and Visual Studio 2019. OpenMP min/max reduction operators were introduced in OpenMP 3.1, but Visual Studio 2019 only supports OpenMP 2.0.

I'd like my code to revert to a serial loop under Visual Studio, but I understand that the preprocessor cannot represent a conditional pragma like this:

// invalid use of preprocessor:
#ifdef _MSC_VER
#define OMP_MIN(expr)
#else
#define OMP_MIN(expr) #pragma omp parallel for reduction(min:(expr))
#endif

double x = 10.0;

OMP_MIN(x)
for (int i = 0; i < array_size; i++) {
    x = fmin(x, array[i]);
}

Is there a way to achieve this?

hertzsprung
  • 9,445
  • 4
  • 42
  • 77
  • You can try to extract the loop part in two different functions (serial loob, OpenMP loop) and describe your define according to these two functions – Landstalker Feb 19 '20 at 09:44
  • That's true, but it'll need lots of refactoring to avoid duplicating code since I have several of these loops. – hertzsprung Feb 19 '20 at 09:46

2 Answers2

2

You can use _Pragma() from C++11 to have a function-like macro that conditionally enables a pragma:

#include <cmath>

#ifdef _MSC_VER
#define OMP_MINX()
#else
#define OMP_MINX() _Pragma("omp parallel for reduction(min:x)")
#endif

int main() {
  double x = 10.0;
  double array[50];
  int array_size = 50;

  OMP_MINX()
  for (int i = 0; i < array_size; i++) {
    x = std::fmin(x, array[i]);
  }
}

but I haven't figured out how to make gcc accept anything other than a literal string for the argument to allow using an arbitrary variable - not even the preprocessor's stringification operator works, meaning you might as well just use

#ifndef _MSC_VER
#pragma omp parallel for reduction(min:x)
#endif
for (int i = 0; i < array_size; i++) {
  x = std::fmin(x, array[i]);
}
Shawn
  • 47,241
  • 3
  • 26
  • 60
  • `_Pragma()` is new to me, I wonder if it was added to address this type of use case? I can't find much info about it. Anyway, I've gone with your second alternative, thanks. – hertzsprung Feb 19 '20 at 10:34
0

You can use the DO_PRAGMA() macro idiom explained in https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html.

#define DO_PRAGMA(x) _Pragma (#x)

#ifdef _MSC_VER
#define OMP_MINX(expr)
#else
#define OMP_MINX(expr) DO_PRAGMA(omp parallel for reduction(min: expr))
#endif

OMP_MINX(x) expands to the desired #pragma omp parallel for reduction(min: x) if _MSC_VER is not defined. expr is expanded first and afterwards the whole argument of DO_PRAGMA() is stringified before the _Pragma() operator is applied. This is what OP asked for.

Solution is inspired from this answer: How to concatenate strings in the arguments of _Pragma

breiters
  • 116
  • 6