ホーム 道しるべ 憩いの広場 濃緑空間 濃緑研の日記

逆数平方根と平方根
ホーム ] 上へ ] 逆数(除算) ] [ 逆数平方根と平方根 ] 処理時間を測ろう ] 配列の扱い・最適化1 ] 最適化2 ]

 


3DNow!に用意されている平方根用の命令も除算以上に興味深いものがあります。

それは除算の場合と同様、単一命令では低精度(15ビット精度)の逆数平方根を導き出すところです。

24ビットの精度で平方根を求める(a = sqrt(b))シーケンスは

X0 = pfrsqrt(b)
X1 = pfmul(X0,X0)
X2 = pfrsqit1(b,X1)
X3 = pfrcpit2(X2,X0)
a = pfmul(b,X3)

となります。

これはNewton-Raphson逆数平方根繰り返し

Xi+1 = 1/2 * Xi * (3 - b * Xi^2)

を1回行うものだそうです。

逆数の場合と同様、X0はテーブル引きしているそうです(15ビット精度)。

最後のbとの乗算により平方根aが求まりますが、X3が逆数平方根です。

では実際に試してみましょう。

最初はSISD(単一データ)で行います。

#include "amd3d.h"
#include <windows.h>
#include <math.h>
#include <stdio.h>

main()
{
    float    a,b,c;
    char    buf[80];

    b = 3;
    _asm{
        femms
        movd         mm0,b

        pfrsqrt         (m1,m0)             ;mm1     ???        | 1/sqrt(b) 15ビット精度
        movq         mm2,mm1
        pfmul         (m1,m1)
        pfrsqit1    (m1,m0)
        pfrcpit2    (m1,m2)             ;mm1     ???        | 1/sqrt(b)     24ビット精度   
        pfmul         (m0,m1)             ;mm0     ???        | sqrt(b)

        movd         a,mm0
        movd         c,mm1
        femms
    }
    sprintf(buf,"%f %f",a,c);
    MessageBox(GetDesktopWindow(), buf,"Test 3DNow!",MB_OK);
}

aが平方根で1.732051、cがその逆数です。

逆数が先に求まるところに、私としては3Dを感じます。

なにせ重力計算ではまさに逆数平方根が必要ですから(逆に平方根にする必要がないです)。

まあしかし、除算もそうですが、ゲームレベルの計算ではpfsqrtのみの15ビット精度でも十分実用的でしょう。

近いうちに(現在1999/06/13日曜)VisualC++で3DNow!がサポートされるという噂が流れています。
サーキット整備班のvさんは、3Dow!をSIMDでなくSISDで利用するのだろうと推測されています。
3DNow!を24ビット精度のSISD演算器として利用しても、P6コアのFPUを軽く凌ぐ能力を持っていますので、重力計算を15ビット精度で行った場合の物理シミュレーションを行う3Dゲームの映像を見てみたいものです。

しかし、K7の浮動小数点演算能力は考えるだに恐ろしい(3DNow!SISD能力がかすむほどです)が、やはり低い演算精度でも十分実用になる3Dゲームでは3DNow!の能力は侮れないでしょう。

KNI(SSE)の実力も気になるところではありますが、私の身近にはPentium!!!どころか、KNI-SDKすらありません。
amd3d.hと同等のマクロヘッダファイルだけでも十分遊べると思うのですが。

庶民はKNI搭載のCeleron待ちでしょうか(T_T)。