首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >循环展开对内存绑定数据的影响

循环展开对内存绑定数据的影响
EN

Stack Overflow用户
提问于 2012-06-13 09:36:06
回答 1查看 814关注 0票数 1

我一直在使用一段内存密集型的代码。我试图通过手动实现缓存阻塞、软件预取、循环展开等方式在单个内核中优化它,尽管缓存阻塞可以显著提高性能。然而,当我引入循环展开时,我得到了巨大的性能降级。

我在所有测试用例中都使用带有编译器标志-O2和-ipo的英特尔icc进行编译。

我的代码类似于此(3D 25点模板):

代码语言:javascript
复制
    void stencil_baseline (double *V, double *U, int dx, int dy, int dz, double c0, double c1,     double c2, double c3, double c4)
   {
   int i, j, k;

   for (k = 4; k < dz-4; k++) 
   {
    for (j = 4; j < dy-4; j++) 
    {
        //x-direction
            for (i = 4; i < dx-4; i++) 
        {
            U[k*dy*dx+j*dx+i] =  (c0 * (V[k*dy*dx+j*dx+i]) //center
                +  c1 * (V[k*dy*dx+j*dx+(i-1)] + V[k*dy*dx+j*dx+(i+1)])                 
                +  c2 * (V[k*dy*dx+j*dx+(i-2)] + V[k*dy*dx+j*dx+(i+2)])     
                +  c3 * (V[k*dy*dx+j*dx+(i-3)] + V[k*dy*dx+j*dx+(i+3)]) 
                +  c4 * (V[k*dy*dx+j*dx+(i-4)] + V[k*dy*dx+j*dx+(i+4)]));

        }

        //y-direction   
        for (i = 4; i < dx-4; i++) 
        {
            U[k*dy*dx+j*dx+i] += (c1 * (V[k*dy*dx+(j-1)*dx+i] + V[k*dy*dx+(j+1)*dx+i])
                + c2 * (V[k*dy*dx+(j-2)*dx+i] + V[k*dy*dx+(j+2)*dx+i])
                + c3 * (V[k*dy*dx+(j-3)*dx+i] + V[k*dy*dx+(j+3)*dx+i]) 
                + c4 * (V[k*dy*dx+(j-4)*dx+i] + V[k*dy*dx+(j+4)*dx+i]));
        }

        //z-direction
        for (i = 4; i < dx-4; i++) 
        {
            U[k*dy*dx+j*dx+i] += (c1 * (V[(k-1)*dy*dx+j*dx+i] + V[(k+1)*dy*dx+j*dx+i])
                + c2 * (V[(k-2)*dy*dx+j*dx+i] + V[(k+2)*dy*dx+j*dx+i])
                + c3 * (V[(k-3)*dy*dx+j*dx+i] + V[(k+3)*dy*dx+j*dx+i]) 
                + c4 * (V[(k-4)*dy*dx+j*dx+i] + V[(k+4)*dy*dx+j*dx+i]));

        }

    }
   }

 }

当我在最里面的循环(维度i)上执行循环展开,并分别以展开因子2、4、8在x,y,z方向上展开时,我得到了所有9种情况下的性能下降,即在x方向上展开2,在y方向上展开2,在z方向上展开2,在x方向上展开4 ...但是当我在最外面的循环(维度k)上执行8倍(2和4也是)的循环展开时,我得到了v.good性能的改进,甚至比缓存阻塞还要好。

我甚至尝试过使用Intel Vtune分析我的代码。这似乎是瓶颈,主要是由于1.LLC未命中和2.LLC加载未命中由远程DRAM提供服务。

我不能理解为什么展开最内部最快的循环会导致性能下降,而展开最外层、最慢的维度却会带来性能提升。然而,在后一种情况下,这种改进是在使用icc编译时使用-O2和-ipo的时候。

我不确定如何解释这些统计数据。有没有人能帮我解释一下。

EN

回答 1

Stack Overflow用户

发布于 2012-12-17 01:54:18

这强烈地表明您正在通过展开导致指令缓存未命中,这是典型的现象。在现代硬件时代,展开不再自动意味着更快的代码。如果每个内部循环都适合一个缓存线,那么您将获得更好的性能。

您可以手动展开,以限制生成的代码的大小,但这将需要检查生成的机器语言指令及其位置,以确保您的循环位于单个缓存线内。高速缓存线通常为64字节长,并在64字节边界上对齐。

外部循环不具有相同的效果。无论展开级别如何,它们都可能在指令高速缓存之外。展开这些结果会产生更少的分支,这就是为什么您会获得更好的性能。

“由远程DRAM服务的加载未命中”意味着您在一个NUMA节点上分配了内存,但现在您正在另一个节点上运行。基于NUMA设置进程或线程亲和性就是答案。

在我使用的Intel机器上,远程DRAM的读取时间几乎是本地DRAM的两倍。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11007134

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档