【发布时间】:2012-04-26 17:54:44
【问题描述】:
我正在使用 openMP 来并行化一些语句。我正在使用 parallel for 构造。并行化的 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 的副本(duplicate 大致是一个复制构造函数)。
我发现的代码中可能存在的缺陷是
functionEvaluation 可以被多个线程同时修改
-
语句中的复制构造函数
model_ = new Model(varModel_);
读取内存中 varModel_ 的成员以构造新的 (model_) 实例。对 varModel_ 数据成员的并发访问可能会发生,尽管这不是要在此处更改它们的值,而只是读取它们(将它们影响到其他变量)。
另外,我只看到了两个改进(我要几天才能测试,但我还是征求意见):
添加原子子句,使得functionEvalution不会并发写入
添加运算符归约(+,functionEvaluation),以便自动处理访问functionEvaluation的并发
这些解决方案是否似乎准确地解决了问题,总体上哪种更有效?我写的代码哪里有问题?什么是解决方案?
非常感谢!
【问题讨论】:
标签: c++ multithreading multiprocessing openmp