C ++函数的以下片段最初是作为串行代码编写的。 为了将外循环与计数器'jC'并行化,我只添加了行“#pragma omp parallel for private(jC)”。尽管这种天真的方法对我有很多次帮助,但我怀疑是否足以并行化jC循环,因为相对于原始代码,执行时间似乎没有变化。 有没有人建议确保以下代码有效地转换为(正确的)并行代码?
如果我的问题没有得到很好的解答(这是我在这个论坛的第一篇文章),请提前致谢并道歉。
代码段是:
#include "omp.h"
void addRHS_csource_to_pcellroutine_par(
double *srcCoeff, double *srcVal, int nPc,
double *adata, double *bdata, int elsize
)
{ int elamax = elsize*elsize;
int jC;
#pragma omp parallel for private(jC)
for (int jC=0; jC<nPc; jC++) {
for (int el=0; el<elamax; el++) {
adata[el + jC*elamax] = adata[el + jC*elamax] - srcCoeff[el + jC*elamax];
}
for (int el=0; el<elsize; el++) {
bdata[el + jC*elsize] = bdata[el + jC*elsize] + srcVal[el + jC*elsize];
}
}
}
附加说明:一种(可能不是最优雅的?)解决方法,包括将代码更改为
void addRHS_csource_to_pcellroutine_parFunction(int jC, int elamax,
double *srcCoeff, double *srcVal, int nPc,
double *adata, double *bdata, int elsize
)
{
for (int el=0; el<elamax; el++) {
adata[el + jC*elamax] -= srcCoeff[el + jC*elamax];
}
for (int el=0; el<elsize; el++) {
bdata[el + jC*elsize] += srcVal[el + jC*elsize];
}
}
void addRHS_csource_to_pcellroutine_par(
double *srcCoeff, double *srcVal, int nPc,
double *adata, double *bdata, int elsize
)
{ int elamax = elsize*elsize;
#pragma omp parallel for
for (int jC=0; jC<nPc; jC++) {
addRHS_csource_to_pcellroutine_parFunction(jC, elamax, srcCoeff, srcVal, nPc, adata, bdata, elsize);
}
}
答案 0 :(得分:1)
正如您可以阅读specifcation(第55页) 你的内部循环没有并行化。只有外面的是。
int jC;
#pragma omp parallel for private(jC)
for (int jC=0;......
您已经定义了两个名为jC的变量。你打算做的是正确的,但你应该决定一个解决方案:
int jC;
#pragma omp parallel for private(jC)
for(jC = 0;....
或
#pragma omp parallel for
for(int jC = 0;....
至于:
我怀疑是否足以并行化jC循环, 因为执行时间似乎 相对于原始代码不变。
充足性取决于您必须执行的迭代次数(由nPc给出)以及您提供的线程数(合理地在四核8线程上)。 您甚至可以获得较慢的并行化循环。这是因为创建新线程的开销非常高(+其他一些额外的东西,如管理线程)。
因此,您需要通过并行化循环来获得比创建线程所需的更多时间。
希望这能回答你的问题。
如果您仍然使用更快的程序,您可以考虑使用并行化内部循环的算法(例如,通过拆分迭代空间并使用openmp reduction构造)