我正在使用C ++创建一个有限元分析例程,并且我尝试使用Open MP来并行化一些' for'在我的代码中循环。
我有一个名为Elements的结构数组,数组的每个部分都包含一个结构,其中包含该特定元素的所有信息。所需的一些信息是每个元素的刚度矩阵(在下面的代码中称为kt)。然后将其组装成整个系统的整体刚度矩阵。
元素刚度矩阵的计算非常复杂且冗长,所以我认为通过并行计算可以获得一些好的速度增益。
下面的代码在与Open MP相关的所有内容都被注释掉时工作正常,但是当它不是因为我不是同时写入Elements并且kt和Elementsi(第i个元素)是私有他们正在使用的线程。
我使用Armadillo作为矩阵代数,这就是' mat'装置
我对C ++很陌生,所以任何帮助都会非常感激。
mat KtCalc(struct Element Elements[],mat Nodes,double ngamma,double nbeta,double hhtalpha, int nel, double dt)
//Stiffness matrix calculation routine
{
int nn=Nodes.n_rows;
mat Kt(nn*6, nn*6, fill::zeros);
int i;
struct Element Elementi;
mat kt;
#pragma omp parallel private(Elementi,kt) shared(nel,i,hhtalpha,ngamma,nbeta,dt,Elements)
{
#pragma omp for
for(i=0;i<nel;i++)
{
#pragma omp critical(dataupdate)
{
Elementi=Elements[i];
}
kt=KtEl(Elementi, ngamma, nbeta, hhtalpha, dt);
#pragma omp critical(dataupdate)
{
Elements[i].kt=kt;
}
}
}
for(int k=0;k<nel;k++){
//Use the stuff calculated above in a non parallel way to calculate Kt
}
return Kt;
}
答案 0 :(得分:1)
你的问题是forloop i
的共同减速。在cpp中,您可以在任何地方声明变量。以下代码是等效的,应该可以工作:
mat KtCalc(struct Element Elements[],mat Nodes,double ngamma,double nbeta,double hhtalpha, int nel, double dt)
//Stiffness matrix calculation routine
{
int nn=Nodes.n_rows;
mat Kt(nn*6, nn*6, fill::zeros);
#pragma omp parallel for
for(int i=0;i<nel;i++)
{
Elements[i].kt=KtEl(Elements[i], ngamma, nbeta, hhtalpha, dt);
}
for(int k=0;k<nel;k++){
//Use the stuff calculated above in a non parallel way to calculate Kt
}
return Kt;
}
此外,您可以同时修改数组的元素,只要您确定永远不会修改相同的元素(这是因为您只触及i
th元素)。因此不需要critical
部分。
另一方面,您通常希望尽可能晚地声明您的变量。将它们声明为旧c风格。尽可能晚地宣布它们means: