如何使用带有串行内循环的openMP并行化外循环以进行数组添加
Posted
技术标签:
【中文标题】如何使用带有串行内循环的openMP并行化外循环以进行数组添加【英文标题】:How to parallellize an outer loop with openMP with serial inner loop for array addition 【发布时间】:2013-11-26 13:38:23 【问题描述】:以下来自 C++ 函数的 sn-p 最初是作为串行代码编写的。 为了使外部循环与计数器'jC' 并行化,我刚刚添加了行 "#pragma omp parallel for private(jC)" 。尽管这种幼稚的方法帮助了我很多次,但我怀疑并行化 jC 循环是否足够,因为相对于原始代码,执行时间似乎没有变化。 有没有人提出一些建议来确保将以下代码有效地转换为(正确的)并行代码?
提前致谢,如果我的问题没有很好地提出,我深表歉意(这是我在这个论坛上的第一篇帖子)。
代码sn-p是:
#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);
【问题讨论】:
你有两个不同的 jC 变量。另外,我认为没有任何理由使用 private(jC)。 确实,在我看来,'#pragma omp parallel for '似乎更合理地使用 '#pragma omp parallel for private(jC)' ... 【参考方案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 构造)
【讨论】:
以上是关于如何使用带有串行内循环的openMP并行化外循环以进行数组添加的主要内容,如果未能解决你的问题,请参考以下文章
带有 break openmp 的并行 If-else 循环
如何使用 OpenMP 通过 C++ std::list 并行化 for 循环?