Ich habe eine Funktion innerhalb einer Klasse, die ich millionenfach in meinem Code aufrufen. In dieser Funktion gibt es anspruchsvolle Schleifen, die parallelisiert werden können. Mein Problem ist, dass sie Summierungen durchführen, die in nicht-skalaren Variablen gespeichert sind. Hier ist der Code.Parallele Summierung mit openMP - was kann ich tun, wenn ich die Reduktionsklausel nicht nutzen kann?
void Forces::ForRes(vector<vector<double> > & Posicoes,double epsilon,double sigma,double rc,double L)
{
double rij_2,rij_6,rij_12,rijx,rijy,rijz;
double t;
double sigma6 = pow(sigma,6);
double sigma12 = pow (sigma6,2);
for (unsigned int i = 0 ; i < Posicoes.size() - 1 ; i++)
{
for (unsigned int j = i + 1 ; j < Posicoes.size() ; j++)
{
rijx = (Posicoes[i][0]-Posicoes[j][0]) - L*round((Posicoes[i][0]-Posicoes[j][0])/L);
rijy = (Posicoes[i][1]-Posicoes[j][1]) - L*round((Posicoes[i][1]-Posicoes[j][1])/L);
rijz = (Posicoes[i][2]-Posicoes[j][2]) - L*round((Posicoes[i][2]-Posicoes[j][2])/L);
rij_2 = rijx*rijx + rijy*rijy + rijz*rijz;
rij_6 = pow(rij_2,3);
rij_12 = pow(rij_6,2);
if (rij_2 <= rc*rc)
{
U += 4*epsilon*((sigma12)/(rij_12)- (sigma6)/(rij_6));
for (int k =0 ; k <3 ; k++)
{
t = ((24*epsilon)/(rij_2))*(2*(sigma12)/(rij_12)- (sigma6)/(rij_6))*((Posicoes[i][k]-Posicoes[j][k])
- L*round((Posicoes[i][k]-Posicoes[j][k])/L));
F[i][k] += t;
F[j][k] -= t;
}
}
}
}
}
Hier ist ein Beispiel, das ich in einem anderen Teil des Codes habe:
#pragma omp parallel for default(shared) reduction(+:K) private(pi_2)
for (int i = 0 ; i < Nparticulas;i++)
{
for (int k = 0 ; k < 3 ; k++)
{
pi_2 += Momentos.M[i][k]*Momentos.M[i][k];
}
K += pi_2/2;
pi_2 = 0;
}
Vielen Dank im Voraus.
-Code nach @phadjido Vorschlag:
void Forces::ForRes(vector<vector<double> > & Posicoes,double epsilon,double sigma,double rc,double L)
{
double rij_2,rij_6,rij_12,rijx,rijy,rijz;
double t;
double sigma6 = pow(sigma,6);
double sigma12 = pow (sigma6,2);
U = 0;
unsigned int j;
for (unsigned int i = 0 ; i < Posicoes.size() - 1 ; i++)
{
#pragma omp parallel private (rij_2,rij_6,rij_12,j)
{
double Up = 0;
vector <vector <double> > Fp(Posicoes.size() , vector<double>(Posicoes[0].size(),0));
#pragma omp for
for (j = i + 1 ; j < Posicoes.size() ; j++)
{
rijx = (Posicoes[i][0]-Posicoes[j][0]) - L*round((Posicoes[i][0]-Posicoes[j][0])/L);
rijy = (Posicoes[i][1]-Posicoes[j][1]) - L*round((Posicoes[i][1]-Posicoes[j][1])/L);
rijz = (Posicoes[i][2]-Posicoes[j][2]) - L*round((Posicoes[i][2]-Posicoes[j][2])/L);
rij_2 = rijx*rijx + rijy*rijy + rijz*rijz;
rij_6 = pow(rij_2,3);
rij_12 = pow(rij_6,2);
if (rij_2 <= rc*rc)
{
Up += 4*epsilon*((sigma12)/(rij_12)- (sigma6)/(rij_6));
for (int k =0 ; k <3 ; k++)
{
t = ((24*epsilon)/(rij_2))*(2*(sigma12)/(rij_12)- (sigma6)/(rij_6))*((Posicoes[i][k]-Posicoes[j][k])
- L*round((Posicoes[i][k]-Posicoes[j][k])/L));
Fp[i][k] += t;
Fp[j][k] -= t;
}
}
}
#pragma omp atomic
U += Up;
for(j = i + 1 ; j < Posicoes.size() ; j++)
{
for (int k = 0 ; k < 3; k++)
{
#pragma omp atomic
F[i][k] += Fp[i][j];
#pragma omp atomic
F[j][k] -= Fp[j][k];
}
}
}
}
}
Und was ist Ihre Frage? – slav
es ist in der Frage Titel "Parallel Summation mit OpenMP - was zu tun, wenn ich die Reduktionsklausel nicht verwenden kann?" wie man die Schleifen im ersten Code parallelisiert. –
Sie können eine benutzerdefinierte Reduzierungsklausel verwenden, wie in [Benutzerdefinierte Verkleinerung auf Vektor unterschiedlicher Größe] erläutert (http://stackoverflow.com/questions/29633531/user-date-reduction-on-vector-of-vyinging-). Größe). – Tim