2013-02-07 63 views
28

我閱讀本文件:http://software.intel.com/en-us/articles/interactive-ray-tracing牛頓拉夫森與SSE2 - 有人可以給我解釋一下這3個行

,我偶然發現了這三行代碼:

的SIMD版本已經相當有點快,但我們可以做得更好。 英特爾爲SSE2指令集添加了快速1/sqrt(x)函數。 唯一的缺點是它的精度有限。我們需要 精度,所以我們完善它用牛頓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)); 

此代碼假定名爲「半壁江山」 (四次0.5F)和可變'一個__m128變量的存在三'(四次3.0f)。

我知道如何使用牛頓拉夫森計算函數的零點,我知道如何使用它來計算一個數的平方根,但我看不出這些代碼如何執行它。

有人可以向我解釋嗎?

回答

34

鑑於牛頓迭代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 
); 

,也可以精確,這種算法是用於the inverse square root

請注意,這still doesn't give fully a fully accurate result。具有NR迭代的rsqrtps給出了近23位的精度,而對於sqrtps的24位具有對最後一位的正確舍入。

如果您想要truncate the result to integer,則精度有限是個問題。 (int)4.999994。另外,如果使用sqrt(x) ~= x * sqrt(x),請注意x == 0.0的情況,因爲0 * +Inf = NaN

+0

當截斷爲整數時,你認爲作爲最後一步添加一個與結果指數相同的值,但只有在有效數中設置的最低位(或兩個?)位是可行的嗎?這當然是在最不重要的數字總是低於該位置的條件下。 – chili

+0

它取決於應用程序。關鍵是,當使用迭代方法'sqrt(n * n)== n'並不總是成立。這不能被任意「固定」 - 因爲'sqrt(n * n - epsilon)== n'可能會導致災難。 –

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) 

此無劃分方法具有 - 在對比的全局收斂Heron's method - 一個有限的收斂區域,所以你需要一個已經很好的逆平方根逼近來獲得更好的近似。