Алгоритмы OpenMp C++ для минимума, максимума, медианы, среднего [закрыто]

StackOverflow https://stackoverflow.com/questions/978222

Вопрос

Я искал в Google страницу, предлагающую несколько простых алгоритмов OpenMp.Вероятно, есть пример расчета минимума, максимума, медианы и среднего значения из огромного массива данных, но я не могу его найти.

По крайней мере, я обычно пытаюсь разделить массив на один фрагмент для каждого ядра и затем выполнить некоторые граничные вычисления, чтобы получить результат для всего массива.

Я просто не хотел изобретать велосипед.


Дополнительное примечание:Я знаю, что существуют тысячи примеров, которые работают с простым сокращением.напримерРасчет ПИ.

const int num_steps = 100000; 
double x, sum = 0.0; 
const double step = 1.0/double(num_steps); 
#pragma omp parallel for reduction(+:sum) private(x) 
for (int i=1;i<= num_steps; i++){ 
  x = double(i-0.5)*step; 
  sum += 4.0/(1.0+x*x); 
} 
const double pi = step * sum;

но когда подобные алгоритмы непригодны для использования, практически не остается примеров сокращения алгоритмов.

Это было полезно?

Решение

OpenMP (по крайней мере 2.0) поддерживает сокращение для некоторых простых операций, но не для максимального и минимального.

В следующем примере reduction Предложение используется для суммирования и critical раздел используется для обновления общей переменной с использованием локальной для потока переменной без конфликтов.

#include <iostream>
#include <cmath>

int main()
{
  double sum = 0;
  uint64_t ii;
  uint64_t maxii = 0;
  uint64_t maxii_shared = 0;
#pragma omp parallel shared(maxii_shared) private(ii) firstprivate(maxii)
  {
#pragma omp for reduction(+:sum) nowait
    for(ii=0; ii<10000000000; ++ii)
      {
        sum += std::pow((double)ii, 2.0);
        if(ii > maxii) maxii = ii;
      }
#pragma omp critical 
    {
      if(maxii > maxii_shared) maxii_shared = maxii;
    }
  }
  std::cerr << "Sum: " << sum << " (" << maxii_shared << ")" << std::endl;
}

РЕДАКТИРОВАТЬ:более чистая реализация:

#include <cmath>
#include <limits>
#include <vector>
#include <iostream>
#include <algorithm>
#include <tr1/random>

// sum the elements of v
double sum(const std::vector<double>& v)
{
  double sum = 0.0;
#pragma omp parallel for reduction(+:sum)
  for(size_t ii=0; ii< v.size(); ++ii)
    {
      sum += v[ii];
    }
  return sum;
}

// extract the minimum of v
double min(const std::vector<double>& v)
{
  double shared_min;
#pragma omp parallel 
  {
    double min = std::numeric_limits<double>::max();
#pragma omp for nowait
    for(size_t ii=0; ii<v.size(); ++ii)
      {
        min = std::min(v[ii], min);
      }
#pragma omp critical 
    {
      shared_min = std::min(shared_min, min);
    }
  }
  return shared_min;
}

// generate a random vector and use sum and min functions.
int main()
{
  using namespace std;
  using namespace std::tr1;

  std::tr1::mt19937 engine(time(0));
  std::tr1::uniform_real<> unigen(-1000.0,1000.0);
  std::tr1::variate_generator<std::tr1::mt19937, 
    std::tr1::uniform_real<> >gen(engine, unigen);

  std::vector<double> random(1000000);
  std::generate(random.begin(), random.end(), gen);

  cout << "Sum: " << sum(random) << " Mean:" << sum(random)/random.size()
       << " Min:" << min(random) << endl;
}

Другие советы

в OpenMP 3.1 и более поздних версиях можно реализовать предложение min, max посредством сокращения, вы можете посмотреть подробный пример, описывающий это, в эта ссылка.

OpenMP не поддерживает эти операции сокращения.Рассмотрим алгоритм Parallel_reduce Intel Threading Building Blocks, в котором можно реализовать произвольный алгоритм.

Вот пример.Он использует суммирование частичных результатов.Вы можете реализовать любую функцию, какую захотите.

#include <stdio.h>
#include <tbb/blocked_range.h>
#include <tbb/parallel_reduce.h>
#include <tbb/task_scheduler_init.h>


///////////////////////////////////////////////////////////////////////////////


class PiCalculation
{
private:
    long num_steps;
    double step;

public:

    // Pi partial value
    double pi;

    // Calculate partial value
    void operator () (const tbb::blocked_range<long> &r) 
    {
        double sum = 0.0;

        long end = r.end();

        for (int i = r.begin(); i != end; i++)
        {
            double x = (i + 0.5) * step;
            sum += 4.0/(1.0 + x * x);
        }

        pi += sum * step;
    }

    // Combine results. Here you can implement any functions
    void join(PiCalculation &p)
    {
        pi += p.pi;
    }

    PiCalculation(PiCalculation &p, tbb::split)
    {
        pi = 0.0;
        num_steps = p.num_steps;
        step = p.step;
    }

    PiCalculation(long steps)
    {
        pi = 0.0;
        num_steps = steps;
        step = 1./(double)num_steps;
    }
};


///////////////////////////////////////////////////////////////////////////////


int main()
{
    tbb::task_scheduler_init init;

    const long steps = 100000000;

    PiCalculation pi(steps);

    tbb::parallel_reduce(tbb::blocked_range<long>(0, steps, 1000000), pi);

    printf ("Pi is %3.20f\n", pi.pi);
}

Пожалуйста, проверьте эту ссылку для получения дополнительных алгоритмов сокращения. http://cache-www.intel.com/cd/00/00/30/11/301132_301132.pdf#page=19 Пожалуйста, ознакомьтесь с пунктом 3.3.1.Существует пример поиска минимального значения в массиве.

Это типичные проблемы сокращения.

Кроме страница, на которую указывает Сувеш, вы можете взглянуть на документацию для оговорка о сокращении.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top