2017-07-06 109 views
0

我想使用OpenMP来并行化一个函数,该函数在C++的main函数中被调用。OpenMP慢速私人功能

我的代码运行速度比顺序模式慢得多:for-loop需要大约6.1s(挂钟)而没有OpenMP(只是注释掉#pragma ...命令),使用OpenMP需要11.8s。

我的机器有8个CPU和8183Mb的物理存储,并配备了64位Windows 7操作系统。我在调试模式下使用Visual Studio编译器来处理64位系统。

我读过性能降低可能是由于应声明为私有变量,但我不确定如何正确执行此操作,以及哪些变量需要声明为私有。

这是相关的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

欢迎来到SO。不幸的是,您没有提供足够的信息来正确回答您的问题。请包括[mcve],描述您的系统配置(CPU,内存,编译器),以及如何测量以及您的具体测量结果。 – Zulan

+0

我添加了系统信息,并用我的程序中的(稍微缩短的)原始代码替换了简化的示例。希望这可以帮助! – Sims

回答

0

你不需要在并行构造声明任何私有变量,因为所有的变量要么只读(nSDia等)或需要共享(mXmY等)。

关于性能下降的问题,你应该提供更多的信息@Zulan在评论中解释。这里一个非常有用的指标是你的函数被调用了多少次,以及它所花费的应用程序总时间中的哪一部分(检查这实际上是一个热点)。具有应用程序执行时间和累积的功能时间会很好。

您可以使用许多工具执行此操作,例如gprof's call graph,但在没有OpenMP的情况下运行。

+0

nRays * nRays = 10 000次完全相互独立的计算。根据其他部分,我预计至少在for-loop的挂钟时间方面将增加50%。在顺序中,代码的一部分占我总执行时间的20-30%。 – Sims