為什么SSE標量sqrt(x)比rsqrt(x)* x慢?我一直在Intel Core Duo上進行一些核心數學分析,在查看各種平方根方法時,我注意到了一些奇怪的事情:使用SSE標量運算,倒數平方根乘以它會更快獲取sqrt,而不是使用本機sqrt操作碼!我正在用類似這樣的循環對其進行測試: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() );}我已經為TestSqrtFunction使用了幾種不同的主體進行了嘗試,并且確實有一些時機讓我很頭疼。到目前為止,最糟糕的是使用本機sqrt()函數并讓“智能”編譯器“優化”。在24ns / float的情況下,使用x87 FPU確實很糟糕:inline float TestSqrtFunction( float in ){ return sqrt(in); }我嘗試的下一件事是使用內部函數強制編譯器使用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。我也試過卡馬克的古怪牛頓迭代逼近技術,這甚至比硬件跑,在4.3ns /浮動,雖然以1比2的錯誤10(這是太多了,我的目的)。當我嘗試SSE op求倒數平方根,然后使用乘積獲得平方根(x * 1 /√x=√x)時,doozy出現了。即使需要兩次相關操作,它還是迄今為止最快的解決方案,速度為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的內置于硬件的平方根操作碼比從其他兩個數學運算中合成出來的速度慢?我確信這確實是操作本身的成本,因為我已經驗證:所有數據都適合緩存,并且訪問是順序的內聯函數展開循環沒有區別編譯器標志設置為完全優化(并且匯編很好,我檢查過)(編輯:stephentyrone正確地指出,長數字串上的運算應使用矢量化SIMD打包操作,例如rsqrtps-但此處的數組數據結構僅用于測試目的:我真正要衡量的是標量性能,以用于代碼中無法向量化。)
4 回答

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

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