簡體   English   中英

openMP-需要原子或歸約子句

[英]openMP - need for atomic or reduction clauses

我正在使用openMP並行化一些語句。 我正在使用並行進行構造。 並行化的for循環如下所示:

double solverFunction::apply(double* parameters_ , Model* varModel_)  
{
     double functionEvaluation = 0;
     Command* command_ = 0;
     Model* model_ = 0;

     #pragma omp parallel for  shared (functionEvaluation) private (model_,command_)
     for (int i=rowStart;i<rowEnd+1;i++)
     {
         model_ = new Model(varModel_);
         model_->addVariable("i", i);
         model_->addVariable("j", 1);
         command_ = formulaCommand->duplicate(model_);
         functionEvaluation += command_->execute().toDouble();
     }
}

平均來說,它是可行的 執行時間大大減少,結果與預期的一樣 但是,有時,尤其是對於大問題(i上的大量迭代,需要在復制構造函數中復制的大量數據)

 model_ = new Model(varModel_);

,其他?),它崩潰了。 調用棧以諸如qAtomicBasic(它是用C ++ / Qt編寫的程序),QHash之類的類結束的,我有一個想法,即由於內存中同時進行讀/寫訪問,它會崩潰。

但是,model_和command_是私有的,因此每個線程都處理每個副本。 在變量model_中,我復制varModel_,以便傳入參數的指針不會被線程更改。 類似地,command_是成員變量FormulaCommand的副本(重復的副本通常是副本構造函數)。

我確定的代碼中可能存在的缺陷是

  • functionEvaluation可以同時由多個線程修改

  • 在語句中復制構造函數

    model_ =新模型(varModel_);

讀取內存中varModel_的成員以構造新的(model_)實例。 可以同時訪問varModel_數據成員,盡管這與更改其值無關,而只是讀取它們(影響它們到其他變量)。

此外,我僅看到兩項改進(我幾天后才能測試,但無論如何我都尋求建議):

  • 添加原子子句,以便不會同時寫入functionEvalution

  • 添加運算符減少(+,functionEvaluation),以便自動處理與訪問functionEvaluation有關的並發

這些解決方案似乎正確地解決了問題,並且總體上更有效嗎? 問題出在哪里與我編寫的代碼有關? 有什么解決方案?

非常感謝!

最初的觀察是,正如您已經注意到的那樣,同時修改functionEvaluation是一個壞主意。 失敗。

另一方面,對varModel_的只讀訪問不是問題。 復制構造函數調用也不是(但是它在哪里?您的代碼沒有顯示它)。

無關地,在C ++中使用private子句是一個壞主意。 只需在並行塊聲明線程專用變量(在本例中for循環)。

我也看不到為什么在這里使用指針。 它們的使用沒有直接意義-而是使用堆棧分配的對象。

下面的修改后的代碼應該可以工作(我還自由地統一了編碼風格……為什么在末尾加下划線?):

double solverFunction::apply(double parameters, Model const& varModel)
{
     double result = 0;

     #pragma omp parallel for reduction(+:result)
     for (int i = rowStart; i < rowEnd + 1; ++i)
     {
         Model model(varModel);
         mode.addVariable("i", i);
         mode.addVariable("j", i);
         Command command = formulaCommand->duplicate(model);
         result += command.execute().toDouble();
     }

     return result;
}

請注意,由於固有的浮點錯誤,此代碼可能會產生與順序代碼不同的結果。 這是不可避免的。

同時修改functionEvaluation絕對是代碼中的問題,處理它的最佳方法是reduction子句。

另一個問題是您通過並行調用new來分配堆內存,對於許多迭代而言,這絕不是一個好主意,因為在系統范圍內,對new調用都處於鎖定狀態。 考慮切換到棧分配,因為棧是每個線程專用的,而堆是共享的。

暫無
暫無

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

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