Подтвердить что ты не робот

Можно ли уменьшить сокращение массива с помощью openmp?

Поддерживает ли OpenMP поддержку сокращения переменной, представляющей массив?

Это будет работать примерно так:

float* a = (float*) calloc(4*sizeof(float));
omp_set_num_threads(13);
#pragma omp parallel reduction(+:a)
for(i=0;i<4;i++){
   a[i] += 1;  // Thread-local copy of a incremented by something interesting
}
// a now contains [13 13 13 13]

В идеале, для omp-параллели есть что-то подобное, и если у вас есть достаточно большое количество потоков, чтобы это имело смысл, накопление произойдет через двоичное дерево.

4b9b3361

Ответ 2

Теперь с OpenMP 4.5 для C и С++ возможно сокращение массивов. Вот пример:

#include <iostream>

int main()
{

  int myArray[6] = {};

  #pragma omp parallel for reduction(+:myArray[:6])
  for (int i=0; i<50; ++i)
  {
    double a = 2.0; // Or something non-trivial justifying the parallelism...
    for (int n = 0; n<6; ++n)
    {
      myArray[n] += a;
    }
  }
  // Print the array elements to see them summed   
  for (int n = 0; n<6; ++n)
  {
    std::cout << myArray[n] << " " << std::endl;
  } 
}

Выходы:

100
100
100
100
100
100

Я скомпилировал это с помощью GCC 6.2. Вы можете видеть, какие распространенные версии компилятора поддерживают функции OpenMP 4.5 здесь: http://www.openmp.org/resources/openmp-compilers/

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

Ответ 4

OpenMP не может выполнять сокращения по переменным типа массива или структуры (см. ограничения).

Вы также можете прочитать private и shared. private объявляет переменную частной для каждого потока, где shared объявляет переменную, которая будет использоваться для всех потоков. Я также нашел ответ на этот question очень полезный для OpenMP и массивов.

Ответ 5

OpenMP может выполнять эту операцию с OpenMP 4.5, а GCC 6.3 (и, возможно, ниже) поддерживает ее. Пример программы выглядит следующим образом:

#include <vector>
#include <iostream>

int main(){
  std::vector<int> vec;

  #pragma omp declare reduction (merge : std::vector<int> : omp_out.insert(omp_out.end(), omp_in.begin(), omp_in.end()))

  #pragma omp parallel for default(none) schedule(static) reduction(merge: vec)
  for(int i=0;i<100;i++)
    vec.push_back(i);

  for(const auto x: vec)
    std::cout<<x<<"\n";

  return 0;
}

Обратите внимание, что omp_out и omp_in являются специальными переменными и что тип declare reduction должен соответствовать вектору, который вы планируете уменьшить.