三维向量运算SSE/SSE2优化

减小字体 增大字体作者:chaos  来源:本站整理  发布时间:2009-12-04 15:49:00

然后我们把注意力放到一条非常特殊的指令shufps(对应intrinsic是_mm_shuffle_ps)上面。这是一条非常有用的指令,它可以把两个操作数的分量以特定的顺序排列并赋予给目标数。比如
__m128 b = _mm_shuffle_ps( a , a , 0 );
则 b 的所有分量都是 a 中下标为0的分量。第三个参数控制分量分配,是一个8bit的常量,这个常量的1~8位分别控制了从两个操作数中选择分量的情况,具体怎么控制将在后面讨论SSE汇编中一并说明,而在使用intrinsic的时候,最好使用_MM_SHUFFLE宏,它可以定义分配情况。下面我们来复习一下叉积的求法。
c = a x b
可以写成:
Vector cross(const Vector& a , const Vector& b ) {
    return Vector(
        ( a[1] * b[2] - a[2] * b[1] ) ,
        ( a[2] * b[0] - a[0] * b[2] ) ,
        ( a[0] * b[1] - a[1] * b[0] ) );
}

那么写成SSE intrinsic形式则是:
/* cross */
__m128 _mm_cross_ps( __m128 a , __m128 b ) {
    __m128 ea , eb;
    // set to a[1][2][0][3] , b[2][0][1][3]
    ea = _mm_shuffle_ps( a , a , _MM_SHUFFLE( 3 , 0 , 2 , 1 ) );
    eb = _mm_shuffle_ps( b , b , _MM_SHUFFLE( 3 , 1 , 0 , 2 ) );
    // multiply
    __m128 xa = _mm_mul_ps( ea , eb );
    // set to a[2][0][1][3] , b[1][2][0][3]
    a = _mm_shuffle_ps( a , a , _MM_SHUFFLE( 3 , 1 , 0 , 2 ) );
    b = _mm_shuffle_ps( b , b , _MM_SHUFFLE( 3 , 0 , 2 , 1 ) );
    // multiply
    __m128 xb = _mm_mul_ps( a , b );
    // subtract
    return _mm_sub_ps( xa , xb );
}
这就是shuffle强大的地方,它可以直接在寄存器里直接调整分量的顺序。而且配合_mm_movehl_ps,我们可以轻松解决点积的运算。_mm_movehl_ps把操作数高位两个分量赋予目标数的低位两分量,而目标数的高位两分量值不变,相当于:
a[0] = b[2];
a[1] = b[3];

三分量的向量求点积,可以写成:
float dot( const float& a , const float& b ) const {
    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}

则用SSE intrinsic可以写成:
/* x[0] * x[1] + y[0] * y[1] + z[0] * z[1] */
__m128 _mm_dot_ps( __m128 x , __m128 y ) {
    __m128 s , r;
    s = _mm_mul_ps( x , y );
    r = _mm_add_ss( s , _mm_movehl_ps( s , s ) );

上一页  [1] [2] [3] [4] [5] [6]  下一页

  • 好的评价 如果您觉得此文章好,就请您
      100%(2)
  • 差的评价 如果您觉得此文章差,就请您
      0%(0)
   评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论

用户名:   验证码:

分 值:100分 85分 70分 55分 40分 25分 10分 1分

内 容:

      若文章有错误,请将右边打钩通知管理员

关于本站 - 友情连接 - 网站地图 - 我要留言