我正在用C ++构建适用于Autodesk Maya 2013的插件。我必须尽快解决一系列优化问题。我为此任务使用了开放式MP。问题是我在并行计算方面没有太多经验。我尝试使用:
#pragma omp parallel for schedule (static)
在我的for循环上(对它应该如何工作没有足够的了解),它对我的某些代码非常有效,但是使我的另一部分代码崩溃了。
这是一个由于omp指令而崩溃的函数示例:
void PlanarizationConstraint::fillSparseMatrix(const Optimizer& opt, vector<T>& elements, double mu)
{
int size = 3;
#pragma omp parallel for schedule (static)
for(int i = 0; i < opt.FVIc.outerSize(); i++)
{
int index = 3*i;
Eigen::Matrix<double,3,3> Qxyz = Eigen::Matrix<double,3,3>::Zero();
for(SpMat::InnerIterator it(opt.FVIc,i); it; ++it)
{
int face = it.row();
for(int n = 0; n < size; n++)
{
Qxyz.row(n) += N(face,n)*N.row(face);
elements.push_back(T(index+n,offset+face,(1 - mu)*N(face,n)));
}
}
for(int n = 0; n < size; n++)
{
for(int k = 0; k < size; k++)
{
elements.push_back(T(index+n,index+k,(1-mu)*Qxyz(n,k)));
}
}
}
#pragma omp parallel for schedule (static)
for(int j = 0; j < opt.VFIc.outerSize(); j++)
{
elements.push_back(T(offset+j,offset+j,opt.fvi[j]));
for(SpMat::InnerIterator it(opt.VFIc,j); it; ++it)
{
int index = 3*it.row();
for(int n = 0; n < size; n++)
{
elements.push_back(T(offset+j,index+n,N(j,n)));
}
}
}
}
这是一个代码示例,可以很好地与这些指令配合使用(并且因此速度更快)
Eigen::MatrixXd Optimizer::OptimizeLLGeneral()
{
ConstraintsManager manager;
SurfaceConstraint surface(1,true);
PlanarizationConstraint planarization(1,true,3^Nv,Nf);
manager.addConstraint(&surface);
manager.addConstraint(&planarization);
double mu = mu0;
for(int k = 0; k < iterations; k++)
{
#pragma omp parallel for schedule (static)
for(int j = 0; j < VFIc.outerSize(); j++)
{
manager.calcVariableMatrix(*this,j);
}
#pragma omp parallel for schedule (static)
for(int i = 0; i < FVIc.outerSize(); i++)
{
Eigen::MatrixXd A = Eigen::Matrix<double, 3, 3>::Zero();
Eigen::MatrixXd b = Eigen::Matrix<double, 1, 3>::Zero();
manager.addLocalMatrixComponent(*this,i,A,b,mu);
Eigen::VectorXd temp = b.transpose();
Q.row(i) = A.colPivHouseholderQr().solve(temp);
}
mu = r*mu;
}
return Q;
}
我的问题是什么使一个函数与omp指令配合得如此好,又使另一个函数崩溃?使omp指令的行为不同有什么区别?
在使用openmp之前,您将一些数据elements
一一推回向量中。但是,对于openmp,将有多个线程在for循环中并行运行代码。当有多个线程同时将数据推回向量elements
时,并且没有代码确保一个线程在另一线程完成之前不会开始推入时,就会发生问题。这就是代码崩溃的原因。
要解决此问题,您可以使用局部增益向量。每个线程首先将数据推送到其私有本地缓冲区向量,然后可以将这些缓冲区向量连接在一起成为单个向量。
您会注意到,此方法不能保持向量中数据元素的原始顺序elements
。如果要这样做,可以计算数据元素的每个预期索引,然后将数据直接分配到正确的位置。
OpenMP提供了API,可让您知道使用了多少线程以及正在使用哪个线程。请参阅omp_get_max_threads()
和omp_get_thread_num()
了解更多信息。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句