Как преобразовать цикл в оператор STL for_each - PullRequest
5 голосов
/ 09 марта 2010

Я хотел бы преобразовать цикл for в цикл STL std :: for_each.

 bool CMyclass::SomeMember()
 {
    int ii;
        for(int i=0;i<iR20;i++)
            {
              ii=indexR[i];
              ishell=static_cast<int>(R[ii]/xStep);
              theta=atan2(data->pPOS[ii*3+1], data->pPOS[ii*3]);
              al2[ishell] += massp*cos(fm*theta);
            }
 }

На самом деле я планировал использовать параллельный STL из g ++ 4.4

 g++ -D_GLIBCXX_PARALLEL -fopenmp

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

Ответы [ 4 ]

5 голосов
/ 09 марта 2010

Вы должны отделить тело цикла в отдельную функцию или функтор; Я предположил, что все необъявленные переменные являются переменными-членами.

void CMyclass::LoopFunc(int ii)  {
    ishell=static_cast<int>(R[ii]/xStep);
    theta=atan2(data->pPOS[ii*3+1],
    data->pPOS[ii*3]);
    al2[ishell] += massp*cos(fm*theta);
}

bool CMyclass::SomeMember()  { 
    std::for_each(&indexR[0],&indexR[iR20],std::tr1::bind(&CMyclass::LoopFunc,std::tr1::ref(*this));
}
1 голос
/ 09 марта 2010

Вы не можете просто разделить тело цикла на функтор и предположить, что он будет паралелизирован, потому что внутри тела цикла слишком много зависимостей. Цикл сможет работать параллельно, только если у вас нет глобальных массивов или указателей. Если вы предоставите полнофункциональное тело, то мы можем подумать, как изменить его на параллельную версию.

1 голос
/ 09 марта 2010
class F {
   public:
   void operator()(int ii) {
              ishell=static_cast<int>(R[ii]/xStep);
              theta=atan2(data->pPOS[ii*3+1], data->pPOS[ii*3]);
              al2[ishell] += massp*cos(fm*theta);
   } 
   F(int[] r): //and other parameters should also be passed into the constructor
      r_(r) {}
   void:
   int[] r_; // refers to R[ii] array
   // and other parameters should also be stored
};

F f(R); // pass other parameters too  
for_each(&indexR[0], &indexR[iR20], f);

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

0 голосов
/ 09 марта 2010

Вам нужно будет преобразовать тело цикла в функцию или функтор. Там много необъявленных переменных, поэтому я не могу легко сказать, как отделить тело цикла. Вот удар в этом:

class DoStuff
{
  int* R;
  int xStep;
  Data* data;
  double massp;
  double fm;
  double* al2;
public:
  DoStuff(int* R_, int xStep_, Data* data_, double massp_, double fm_, double* al2_) :
    R(R_), xStep(xStep_), data(data_), massp(massp_), fm(fm_), al2(al2_) {}

  void operator()(int ii)
  {
     int ishell = static_cast<int>(R[ii]/xStep);
     double theta = atan2(data->pPOS[ii*3+1], data->pPOS[ii*3]);
     al2[ishell] += massp*cos(fm*theta);
  }
};

for_each(indexR, indexR+iR20, DoStuff(R, xStep, data, massp, fm, al2));
...