2017-07-06 12 views
0

私はOpenMPを使ってforループを、C++のメインから呼び出される関数の中で並列化したいと思っています。OpenMPスロープライベート関数

私のコードは、シーケンシャルモードよりもはるかに遅くなります。forループは、OpenMPなしで約6.1秒(壁時計)(#pragma ...コマンドをコメントアウトするだけ)、OpenMPで11.8秒です。

私のマシンには8個のCPUと8183Mbの物理ストレージがあり、64ビットのWindows 7オペレーティングシステムが搭載されています。私は、デバッグモードで64xビットシステム用のビジュアルスタジオコンパイラを使用します。

私は、パフォーマンスの低下はプライベートとして宣言する必要がある変数が原因である可能性がありますが、これを正しく行う方法は不明であり、どの変数をプライベートとして宣言する必要があるのか​​読んでいます。

これは、forループ関連している:

vec DecenterOffsetParallel(const real_1d_array &x22, vec vDistance, double dOffsetXp, double dOffsetYp, double dOffsetXm, double dOffsetYm, double dOffsetXpY, double dOffsetYpX, double dOffsetXmY, double dOffsetYmX, double* dDeltaXp, double* dDeltaYp, double* dDeltaXm, double* dDeltaYm, double* dDeltaXpY, double* dDeltaYpX, double* dDeltaXmY, double* dDeltaYmX, double* delta0, /*local variables for the parallel code: */ const int nRaysn, double PupilDian, mat mRxNn, mat mRyNn, mat mRzNn, mat mRxN1n, mat mRyN1n, mat mRzN1n, mat mRxN2n, mat mRyN2n, mat mRzN2n, mat mRxN3n, mat mRyN3n, mat mRzN3n, mat mRcxNn, mat mRcyNn, mat mRczNn, mat mRcxN1n, mat mRcyN1n, mat mRczN1n, mat mRcxN2n, mat mRcyN2n, mat mRczN2n, mat mRcxN3n, mat mRcyN3n, mat mRczN3n, mat mPathNn, mat mPath1Nn, mat mPath00Nn, mat mPathN1n, mat mPath1N1n, mat mPath00N1n, mat mPathN2n, mat mPath1N2n, mat mPath00N2n, mat mPathN3n, mat mPath1N3n, mat mPath00N3n) 
{ 
#pragma omp parallel for 
for (int xy = 0; xy < nRaysn * nRaysn; xy++){ 
    mat temp = mat(nRaysn, nRaysn); 
    mat mScxn(nRaysn, nRaysn); 
    mat mScyn(nRaysn, nRaysn); 
    mat mSczn(nRaysn, nRaysn); 

    int i = xy/nRaysn; 
    int j = xy % nRaysn; 
    // only rays inside entrance pupil:t 
    if (sqrt(((10.0/nRaysn) * i - 5.0)*((10.0/nRaysn) * i - 5.0) + ((10.0/nRaysn)*j - 5.0) *((10.0/nRaysn)*j - 5.0)) <= PupilDian/2.0){ 
     // Initialize the matrices 
     mRxNn(i, j) = (10.0/nRaysn) * i - 5.0; 
     mRyNn(i, j) = (10.0/nRaysn) * j - 5.0; 
     mRzNn(i, j) = 0.0; 
     //... everything is repeated 3 more times to simulate all in all 4 cases...: mRxNn1(i,j) = (10.0/nRaysn)*i-5.0; and so on... 


     mRcxNn(i, j) = sign(vDistance(0)) *(mRxNn(i, j) - dOffsetYmX)/(sqrt(vDistance(0)*vDistance(0) + (mRxNn(i, j) - dOffsetYmX) * (mRxNn(i, j) - dOffsetYmX) + (mRyNn(i, j) - dOffsetYm) *(mRyNn(i, j) - dOffsetYm))); 
     mRcyNn(i, j) = sign(vDistance(0)) *(mRyNn(i, j) - dOffsetYm)/(sqrt(vDistance(0)*vDistance(0) + (mRxNn(i, j) - dOffsetYmX) * (mRxNn(i, j) - dOffsetYmX) + (mRyNn(i, j) - dOffsetYm) *(mRyNn(i, j) - dOffsetYm))); 
     mRczNn(i, j) = sqrt(1 - mRcxNn(i, j)*mRcxNn(i, j) - mRcyNn(i, j)*mRcyNn(i, j)); 
     mPathNn(i, j) = 0.0; 
     mPath1Nn(i, j) = sign(vDistance(0)) *nAir * vDistance(0)/mRczNn(i, j); 
     mPath00Nn(i, j) = mPath1Nn(i, j); 
     //... everything is repeated 3 more times to simulate 4 different cases... 

     //trace rays through cornea 
     temp(i, j) = RayIntersect(ZernAnt, ZernRadAnt, &mRxNn(i, j), &mRyNn(i, j), P2DAnt, UAnt, VAnt, &mRzNn(i, j), mRcxNn(i, j), mRcyNn(i, j), mRczNn(i, j), &mPathNn(i, j), xNullAnt, yNullAnt, NknotsUAnt, NknotsVAnt); // find the intersection (modifies mRz, mRy, mRx, mPath) 
     mPathNn(i, j) = mPath1Nn(i, j) + nAir*mPathNn(i, j); 
     temp(i, j) = Surface(P2DAnt, UAnt, VAnt, ZernAnt, ZernRadAnt, mRxNn(i, j), mRyNn(i, j), mRzNn(i, j), &mScxn(i, j), &mScyn(i, j), &mSczn(i, j), KnotIntervallSizeAnt, xNullAnt, yNullAnt); 
     // *Ant are identical for all four cases! 
     temp(i, j) = Refract(nAir, nCornea, &mRcxNn(i, j), &mRcyNn(i, j), &mRczNn(i, j), mScxn(i, j), mScyn(i, j), mSczn(i, j)); 
     //... everything is repeated 3 more times to simulate all in all 4 cases... 
    } 
    else{ 
     mRxNn(i, j) = mRyNn(i, j) = mRzNn(i, j) = mRcxNn(i, j) = mRcyNn(i, j) = mRczNn(i, j) = mPathNn(i, j) = mPath1Nn(i, j) = NAN; 
     //... everything is repeated 3 more times to simulate all in all 4 cases... 
    } 
} 
// some other stuff, that is not relevant to the questions... 

}

誰もがパフォーマンスの低下を引き起こす可能性があるものを、私にヒントを与えることはできますか? ありがとうございました!

PS:マトリクスおよびベクターには、アルマジロライブラリーが使用されています。

+0

'public'や' private'はその点で何も変わりません。 –

+1

ようこそ。残念ながら、あなたはあなたの質問に正しく答えるのに十分な情報を提供していません。 [mcve]を含めて、システム構成(CPU、メモリ、コンパイラ)を記述し、どのように測定するか、特定の測定結果を記述してください。 – Zulan

+0

私はシステム情報を追加し、簡単な例を私のプログラムの(やや短縮した)元のコードに置き換えました。お役に立てれば! – Sims

答えて

0

すべての変数が(nSDiaなど)を読み取り専用または共有する必要がある(mXmYなど)のどちらかであるので、あなたは、並列構造のいずれかのプライベート変数を宣言する必要はありません。

パフォーマンスの低下についての質問は、@ Zulanがコメントで説明したように、より多くの情報を提供する必要があります。ここで非常に便利な指標は、関数が呼び出された回数とアプリケーションの合計時間のうちのどの部分が(実際にホットスポットであるかを確認するために)どれだけの時間がかかるかです。アプリケーション実行時間と蓄積された関数時間を持つことは素晴らしいことです。

gprof's call graphのような多くのツールでこれを行うことができますが、OpenMPなしで実行できます。

+0

nRays * nRays = 10000個の計算は互いに完全に独立しています。他の部分に基づいて、私はfor-loopのウォールクロック時間の点で少なくとも50%の利益を期待します。シーケンシャルでは、コードの部分が私の合計実行時間の約20〜30%を占めています。 – Sims