OpenMP Acronym with Overloaded Operator

I am trying to parallelize a loop in the following function using OpenMP

void CEnergymulti::forcetwobody(vector<CMolecule*> m_mols,CPnt force0,CPnt torque0) { const int nmol=m_mols.size(); vector<CMolecule*> twomols(2); CPnt forcetemp,torquetemp; twomols.clear(); force0.zero(); torque0.zero(); forcetemp.zero(); torquetemp.zero(); #pragma omp parallel for reduction(+:force0,torque0) private(twomols) for(int j=1;j<nmol;j++) { twomols.push_back(m_mols[0]); twomols.push_back(m_mols[j]); CMolecule::polarize_mutual(twomols,false, 1000); twomols[0]->computeMol_Force_and_Torque(forcetemp,torquetemp); force0+=forcetemp; torque0+=torquetemp; forcetemp.zero(); torquetemp.zero(); twomols.clear(); } REAL converter=COUL_K*IKbT; force0*=converter; torque0*=converter; return; } 

When I compile the code, it gives the following message:

 EnergyD_multi.cpp: In static member function 'static void CEnergymulti::forcetwobody(std::vector<CMolecule*, std::allocator<CMolecule*> >, CPnt, CPnt)': EnergyD_multi.cpp:226: error: 'torque0' has invalid type for 'reduction' EnergyD_multi.cpp:226: error: 'force0' has invalid type for 'reduction' 

I understand that the variables "force0" and "torque0" are not data of double or integer type, but of type "CPnt", a class that is defined to represent three-dimensional vectors in space. For the CPnt class, the + and - operators are already defined by operator overloading. So my questions are: is it true that the OpenMP abbreviation cannot handle such overloaded statements? Are there alternative ways to parallelize this loop using OpenMP without decreasing force0 and torque0 on each component?

Thank you very much.

+6
source share
2 answers

It is true that OpenMP reduction cannot handle such overloaded statements. However, there is an alternative. One way to rewrite abbreviation in OpenMP is to use the nowait and atomic options. http://bisqwit.iki.fi/story/howto/openmp/#ReductionClause This is as fast as the normal way.

If you replace atomic with critical , you can use more complex overloaded operators. It's not as fast as using atomic , but it still works well in my experience.

I did this to use operators that work with 4 or 8 floats at the same time (using SEE or AVX). using OpenMP with SSE / AVX

Edit: I modified my code to reflect what I think will do what you want.

 void CEnergymulti::forcetwobody(vector<CMolecule*> m_mols,CPnt force0,CPnt torque0) { const int nmol=m_mols.size(); force0.zero(); torque0.zero(); #pragma omp parallel { CPnt force0_private; CPnt torque0_private; force0_private.clear(); torque0_private.clear(); #pragma omp for nowait for(int j=1;j<nmol;j++) { CPnt forcetemp,torquetemp; forcetemp.zero(); torquetemp.zero(); vector<CMolecule*> twomols(2); twomols.clear(); twomols.push_back(m_mols[0]); twomols.push_back(m_mols[j]); CMolecule::polarize_mutual(twomols,false, 1000); twomols[0]->computeMol_Force_and_Torque(forcetemp,torquetemp); force0_private+=forcetemp; torque0_private+=torquetemp; } #pragma omp critical { force0 += force0_private; torque0 += torque0_private; } } REAL converter=COUL_K*IKbT; force0*=converter; torque0*=converter; return; } 
+7
source

Nowadays, you can also use the declare reduction directive (OpenMP 4. 0+); eg,

 #pragma omp declare reduction(mysum:CPnt:omp_out += omp_in) initializer(omp_priv.zero()) #pragma omp parallel for reduction(mysum:force0,torque0) private(twomols) for(int j=1;j<nmol;j++) ... 
+2
source

Source: https://habr.com/ru/post/943467/


All Articles