首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >二维模板的SSE本质矢量化

二维模板的SSE本质矢量化
EN

Stack Overflow用户
提问于 2012-06-22 17:36:20
回答 1查看 685关注 0票数 1

我正在尝试矢量化一个2D模板,只使用对齐,加载和存储。为此,我想从本质上使用_mm_load_ps_mm_shuffle_ps来获得所需的地址。

我的标量版本的代码是:

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

            for (j = 4; j < dy-4; j++)
            {
                    for (i = 4; i < dx-4; i++)
                    {

                            U[j*dx+i] = (c0 * (V[j*dx+i]) //center
                                    + c1 * (V[j*dx+(i-1)] + V[(j-1)*dx+i] + V[j*dx+(i+1)] + V[(j+1)*dx+i] )
                                    + c2 * (V[j*dx+(i-2)] + V[(j-2)*dx+i] + V[j*dx+(i+2)] + V[(j+2)*dx+i] )
                                    + c3 * (V[j*dx+(i-3)] + V[(j-3)*dx+i] + V[j*dx+(i+3)] + V[(j+3)*dx+i] )
                                    + c4 * (V[j*dx+(i-4)] + V[(j-4)*dx+i] + V[j*dx+(i+4)] + V[(j+4)*dx+i] ));

                    }
            }

      }

到目前为止,我的向量查看了代码的版本:

代码语言:javascript
复制
     for (j = 4; j < dy-4; j++)
    {
            for (i = 4; i < dx-4; i+=4)
            {
                    __m128 b = _mm_load_ps(&V[j*dx+i]);
                    center = _mm_mul_ps(b,c0_i);
                    a = _mm_load_ps(&V[j*dx+(i-4)]);
                    c = _mm_load_ps(&V[j*dx+(i+4)]);

                    d = _mm_load_ps(&V[(j-4)*dx+i]);
                    e = _mm_load_ps(&V[(j+4)*dx+i]);

                    u_i2 = _mm_shuffle_ps(a,b,_MM_SHUFFLE(1,0,3,2));//i-2
                    u_i6 = _mm_shuffle_ps(b,c,_MM_SHUFFLE(1,0,3,2));//i+2

                    u_i1 = _mm_shuffle_ps(u_i2,b,_MM_SHUFFLE(2,1,2,1));//i-1
                    u_i5 = _mm_shuffle_ps(b,u_i6,_MM_SHUFFLE(2,1,2,1));//i+1

                    u_i3 = _mm_shuffle_ps(a,u_i2,_MM_SHUFFLE(2,1,2,1));//i-3
                    u_i7 = _mm_shuffle_ps(u_i6,c,_MM_SHUFFLE(2,1,2,1));//i+3

                    u_i4 = a; //i-4
                    u_i8 = c; //i+4

有人能帮我获得j-1,j+1 .j-4,j+4的职位吗?

这样做是行不通的:

代码语言:javascript
复制
                    u_j2 = _mm_shuffle_ps(d,b,_MM_SHUFFLE(1,0,3,2));//j-2 (this is incorrect)
                    u_j6 = _mm_shuffle_ps(b,e,_MM_SHUFFLE(1,0,3,2));//j+2

                    u_j1 = _mm_shuffle_ps(u_j2,b,_MM_SHUFFLE(2,1,2,1));//j-1
                    u_j5 = _mm_shuffle_ps(b,u_j6,_MM_SHUFFLE(2,1,2,1));//j+1

                    u_j3 = _mm_shuffle_ps(d,u_j2,_MM_SHUFFLE(2,1,2,1));//j-3
                    u_j7 = _mm_shuffle_ps(u_j6,e,_MM_SHUFFLE(2,1,2,1));//j+3

                    u_j4 = d; //j-4 (this is fine)
                    u_j8 = e; //j+4

我只需要帮助确定如何获得(j-1)*dx+i(j+1)*dx+1 .(j-4)*dx+i(j+4)*dx+i不使用未对齐负载。

作为一种潜在的解决方案,我考虑在存储在d中的地址中添加一个置换d以获得(j-1)*dx+i。并减去3*dx的位移到存储在e中的地址以获得(j+1)*dx+i。类似地,将2*dx添加到d的地址以获得j-2等等。但是我不知道如何使用SSE的本质来实现这个策略。

请帮帮忙。我正在使用Intel icc编译器。

EN

回答 1

Stack Overflow用户

发布于 2013-01-27 07:12:10

“有人能帮我获得j-1,j+1 .j-4,j+4的位置吗?”--这些不需要洗牌,它们已经与你的SIMD车道保持一致了。

代码语言:javascript
复制
u_j2 = _mm_load_ps(&V[(j-2)*dx+i]); 
u_j6 = _mm_load_ps(&V[(j+2)*dx+i]); 
u_j1 = _mm_load_ps(&V[(j-1)*dx+i]); 
u_j5 = _mm_load_ps(&V[(j+1)*dx+i]); 
// and so forth

您绝对不能通过任何可能的重新排列将这些变量标记为de,因为d中的值(例如)是V[j-4, i], V[j-4, i+1], V[j-4, i+2], V[j-4, i+3],并且不能从中提取V[j-2, i]

提示:从SIMD车道的角度来看,这表明您需要水平而不是垂直地重新排列。

提示:考虑当内环计数器增量(i+=4)时会发生什么。上一个循环中的u_i5 (V[j, i+1..i+5])现在是当前循环中的u_i3 (V[j, i-3..i+1])。您正在计算行中数据的每个偏移版本至少两次。您可能可以展开循环几次,避免做所有额外的工作。

提示:为什么不使用AVX?使用_mm256_permute_ps (如果需要的话使用_mm256_permute2f128_ps )来洗牌,并使用相应的加载指令。这将是几乎两倍的速度,因为你有两倍的宽SIMD寄存器和大多数AVX指令仍然只需要一个周期的现代CPU,同样的SSE指令。

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

https://stackoverflow.com/questions/11161355

复制
相关文章

相似问题

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