私は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_ = new Model(varModel_);
メモリ内のvarModel_のメンバーを読み取り、新しい(model_)インスタンスを構築します。varModel_データメンバーへの同時アクセスが発生する可能性がありますが、これはここで値を変更することではなく、それらを読み取る(他の変数に影響を与える)だけです。
また、2つの改善のみが見られます(数日までテストできませんが、とにかくアドバイスを求めます)。
functionEvalutionが同時に書き込まれないようにアトミック句を追加します
functionEvaluationへのアクセスに関する同時実行性が自動的に処理されるように、演算子reduction(+、functionEvaluation)を追加します
これらの解決策は問題を正確に解決しているように見えますか?一般的にどちらがより効率的ですか?私が書いたコードのどこに問題があるのでしょうか?解決策は何ですか?
どうもありがとう!