Pergunta

Eu estava procurando Google para uma página que oferece alguns algoritmos simples OpenMP. Provavelmente não é um exemplo para min calcular, máximo, mediana, média de uma matriz de dados enorme, mas eu não sou capaz de encontrá-lo.

Pelo menos eu normalmente tentar dividir a matriz em um pedaço para cada núcleo e fazer alguns cálculos de limite depois de obter o resultado para a matriz completa.

Eu só não queria reinventar a roda.


Observação adicionais: Eu sei que há milhares de exemplos que trabalham com redução simples. por exemplo. Calculando PI.

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;

mas quando estes tipos de algoritmos não são utilizáveis ??quase não há exemplos deixados para reduzir algoritmos.

Foi útil?

Solução

OpenMP (pelo menos 2,0) suporta redução para algumas operações simples, mas não para o máximo e mínimo.

No exemplo a seguir a cláusula reduction é usado para fazer uma soma e uma seção critical é usado para atualizar uma variável compartilhada usando um segmento local sem conflitos.

#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;
}

EDIT: uma implementação mais limpo:

#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;
}

Outras dicas

em OpenMP 3.1 em diante se pode implementar para min, max através de cláusula de redução, você pode dar uma olhada no exemplo detalhado cobrindo isso em este link .

OpenMP não suporta estas operações de redução. Considere algoritmo parallel_reduce Intel Threading Building Blocks', onde você pode implementar algoritmo arbitrário.

Aqui um exemplo. Ele usa somatório dos resultados parciais. Você pode executar qualquer função que deseja.

#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);
}

Por favor, verifique este link para algoritmos de redução adicionais. http://cache-www.intel .com / cd / 00/00/30/11 / 301132_301132.pdf # page = 19 olha por favor através ponto 3.3.1. Há um exemplo em encontrar o valor mínimo em uma matriz.

Isto são problemas típicos de redução.

Além página apontada por Suvesh , você pode ter um olhar a documentação para o redução cláusula .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top