« 行列の転置 | メイン | 平方根の逆数の高精度化 »

2008年02月23日

x86 SIMD Technique:: 逆数の高精度化

    

割り算は遅いので、逆数の掛け算で処理したいのだが、逆数を求める _mm_rcp_ps は 11bit 精度しかなくて、普通の用途には使い辛い ( 11bit 精度だと、10 進数で3桁程度しかない ) 。
でも、割り算は遅い。
と言うことで、11bit 精度で得られた逆数の近似値をニュートン-ラフソン法 ( Newton-Raphson ) を用いて高精度化する。
SSE のソースコードは以下。
精度は 22bit 程度。_mm_div_ps は 23bit 精度なので、あまり変わらない。
とりあえず、よくわからなくても以下のコードコピペして使えばうまく行く。

// 22bit 精度で逆数を求める
// aの逆数 = 2 * a - rcpa * a * a を用いる
inline __m128 m128_rcp_22bit_ps( const __m128& a ) {
  __m128 xm0 = a;
  __m128 xm1 = _mm_rcp_ps(xm0);
  xm0 = _mm_mul_ps( _mm_mul_ps( xm0, xm1 ), xm1 );
  xm1 = _mm_add_ps( xm1, xm1 );
  return _mm_sub_ps( xm1, xm0 );
}
inline __m128 m128_rcp_22bit_ss( const __m128& a ) {
  __m128 xm0 = a;
  __m128 xm1 = _mm_rcp_ss(xm0);
  xm0 = _mm_mul_ss( _mm_mul_ss( xm0, xm1 ), xm1 );
  xm1 = _mm_add_ss( xm1, xm1 );
  return _mm_sub_ss( xm1, xm0 );
}
inline float rcp_sse( float a ) {
  float  ret;
  __m128 xm0 = _mm_set_ss(a);
  _mm_store_ss( &ret, m128_rcp_22bit_ss(xm0) );
  return ret;
}

これで割り算の多い日も安心。



投稿者 Takenori : 2008年02月23日 20:57




comments powered by Disqus
Total : Today : Yesterday : なかのひと