tags:

views:

321

answers:

4

Hi, I would like to convert my for loop to STL std::for_each loop.

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

Actually I was planning to use parallel STL from g++4.4

 g++ -D_GLIBCXX_PARALLEL -fopenmp

which is allow to run code in parallel without changes if the code is written in standard STL library.

Thanks in advanced Arman.

A: 

You'll need to convert the loop body into a function or functor. There are a lot of undeclared variables in there, so I can't easily tell how to separate out the loop body. Here's a stab at it:

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));
Fred Larson
When using initialisation list, you don't have to rename arguments. I.e. `R(R)` etc. will work just fine.
PiotrLegnica
Yes, I'm aware of that.
Fred Larson
+4  A: 

You need to seperate out the loop body into a seperate function or functor; I've assumed all the undeclared variables are member variables.

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));
}
Joe Gauterin
Nice!! this concept is the best. Thanks!
Arman
Is this solution thread safe? I would assume not. If the parallel `for_each` splits the loop into different threads, all of them will be accessing the same member attributes without any kind of protection.
David Rodríguez - dribeas
He'd need to be careful about thread safety - his original code didn't make clear what variables were locals and which were member variables. Writing to index i and index i+1 in different threads should be safe for an array of ints shouldn't it?
Joe Gauterin
If you read from the member from different threads you don't need to worry. For writing probably I need a lock.
Arman
+1  A: 
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);

However it might not be a good idea to use this "automatic parallelization" since you need to keep in mind the grainsize of each parallel computation -- I am not sure how well the compiler takes the grain size into account.

Amit Kumar
This looks good, but imagine I have several loops in the SomeMember() function and we need to define Class like functors for the every loop.
Arman
Yes. That's the C++ way of functional programming. If you're gonna do this, you may as well use Intel TBB and use parallel_for for parallelization (TBB is the way I prefer).
Amit Kumar
Yes TBB well designed, but I am a researcher, I prefer GPL software.
Arman
Not sure why you prefer GPL. The TBB license (GPL with runtime exception) should be compatible with GPL (although I am not a lawyer and cannot make a reliable statement). Or do you mean you prefer open-source? Then, that's a different thing.
Amit Kumar
yes, I mean open-source.
Arman
+1  A: 

You cannot just separate cycle body into functor and assume that it will be paralellised because you have too many dependencies inside cycle body. Cycle will be able to run in parallel only if you have no global arrays or pointers. If you provide full function body then we can think how to change it to parallel version.

Oleg