為什么SSE標量sqrt(x)比rsqrt(x)* x慢?我一直在Intel Core Duo上進行一些核心數(shù)學(xué)分析,在查看各種平方根方法時,我注意到了一些奇怪的事情:使用SSE標量運算,倒數(shù)平方根乘以它會更快獲取sqrt,而不是使用本機sqrt操作碼!我正在用類似這樣的循環(huán)對其進行測試:inline float TestSqrtFunction( float in );void TestFunc(){ #define ARRAYSIZE 4096 #define NUMITERS 16386 float flIn[ ARRAYSIZE ]; // filled with random numbers ( 0 .. 2^22 ) float flOut [ ARRAYSIZE ]; // filled with 0 to force fetch into L1 cache cyclecounter.Start(); for ( int i = 0 ; i < NUMITERS ; ++i ) for ( int j = 0 ; j < ARRAYSIZE ; ++j ) { flOut[j] = TestSqrtFunction( flIn[j] ); // unrolling this loop makes no difference -- I tested it. } cyclecounter.Stop(); printf( "%d loops over %d floats took %.3f milliseconds", NUMITERS, ARRAYSIZE, cyclecounter.Milliseconds() );}我已經(jīng)為TestSqrtFunction使用了幾種不同的主體進行了嘗試,并且確實有一些時機讓我很頭疼。到目前為止,最糟糕的是使用本機sqrt()函數(shù)并讓“智能”編譯器“優(yōu)化”。在24ns / float的情況下,使用x87 FPU確實很糟糕:inline float TestSqrtFunction( float in ){ return sqrt(in); }我嘗試的下一件事是使用內(nèi)部函數(shù)強制編譯器使用SSE的標量sqrt操作碼:inline void SSESqrt( float * restrict pOut, float * restrict pIn ){ _mm_store_ss( pOut, _mm_sqrt_ss( _mm_load_ss( pIn ) ) ); // compiles to movss, sqrtss, movss}效果更好,為11.9ns / float。我也試過卡馬克的古怪牛頓迭代逼近技術(shù),這甚至比硬件跑,在4.3ns /浮動,雖然以1比2的錯誤10(這是太多了,我的目的)。當(dāng)我嘗試SSE op求倒數(shù)平方根,然后使用乘積獲得平方根(x * 1 /√x=√x)時,doozy出現(xiàn)了。即使需要兩次相關(guān)操作,它還是迄今為止最快的解決方案,速度為1.24ns /浮點,精確度為2 -14:inline void SSESqrt_Recip_Times_X( float * restrict pOut, float * restrict pIn ){ __m128 in = _mm_load_ss( pIn ); _mm_store_ss( pOut, _mm_mul_ss( in, _mm_rsqrt_ss( in ) ) ); // compiles to movss, movaps, rsqrtss, mulss, movss}我的問題基本上是什么給?為什么SSE的內(nèi)置于硬件的平方根操作碼比從其他兩個數(shù)學(xué)運算中合成出來的速度慢?我確信這確實是操作本身的成本,因為我已經(jīng)驗證:所有數(shù)據(jù)都適合緩存,并且訪問是順序的內(nèi)聯(lián)函數(shù)展開循環(huán)沒有區(qū)別編譯器標志設(shè)置為完全優(yōu)化(并且匯編很好,我檢查過)(編輯:stephentyrone正確地指出,長數(shù)字串上的運算應(yīng)使用矢量化SIMD打包操作,例如rsqrtps-但此處的數(shù)組數(shù)據(jù)結(jié)構(gòu)僅用于測試目的:我真正要衡量的是標量性能,以用于代碼中無法向量化。)
4 回答

慕標5832272
TA貢獻1966條經(jīng)驗 獲得超4個贊
sqrtss給出正確的舍入結(jié)果。 rsqrtss給出倒數(shù)的近似值,精確到大約11位。
sqrtss當(dāng)需要準確性時,可以產(chǎn)生更準確的結(jié)果。 rsqrtss存在一個近似值但需要速度的情況。如果您閱讀了英特爾的文檔,您還將發(fā)現(xiàn)一條指令序列(平方根的倒數(shù),后跟一個牛頓-拉夫森步長),幾乎可以提供全精度(如果我沒記錯的話,精度約為23位),并且仍然有些比快sqrtss。
編輯:如果速度至關(guān)重要,并且您實際上是在循環(huán)中調(diào)用許多值,則應(yīng)該使用這些指令的向量化版本,rsqrtps或sqrtps,這兩個指令每條處理四個浮點數(shù)。

BIG陽
TA貢獻1859條經(jīng)驗 獲得超6個贊
劃分也是如此。MULSS(a,RCPSS(b))比DIVSS(a,b)快得多。實際上,即使使用牛頓-拉夫森(Newton-Raphson)迭代來提高精度時,它仍然更快。
英特爾和AMD均在其優(yōu)化手冊中推薦了該技術(shù)。在不需要IEEE-754兼容的應(yīng)用程序中,使用div / sqrt的唯一原因是代碼可讀性。
- 4 回答
- 0 關(guān)注
- 1754 瀏覽
添加回答
舉報
0/150
提交
取消