函数的 OpenMP 优化

Posted

技术标签:

【中文标题】函数的 OpenMP 优化【英文标题】:OpenMP optimization for a function 【发布时间】:2012-11-23 05:37:44 【问题描述】:

我们的任务是使用 openmp 来优化结构不佳的程序。我是编程新手,所以我希望任何人都可以了解如何优化此功能(我需要优化的众多功能之一):

void
entry_type3(F2D *sData, F2D *ones, F2D *quat, F2D **pos, F2D **vel)

    //Observation

   F2D *t;

   t = fSetArray(1, 3, 0);
    asubsref(t,2) = -9.8;


    F2D *accl = fDeepCopyRange(sData, 0, 1, 0, 3);
    F2D *gtemp = fMtimes( ones, t);
    F2D *gravity = quatRot(gtemp, quat);



    fFreeHandle(gtemp);
    fFreeHandle(t);

   t = fSetArray(3,3,0);
    asubsref(t,0) = 1;
    asubsref(t,4) = 1;
    asubsref(t,8) = 1;

    int n = ones->height;
    int i;
    for(i=0; i<(t->height*t->width); i++)
            asubsref(t,i) = asubsref(t,i)/STDDEV_ACCL;

   F2D *w = mcl( gravity, accl, t);

    generateSample(w, quat, *vel, *pos);
    fFreeHandle(t);


    //Motion model
  t = fMtimes(ones, accl);
    fFreeHandle(accl);
    accl = fMinus(t, gravity);
    fFreeHandle(w);
    fFreeHandle(gravity);
    fFreeHandle(t);




    F2D *is;
    #pragma omp parallel sections
    
        #pragma omp section
        
            F2D *is = quatConj(quat);
            F2D *s = quatRot(*vel, is);
            fFreeHandle(is);
            for(i=0; i<(s->height*s->width); i++)
            
                 asubsref(s,i) = asubsref(s,i)*acclTimeInterval;
            
            is = fPlus(*pos, s);
            fFreeHandle(*pos);
            *pos = fDeepCopy(is);
            fFreeHandle(is);
            fFreeHandle(s);
         


        /** pos_ above stores: pos+quatRot(vel,quatConj(quat))*acclTimeInterval **/

        #pragma omp section
        
            F2D *is = quatConj(quat);
            F2D *s = quatRot(accl, is);
            F2D* t = fDeepCopy(s);

            for(i=0; i<(s->height*s->width); i++)
            
                asubsref(t,i) = 1/2*asubsref(s,i)*acclTimeInterval*acclTimeInterval;
            

            /** t_ above stores: 1/2*quatRot(accl,quatCong(quat))*acclTimeInterval^2 **/

            fFreeHandle(s);
            fFreeHandle(is);


 s = randnWrapper(n,3);

            for(i=0; i<(s->height*s->width); i++)
            
                asubsref(s,i) = asubsref(s,i) * M_STDDEV_POS;
            

            /** s_ above stores: randn(n,3)*M_STDDEV_POS **/

       is = fPlus(*pos, t);
           fFreeHandle(*pos);
         *pos = fPlus(is, s);

            fFreeHandle(s);
            fFreeHandle(t);
            fFreeHandle(is);
     

        
        //vel=vel+accl*acclTimeInterval+randn(n,3)*M_STDDEV_VEL;
#pragma omp parallel sections

#pragma omp section

 F2D *t = fDeepCopy(accl);
#pragma omp parallel for
    for(i=0; i<(accl->height*accl->width); i++)
    
            asubsref(t,i) = asubsref(accl,i) * acclTimeInterval;
    

    is = fPlus(*vel, t);
    fFreeHandle(accl);
    fFreeHandle(t);

#pragma omp section


 F2D *s = randnWrapper(n,3);
#pragma omp parallel for
    for(i=0; i<(s->height*s->width); i++)
    
            asubsref(s,i) = asubsref(s,i) * M_STDDEV_VEL;
    

    fFreeHandle(*vel);
    *vel = fPlus(is, s);
    fFreeHandle(is);
    fFreeHandle(s);



我已经在其中添加了一些 openmp 并行,但它仍然运行得很慢,所以我希望各位经验丰富的老手能指出我应该关注哪些地方来提高性能。

【问题讨论】:

您正在使用 OpenMP 部分。您真的确定,这两个部分(每个 section 构造内)中的代码可以彼此独立执行,即它们之间没有数据依赖关系吗?执行速度非常慢通常是线程之间(错误)共享的标志。 【参考方案1】:

现在,看起来只是在仓促中困住了一些 pragmas,而不关心代码的并行性。现在,您并没有真正将工作分配给您的处理器,您实际上是通过让每个内核做同样的事情来重复工作(并且可能会在此过程中产生一些严重的错误答案)。很高兴看到原版,看看你改变了什么。您实际上需要以编程方式拆分任务(即,如果您正在处理图像,则需要告诉处理器 1 处理奇数像素,处理器 2 处理偶数像素,OpenMP 不够聪明,无法解决这个问题)。很抱歉,如果这看起来没有那么有用,但是说这是一个任务,我认为你可能需要自己计算出一定的数量 - 但重要的部分是 OpenMP 不能只是让代码并行,你需要告诉它如何。查看 omp_get_num_threads() 和 omp_get_thread_num()。

【讨论】:

谢谢你,这实际上很有帮助,我也在想同样的事情(关于我只是为了它而放入编译指示)问题是我无法看到哪些部分可以并行运行由于变量看起来都是相互关联的,应该一个接一个地执行,我主要希望有一些关于如何成功拆分代码的提示 所以,我可能不会给予应有的公正,但请看这里:for(i=0; i&lt;(s-&gt;height*s-&gt;width); i++)asubsref(s,i) = asubsref(s,i) * M_STDDEV_POS;。看起来这一位并不完全依赖于序列(尽管有一些处理方法——我只是没有资格谈论它们),所以假设我做了它而不是int k=numProcessors; int MaxI=s-&gt;height*s-&gt;width;int procNum=processorNumber;for(int i=procNum;i&lt;MaxI;i+=k)asubsref(s,i) = asubsref(s,i) * M_STDDEV_POS;。这将分散工作 - 我希望你明白为什么。【参考方案2】:

开头的这段代码: for(i=0; i<(t->height*t->width); i++) asubsref(t,i) = asubsref(t,i)/STDDEV_ACCL; 可以有效地并行化。每个i 的计算都是完全独立的。

寻找这些独立的代码部分。当然,您应该考虑要并行化什么。

【讨论】:

以上是关于函数的 OpenMP 优化的主要内容,如果未能解决你的问题,请参考以下文章

在针对顺序运行进行优化的程序上使用 openMP 后没有性能提升

在更好的优化标志和OpenMP之后,向量的计算变得更慢。

MIC性能优化

Mac 上的 G++ 链接时优化 - 编译器/链接器错误?

openmp应用和原理

如何优化并行嵌套循环?