OPENMP C ++ для вложенных циклов и дальнейшей оптимизации - PullRequest
0 голосов
/ 24 декабря 2018

Я новичок в OpenMP и пытаюсь распараллелить следующий цикл for, который включает в себя 2 внутренних цикла for.При помощи 2-го внутреннего цикла в зависимости от результата 1-го.

После прочтения следующего ответа я распараллелил внешний цикл.

Теперь я бы хотел распараллелить 2 внутренних цикла .Чтобы заняться этим, я подумал о том, чтобы их вложить.

Меня беспокоит условия гонки , которые могут возникнуть.Я читал об объявлении private vars.Это способ избежать этой проблемы?

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

#include <iostream>
#include <cstring>
#include <vector>
#include <string>
#include <random>
#include <algorithm>
#include <omp.h>

int main(int argc, const char *argv[]) {

  const int N = 1000000;
  const double T = 1;
  const int r = 0;
  const int K = 100;
  const double s = 0.5;
  const int S0 = 100;
  const int m = 1000;
  const double k=0.9;

  const double D = T / m;

  std::vector<double> A;
  std::vector<double> kappa(21, 0);
  std::vector<double> U(21, 0);

  const double distMean = (r -  pow (s, 2.0) / 2) * D;
  const double distStdDev = s * pow(D, 0.5);
  const int distSize = 1000;

  #pragma omp parallel for num_threads(8)
  for (int i = N; i > 0; --i) {

    std::random_device randDev; //print this one separately
    std::mt19937 generator(randDev());
    std::normal_distribution<double> dist(distMean, distStdDev);

    std::vector<double> X;
    X.reserve(distSize + 1);

    #pragma omp parallel for //num_threads(8)
    for (int m = distSize; m > 0; --m) {
      X.push_back(dist(generator)); 
    }

    std::vector<double> XCumSum(1000);
    std::partial_sum(X.begin(), X.end(), XCumSum.begin(), std::plus<double>());

    std::vector<double> expCumSum;
    expCumSum.reserve(distSize + 1);

    for (int m = distSize; m > 0; --m) {
      expCumSum.push_back( exp( XCumSum[m] ) );  
    }

    double maxPart2 = k * S0 * ( std::accumulate(expCumSum.begin(), expCumSum.end(), 0.0) / expCumSum.size() ) ;
    double maxPart1 = S0 * exp(std::accumulate(X.begin(), X.end(), 0.0));
    double result = exp(-r*T) * std::max( (maxPart1 - maxPart2), 0.0 );

    A.reserve(N + 1);
    A.push_back(result);

  }
  float ASumMean = ( std::accumulate(A.begin(), A.end(), 0.0) ) / A.size();
  std::cout << ASumMean << std::endl;
  return ASumMean;
}

Я компилирую это с

g++-8.2 -O3 -o tests tests.cpp

Безfopenmp мои результаты:

16.6318

real    1m27.113s
user    1m14.483s
 sys    0m11.217s

С fopenmp, с использованием g++-8.2 -O3 -o tests tests.cpp -fopenmp, и результаты:

16.6555

real    0m39.474s
user    1m42.468s
 sys    0m30.546s

Это ожидаемые результаты, но время иУскорение, заставьте меня усомниться в фактическом кодировании цикла.

PS: довольно плохо знаком с C ++.Всегда приветствуются любые предложения о том, как улучшить мой стиль, или советы по передовому опыту.

...