1

以下は、openMP によって並列化されたコードの一部です。配列、ap[]およびsc[]、は加算代入に課せられているため、それらを共有してから、句が配列を受け入れないため、それらをcritical句セクションに入れることにしました。reductionしかし、それはそのシリアル版とは異なる結果をもたらします。問題はどこだ?

Vector PN, Pf, Nf; // Vector is user-defined structure
Vector NNp, PPp;
Vector gradFu, gradFv, gradFw;
float dynVis_eff, SGSf; 
float Xf_U, Xf_H;
float mf_P, mf_N;
float an_diff, an_conv_P, an_conv_N, an_trans;  
float sc_cd, sc_pres, sc_trans, sc_SGS, sc_conv_P, sc_conv_N;   
float ap_trans;

#pragma omp parallel for
for (int e=0; e<nElm; ++e)
{
    ap[e] = 0.f;
    sc[e] = 0.f;
}

#pragma omp parallel for shared(ap,sc)
for (int f=0; f<nFaces; ++f)
{
    PN = cntE[face_N[f]] - cntE[face_P[f]];
    Pf = cntF[f] - cntE[face_P[f]];
    Nf = cntF[f] - cntE[face_N[f]];
    PPp = Pf - (Pf|norm(PN))*norm(PN);
    NNp = Nf - (Nf|norm(PN))*norm(PN);

    mf_P = mf[f];
    mf_N = -mf[f];

    SGSf = (1.f-ifac[f]) * SGSvis[face_P[f]]
         +      ifac[f]  * SGSvis[face_N[f]];

    dynVis_eff = dynVis + SGSf;

    an_diff = dynVis_eff * Ad[f] / mag(PN);

    an_conv_P = -neg(mf_P);
    an_conv_N = -neg(mf_N);

    an_P[f] = an_diff + an_conv_P;
    an_N[f] = an_diff + an_conv_N;

    // cross-diffusion
    sc_cd = an_diff * ( (gradVel[face_N[f]]|NNp) - (gradVel[face_P[f]]|PPp) );

    #pragma omp critical
    {       
        ap[face_P[f]] += an_N[f];   
        ap[face_N[f]] += an_P[f];

        sc[face_P[f]] += sc_cd + sc_conv_P;
        sc[face_N[f]] += -sc_cd + sc_conv_N;
    }
4

1 に答える 1

3

parallel 句の他のすべての変数を共有するかどうかを宣言していません。defaultこれは、句を使用して一般的に行うことができます。デフォルトが指定されていない場合、変数はすべて共有されるため、コードで問題が発生します。

あなたの場合、私はあなたが行くべきだと思います

#pragma omp parallel for default(none), shared(ap,sc,face_N,face_P,cntF,cntE,mf,ifac,Ad,an_P,an_N,SGSvis,dynVis), private(PN,Pf,Nf,PPp,NNp,mf_P,mf_N,SGSf,dynVis_eff,an_diff,an_conv_P,an_conv_N,sc_cd)

default(none)変数を明示的に宣言せず、変数について明示的に考えるように強制するたびにコンパイラが文句を言うように、常に使用することを強くお勧めします。

于 2012-06-19T21:05:06.000 に答える