Распараллеливание простого цикла с алгоритмами c ++ 17 - PullRequest
0 голосов
/ 04 февраля 2019

У меня есть параллельный код, который можно сократить до:

#include <algorithm>
#include <vector>

struct TKeyObjPtr;

class TObj
{
public:
  virtual void Calculate(TKeyObjPtr const &) = 0;
};

struct TKeyObjPtr
{
  int Key;
  TObj *ObjPtr;
};

void Calculate(std::vector<TKeyObjPtr> const &KeyObjPtrVec)
{
  #pragma omp parallel for
  for (auto It1= KeyObjPtrVec.begin(); It1!=KeyObjPtrVec.end(); ++It1)
    for (auto It2= It1+1; It2!=KeyObjPtrVec.end() && It2->Key==It1->Key; ++It2)
      It1->ObjPtr->Calculate(*It2);
}

Я бы хотел модернизировать этот код с помощью параллельных алгоритмов .К сожалению, у меня возникают проблемы при переписывании такого простого куска кода.

Можно использовать параметр boost::counting_iterator:

void Calculate(std::vector<TKeyObjPtr> const &KeyObjPtrVec)
{
  std::for_each(std::execution::par_unseq,
    boost::counting_iterator<std::size_t>(0u),
    boost::counting_iterator<std::size_t>(KeyObjPtrVec.size()),
    [&KeyObjPtrVec](auto i)
      {
        for (auto j= i+1; j<KeyObjPtrVec.size() && KeyObjPtrVec[j].Key==KeyObjPtrVec[i].Key; ++j)
          KeyObjPtrVec[i].ObjPtr->Calculate(KeyObjPtrVec[j]);
      });
}

Это работает, нозначительно более многословный и, что еще хуже, я не думаю, что он соответствует стандарту, потому что boost::counting_iterator является итератором хранения и, следовательно, не соответствует Cpp17ForwardIterator требованиям .

Можно ли написать приведенный выше код так же лаконично, как с OpenMP, при соблюдении ограничений стандарта на параллельные алгоритмы?

...