如何将openMP的外循环与串行内循环并行化以添加数组

How to parallellize an outer loop with openMP with serial inner loop for array addition

本文关键字:循环 并行化 数组 添加 openMP      更新时间:2023-10-16

以下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);
    }
}

如您所见(第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线程上合理)。您甚至可以获得较慢的并行化循环。这是因为创建新线程的开销非常高(加上一些其他额外的东西,比如破坏线程)。

因此,您必须通过并行化循环获得比创建线程所需更多的时间。

希望这能回答你的问题。

如果你仍然需要一个更快的Programm,你可以考虑一种算法来并行内部循环(例如,通过分割迭代空间和使用openmp约简结构)