代码之家  ›  专栏  ›  技术社区  ›  Brett

需要对我的SSE/Assembly尝试提出一些建设性的批评吗

  •  6
  • Brett  · 技术社区  · 16 年前

    我正在将一些代码转换为SSE,虽然我有正确的输出,但结果证明它比标准c++代码慢。

    我需要这样做的代码是:

    float ox = p2x - (px * c - py * s)*m;
    float oy = p2y - (px * s - py * c)*m;
    

    我得到的SSE代码是:

    void assemblycalc(vector4 &p, vector4 &sc, float &m, vector4 &xy)
    {
        vector4 r;
        __m128 scale = _mm_set1_ps(m);
    
    __asm
    {
        mov     eax,    p       //Load into CPU reg
        mov     ebx,    sc
        movups  xmm0,   [eax]   //move vectors to SSE regs
        movups  xmm1,   [ebx]
    
        mulps   xmm0,   xmm1    //Multiply the Elements
    
        movaps  xmm2,   xmm0    //make a copy of the array  
        shufps  xmm2,   xmm0,  0x1B //shuffle the array     
    
        subps   xmm0,   xmm2    //subtract the elements
    
        mulps   xmm0,   scale   //multiply the vector by the scale
    
        mov     ecx,    xy      //load the variable into cpu reg
        movups  xmm3,   [ecx]   //move the vector to the SSE regs
    
        subps   xmm3,   xmm0    //subtract xmm3 - xmm0
    
        movups  [r],    xmm3    //Save the retun vector, and use elements 0 and 3
        }
    }
    

    由于很难阅读代码,我将解释我所做的:

    加载向量4,xmm0\p=[px,py,px,py]
    穆特。通过向量4,xmm1 cs=[c,c,s,s]
    __________________________骡子----------------------------
    结果,xmm0=[px c、 py公司 [秒]

    c、 py公司 s、 py公司 [秒]
    洗牌结果,xmm2=[py s、 像素 s、 py公司
    _____________________减法----------------------------
    结果,xmm0=[px c-py公司 s、 py公司 碳对二甲苯 s、 像素 c、 py公司 [英]

    重用结果,xmm0=[px c-py公司 碳对二甲苯 s、 像素 s-py公司 c、 py公司 s-px公司 [英]
    加载m矢量4,比例=[m,m,m,m]

    结果,xmm0=[(px c-py公司 秒) c-px*s型) m、 (像素) m、 (年) s-px*c型) [米]


    加载xy矢量4,xmm3=[p2x,p2x,p2y,p2y]
    c-py*s型) m、 (年) c-px*s型) s-py*c) s-px*c型) [米]
    _____________________减法----------------------------
    结果,xmm3=[p2x-(px
    c-py*s型) m、 p2x-(py) c-px*s型) m、 p2y-(像素) s-py*c) s-px*c)*米]

    然后ox=xmm3[0]和oy=xmm3[3],所以我基本上不使用xmm3[1]或xmm3[4]

    很抱歉阅读本文有困难,但我希望有人能为我提供一些指导,因为标准c++代码的运行时间为0.001444ms,SSE代码的运行时间为0.00198ms。

    让我知道如果有什么我可以做进一步解释/清理这一点。我之所以尝试使用SSE是因为我运行这个计算数百万次,而这是减慢我当前代码速度的一部分。

    提前感谢您的帮助! 布雷特

    1 回复  |  直到 15 年前
        1
  •  9
  •   Stephen Canon    16 年前

    ox oy ,你计算四个 公牛 同时输入值。这样可以最大限度地减少浪费的计算和无序处理。

    x , y , p2x p2y 值转换为连续数组(即,您可能有一个包含四个值的数组 y

    movups  %xmm0,  [x]
    movups  %xmm1,  [y]
    movaps  %xmm2,  %xmm0
    mulps   %xmm0,  [c]    // cx
    movaps  %xmm3,  %xmm1
    mulps   %xmm1,  [s]    // sy
    mulps   %xmm2,  [s]    // sx
    mulps   %xmm3,  [c]    // cy
    subps   %xmm0,  %xmm1  // cx - sy
    subps   %xmm2,  %xmm3  // sx - cy
    mulps   %xmm0,  scale  // (cx - sy)*m
    mulps   %xmm2,  scale  // (sx - cy)*m
    movaps  %xmm1,  [p2x]
    movaps  %xmm3,  [p2y]
    subps   %xmm1,  %xmm0  // p2x - (cx - sy)*m
    subps   %xmm3,  %xmm2  // p2y - (sx - cy)*m
    movups  [ox],   %xmm1
    movups  [oy],   %xmm3
    

    使用此方法,我们在18条指令中同时计算4个结果,而使用您的方法在13条指令中计算单个结果。我们也没有浪费任何成果。

    还有待改进;由于要使用这种方法,必须重新排列数据结构,因此应该对齐数组,并使用对齐的加载和存储,而不是未对齐的加载和存储。您应该将c和s加载到寄存器中,并使用它们来处理 许多的 x和y的向量,而不是为每个向量重新加载它们。为了获得最佳性能,应该将两个或多个计算向量交错,以确保处理器有足够的工作来执行任务,从而防止管道暂停。

    cx + sy 而不是 cx - sy

    你在什么硬件上做计时的评论几乎把一切都弄清楚了:“奔腾4HT,2.79GHz”。这是一个非常古老的微体系结构,在这个微体系结构上,不对齐的移动和洗牌相当慢;在流水线中没有足够的工作来隐藏算术运算的延迟,而且重新排序引擎也没有在较新的微体系结构上那么聪明。

    我希望你的向量码 证明它比i7上的标量代码快,也可能比Core2上的标量代码快。另一方面,如果可以的话,一次做四个会更快。

    推荐文章