Любой чистый способ заставить прагмы OpenMP работать с макросами? - PullRequest
0 голосов
/ 23 мая 2018

Я должен добавить OpenMP к коду клиента.У него есть пара макросов, которые работают примерно так:

int i, imax;
#ifdef MAC1
double x1, y1
#endif
#ifdef MAC2
double x2, y2
#endif

//first loop:
for (i=0; i<imax; i++ ) {
#ifdef MAC1
//process x1, y1
#endif
#ifdef MAC2
//process x2, y2
#endif
//do a ton of other stuff
}

// Lots more code.  No way it will all work in one omp region.

//second loop:
for (i=0; i<imax; i++ ) {
#ifdef MAC1
//process x1, y1
#endif
#ifdef MAC2
//process x2, y2
#endif
//do a ton of other stuff
}

Вполне возможно, что MAC1 и MAC2 могут быть оба определены, или либо, либо ни того, ни другого.

Итак, теперь я хочу запустить циклы под OpenMP.Обычно это не сработает:

#pragma omp parallel private(x1, y1,   \
                             x2, y2,   \
                             and a     \
                             ton of    \
                             other stuff)
{
...
}

... потому что, если MAC1 и / или MAC2 не определены, компилятор жалуется, что x1, y1 и / или x2, y2 не определены.

Я думал о нескольких способах обойти это, которые либо не будут работать, либо не соответствуют стандартам:

1) Я не могу просто вставить определения этих переменных в ompпараллельная область, потому что, как я уже сказал, мне придется использовать их во второй области позже, и я не могу переопределить их там.

2) Я думаю, я мог бы вытащить эти переменные за пределы их макроблоков и определитьим ли они нужны или нет.Это было бы самое простое решение, но это похоже на «взлом».И я подозреваю, что в принципе бывают ситуации, когда это все равно не сработает.

3) Думаю, я мог бы написать несколько прагм omp, по одной для каждой комбинации макросов, заключенных в четыре разных #ifdefs, нотогда мне нужны четыре разные дополнительные прагмы, и код будет очень быстро запутываться.

4) Я пытался сделать что-то вроде

#pragma omp parallel private(the other stuff) \
#ifdef MAC1
                     private(x1, y1)   \
#endif
#ifdef MAC2
                     private(x2, y2)   \
#endif
{ ... }

Это все равно было бы не очень приятно смотретьв, но это было бы намного лучше, чем четыре разные дополнительные прагмы.Тем не менее, я попробовал несколько вариантов синтаксиса этого, но компилятор понятия не имел, что я пытался сделать.

Кто-нибудь знает чистый способ сделать то, что я пытаюсь сделать здесь?

Ответы [ 2 ]

0 голосов
/ 25 мая 2018

Если вы компилируете с использованием C99 и выше, вы можете использовать оператор pragma: https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html

Вот небольшой рабочий пример:

#include <stdio.h>
#include <omp.h>

#define MAC1
#define MAC2

#ifdef MAC1
double x1 = 0.0, y1 = 0.1;
#endif

#ifdef MAC2
double x2 = 1.0, y2 = 1.1;
#endif

#if defined(MAC1) && defined(MAC2)
# define MY_OMP_LOOP_PRAGMA _Pragma("omp parallel for firstprivate(x1, y1, x2, y2)")
#elif defined(MAC1)
# define MY_OMP_LOOP_PRAGMA _Pragma("omp parallel for firstprivate(x1, y1)")
#elif defined(MAC2)
# define MY_OMP_LOOP_PRAGMA _Pragma("omp parallel for firstprivate(x2, y2)")
#endif

int main(int argc, char* argv[])
{
   int imax = 10;
MY_OMP_LOOP_PRAGMA
   for (int i=0; i < imax; ++i) {
#ifdef MAC1
     printf("%d: %f, %f\n", omp_get_thread_num(), x1, y1);
#endif
#ifdef MAC2
    printf("%d: %f, %f\n", omp_get_thread_num(), x2, y2);
#endif
}

  return 0;
}
0 голосов
/ 23 мая 2018

Самая простая и естественная вещь, о которой я могу подумать, была бы такова:

// Just once, in a header if need be:

#ifdef MAC1
// Note trailing comma:
#define MAC1_VARS x1, y1,
#else
#define MAC1_VARS
#endif

#ifdef MAC2
// Note trailing comma:
#define MAC2_VARS x2, y2,
#else
#define MAC2_VARS
#endif
/////////////////////////

// ...

// each parallel region / loop:
#pragma omp parallel private(MAC1_VARS \
                         MAC2_VARS     \
                         other, stuff)
{
    // ...
}

Таким образом, MAC1_VARS и MAC2_VARS расширяются соответствующим образом, ни к чему, или к соответствующей подпоследовательности списка переменных..

Если вы можете изменить клиентский код, который условно объявляет эти переменные, то я бы также поместил определения MAC1_VARS и MAC2_VARS вместо отдельных условных выражений препроцессора.

...