三维向量运算SSE/SSE2优化

减小字体 增大字体作者:chaos  来源:本站整理  发布时间:2009-12-04 15:49:00
    r = _mm_add_ss( r , _mm_shuffle_ps( r , r , 1 ) );
    return r;
}

通过这两个例子,可以留意到向量内元素的垂直相加一般形式,即:
/* x[0] + x[1] + x[2] + x[3] */
__m128 _mm_sum_ps( __m128 x ) {
    __m128 r;
    r = _mm_add_ps( x , _mm_movehl_ps( x , x ) );
    r = _mm_add_ss( r , _mm_shuffle_ps( r , r , 1 ) );
    return r;
}

那么通过扩展,可以得到求向量长度的函数,首先是求分量平方和函数:
/* x[0] * x[0] + y[0] * y[0] + z[0] * z[0] */
__m128 _mm_square_ps( __m128 x ) {
    __m128 s , r;
    s = _mm_mul_ps( x , x );
    r = _mm_add_ss( s , _mm_movehl_ps( s , s ) );
    r = _mm_add_ss( r , _mm_shuffle_ps( r , r , 1 ) );
    return r;
}
然后就可以直接把结果求平方根,可得长度。解决了长度,接下来则是很重要的单位化了。可以说单位化是最重要的一个函数,它经常被调用到,而函数内的陷阱却又最多。求单位化其实并不难,就是分量除以向量长度,可以写成:
void normalize( const Vector& a ) {
    float len = a[0] * a[0] + a[1] * a[1] + a[2] * a[2];
    if( is_zero( len ) )
        return;
    len = 1 / len;
    a[0] *= len;
    a[1] *= len;
    a[2] *= len;
}

我和这个家伙打交道已经有差不多七年时间了,所以脾性非常熟悉。首先求分量的平方和,判断是否为0(问我为什么不直接用 if( len == 0 )?好样的,请先去复习一下浮点数的基本知识),然后再求倒数,最后反映到分量上。在把它写成SSE intrinsic格式前,我先引入另外一个能极大提升运算效率的函数,求平方根的倒数。有数值运算编成经验的人都知道,如果说除法是恶魔的话,那么平方根就是撒旦了,而平方根的倒数简直就是撒旦他妈。虽然上面提供了倒数的逼近方法,但仅仅使用它还是绕不开最主要的开销、平方根运算。幸好,SSE提供了一个直接计算平方根倒数近似值的指令,rsqrtss/rsqrtps(即_mm_rsqrt_ss和_mm_rsqrt_ps)。照搬倒数求法,可以轻松得出:

/* r = 1 / sqrt(a) */
/* 0.5 * rsqrtss * (3 - x * rsqrtss(x) * rsqrtss(x)) */
__m128 _mm_rsqrt( __m128 a )
{
    // divisor
    static const __m128 _05 = _mm_set1_ps( 0.5f );
    static const __m128 _3 = _mm_set1_ps( 3.f );
    __m128 rsqrt = _mm_rsqrt_ss( a );

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

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

用户名:   验证码:

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

内 容:

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

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