28

このドキュメントを読んでいます: http://software.intel.com/en-us/articles/interactive-ray-tracing

そして、次の 3 行のコードに出くわしました。

SIMD バージョンはすでにかなり高速ですが、さらに改善することができます。Intel は、高速な 1/sqrt(x) 関数を SSE2 命令セットに追加しました。唯一の欠点は、その精度が限られていることです。精度が必要なので、Newton-Rhapson を使用して精度を上げます。

 __m128 nr = _mm_rsqrt_ps( x ); 
 __m128 muls = _mm_mul_ps( _mm_mul_ps( x, nr ), nr ); 
 result = _mm_mul_ps( _mm_mul_ps( half, nr ), _mm_sub_ps( three, muls ) ); 

このコードは、'half' (0.5f の 4 倍) という名前の __m128 変数と変数 'three' (3.0f の 4 倍) の存在を前提としています。

Newton Raphson を使用して関数のゼロを計算する方法と、それを使用して数値の平方根を計算する方法は知っていますが、このコードがそれをどのように実行するかはわかりません。

誰か説明してくれませんか?

4

2 に答える 2

35

ニュートン反復法を考えると、y_n + 1 = y_n(3-x(y_n)^ 2)/ 2これをソースコードで確認するのは非常に簡単です。

 __m128 nr   = _mm_rsqrt_ps( x );                  // The initial approximation y_0
 __m128 muls = _mm_mul_ps( _mm_mul_ps( x, nr ), nr ); // muls = x*nr*nr == x(y_n)^2
 result = _mm_mul_ps(
               _mm_sub_ps( three, muls )    // this is 3.0 - mul;
   /*multiplied by */ __mm_mul_ps(half,nr)  // y_0 / 2 or y_0 * 0.5
 );

正確には、このアルゴリズムは逆平方根用です。

これでも完全に正確な結果が得られるわけではないことに注意してください。 rsqrtpsNR反復を使用すると、ほぼ23ビットの精度が得られますsqrtpsが、最後のビットを正しく丸めると、の24ビットが得られます。

結果を整数に切り捨てる場合は、精度の制限が問題になります。 (int)4.99999です4x == 0.0また、を使用する場合は、ケースに注意してsqrt(x) ~= x * sqrt(x)ください0 * +Inf = NaN

于 2013-02-07T13:59:12.493 に答える
3

の逆平方根を計算するために、ニュートン法が導関数を含むa方程式に適用されるため、反復ステップ0=f(x)=a-x^(-2)f'(x)=2*x^(-3)

N(x) = x - f(x)/f'(x) = x - (a*x^3-x)/2 
     = x/2 * (3 - a*x^2)

この除算のない方法は、グローバルに収束するヘロンの方法とは対照的に、収束領域が限られているため、より適切な近似を得るには、逆平方根の適切な近似が必要です。

于 2014-03-12T16:37:48.767 に答える