OpenMP reduction with overloaded operator

c++, openmp, operator-overloading, parallel-processing

Solution

It's true that OpenMP reduction can't handle such overloaded operators. However, there is an alternative. One way to rewrite a reduction in OpenMP is to use the `nowait` and `atomic` paramters. http://bisqwit.iki.fi/story/howto/openmp/#ReductionClause .This is just as fast as the normal way.

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

I did this so I could use operators that operate on 4 or 8 floats at once (with SEE or AVX). reduction with OpenMP with SSE/AVX

Edit: I changed your code to reflect what I think would 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;
}

Problem

I'm trying to parallelize the loop in the following function with 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 variables 'force0' and 'torque0' are neither double or integer type of data, but of type 'CPnt', a class that is defined to represent three-dimensional vectors in space. For class 'CPnt', operator '+' and '-' have already been defined by operator overloading. So my questions is: is it true that reduction in OpenMP cannot handle such overloaded operators? Is there any alternate ways to parallelize this loop with OpenMP without doing reduction on each component of 'force0' and 'torque0'? Thanks a lot.

Original source