[英]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.