簡體   English   中英

使用重載運算符減少OpenMP

[英]OpenMP reduction with overloaded operator

我正在嘗試使用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;
     }

當我編譯代碼時,它給出以下消息:

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’

我知道變量'force0'和'torque0'既不是雙重或整數類型的數據,而是類型'CPnt',這是一個定義為表示空間中三維向量的類。 對於類'CPnt',運算符'+'和' - '已經由運算符重載定義。 所以我的問題是:OpenMP的減少是否真的無法處理這樣的重載運算符? 有沒有其他方法可以將此循環與OpenMP並行化而不減少'force0'和'torque0'的每個組件?

非常感謝。

確實,OpenMP減少無法處理這樣的重載運算符。 但是,還有另一種選擇。 重寫OpenMP減少的一種方法是使用nowaitatomic參數。 http://bisqwit.iki.fi/story/howto/openmp/#ReductionClause 。這和正常方式一樣快。

如果將atomic替換為critical ,則可以使用更復雜的重載運算符。 這並不像使用atomic那么快,但它在我的經驗中仍然有效。

我這樣做了所以我可以使用同時操作4或8個浮點數的運算符(使用SEE或AVX)。 使用SSE / AVX進行OpenMP減少

編輯:我改變了你的代碼,以反映我認為你想做的事情。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM