Пункты сокращения и коллапса в OMP имеют некоторые запутанные моменты

Обе части сокращения и коллапса в OMP смущают меня,
некоторые поднятые вопросы всплыли в моей голове

  1. Почему сокращение не работает с минусом? как в указанном ограничении Вот
  2. Есть ли работа, чтобы достичь минус?
  3. Как работает унарный оператор, то есть x ++ или x—? — или ++ применяется к каждому частичному результату? или только один раз при создании глобального результата? оба случая совершенно разные.

О развале ..
мы могли бы применить сжатие к вложенным циклам, но между ними должно быть несколько строк кода
например

for (int i = 0; i < 4; i++)
{
cout << "Hi"; //This is an extra line. which breaks the 2 loops.
for (int j = 0; j < 100; j++)
{
cout << "*";
}
}

2

Решение

1 & 2. За минус, что вы вычитаете из? Если у вас есть две темы, вы делаете result_thread_1 - result_thread_2, или же result_thread_2 - result_thread_1? Если у вас более двух потоков, это становится еще более запутанным: у меня только один отрицательный термин, а все остальные положительные? Есть только один положительный термин, а другие отрицательные? Это смесь? Какие результаты какие? Как такового нет, обходного пути нет.

  1. В случае x++ или же x--Предполагая, что они находятся в цикле сокращения, они должны происходить с каждым частичным результатом.

  2. Да, я верю в это.

2

Другие решения

Условие сокращения требует, чтобы операция была ассоциативной и x = a[i] - x операция в

for(int i=0; i<n; i++) x = a[i] - x;

не является ассоциативным Попробуйте несколько итераций.

n = 0:  x = x0;
n = 1:  x = a[0] - x0;
n = 2:  x = a[1] - (a[0] - x0)
n = 3:  x = a[2] - (a[1] - (a[0] - x0))
= a[2] - a[1] + a[0] - x0;

Но x = x - a[i] работает, например

n = 3:  x = x0 - (a[2] + a[1] + a[0]);

Однако есть обходной путь. Знак чередует каждый второй термин. Вот рабочее решение.

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

int main(void) {
int n = 18;

float x0 = 3;

float a[n];
for(int i=0; i<n; i++) a[i] = i;
float x = x0;
for(int i=0; i<n; i++) x = a[i] - x; printf("%f\n", x);

int sign = n%2== 0 ? -1 : 1 ;
float s = -sign*x0;
#pragma omp parallel
{
float sp = 0;
int signp = 1;
#pragma omp for schedule(static)
for(int i=0; i<n; i++) sp += signp*a[i], signp *= -1;

#pragma omp for schedule(static) ordered
for(int i=0; i<omp_get_num_threads(); i++)
#pragma omp ordered
s += sign*sp, sign *= signp;
}
printf("%f\n", s);
}

Вот более простая версия, которая использует reduction пункт. Следует отметить, что все нечетные термины — это один знак, а четные — другой. Таким образом, если мы делаем сокращение двумя членами за раз, знак не меняется, и операция является ассоциативной.

x = x0;
for(int i=0; i<n; i++) x = a[i] - x

можно уменьшить параллельно, как это.

x = n%2 ? a[0] - x0 : x0;
#pragma omp parallel for reduction (+:x)
for(int i=0; i<n/2; i++) x += a[2*i+1+n%2] - a[2*i+n%2];
0