2010-03-09 11 views
5

Vorrei convertire il mio ciclo for in STL std :: for_each loop.Come convertire per loop in STL istruzione 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); 
      } 
} 

In realtà avevo intenzione di usare STL parallelo da g ++ 4,4

g++ -D_GLIBCXX_PARALLEL -fopenmp 

che permettono di eseguire il codice in parallelo senza modifiche se il codice è scritto in libreria STL standard.

+1

Perché non semplicemente '#pragma omp parallel for' prima del for? – stephan

+1

+1 stephan, anche se tje 'al2 [ishell]' ** + = ** ha bisogno di una clausola di riduzione o di una barriera atomica. Non sono sicuro di come questo si tradurrebbe in parallelo STL. – peterchen

+0

Sì, una delle soluzioni sarà "#pragma omp parallel for" ma sempre prima di ciascuna per una necessità di considerare variabili condivise e private. che è sempre una delle fonti di errori. – Arman

risposta

5

È necessario separare il corpo del loop in una funzione o un funceper separati; Ho assunto che tutte le variabili non dichiarate siano variabili membro.

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

Bello !! questo concetto è il migliore Grazie! – Arman

+1

Questa discussione è sicura? Non darei per scontato. Se il parallelo 'for_each' divide il ciclo in thread diversi, tutti accederanno agli stessi attributi del membro senza alcun tipo di protezione. –

+0

Avrebbe bisogno di fare attenzione alla sicurezza dei thread: il suo codice originale non chiariva quali variabili fossero i locali e quali fossero le variabili membro. Scrivere per indicizzare i e index i + 1 in thread diversi dovrebbe essere sicuro per una serie di ints, non dovrebbe? –

0

Avrete bisogno di convertire il corpo del loop in una funzione o un funtore. Ci sono molte variabili non dichiarate, quindi non posso facilmente dire come separare il corpo del ciclo. Ecco una pugnalata:

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)); 
+0

Quando si utilizza l'elenco di inizializzazione , non è necessario rinominare gli argomenti. Cioè 'R (R)' ecc. Funzionerà bene. –

+0

Sì, ne sono a conoscenza. –

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

Tuttavia potrebbe non essere una buona idea di utilizzare questo "parallelizzazione automatica", in quanto è necessario tenere a mente la grainsize di ogni calcolo parallelo - Non sono sicuro di quanto bene il compilatore prende il dimensione del grano in considerazione.

+0

Sembra buono, ma immagino di avere diversi loop nella funzione SomeMember() e abbiamo bisogno di definire i functors di classe per ogni loop. – Arman

+0

Sì. Questo è il modo C++ di programmazione funzionale. Se lo farai, potresti usare anche Intel TBB e usare parallel_for per la parallelizzazione (TBB è il modo che preferisco). –

+0

Sì TBB ben progettato, ma io sono un ricercatore, preferisco il software GPL. – Arman

1

Non è possibile separare il corpo del ciclo in funtore e assumere che esso sarà paralizzato perché si hanno troppe dipendenze all'interno del corpo del ciclo. Il ciclo potrà essere eseguito in parallelo solo se non si dispone di matrici o puntatori globali. Se fornisci il corpo completo della funzione, possiamo pensare a come cambiarlo in versione parallela.

Problemi correlati