2014-05-23 72 views
9

由於函數fsin用於計算x86下的sin(x)函數可以追溯到奔騰時代,顯然它甚至不使用SSE寄存器,所以我想知道是否有更新,更好的計算三角函數的指令集。Intel asm更快但更不準確的fsin?

我習慣於在C++中編寫代碼並進行一些asm優化,因此任何適合從C++到C到asm的管道都適合我。

謝謝。


我在Linux下64位,現在,隨着gccclang(甚至強硬鐺並沒有真正提供任何FPU相關的優化據我所知)。

編輯

  • 我已經實現了一個sin功能,它通常2倍於std::sin甚至與sse上。
  • 我的功能是永遠慢然後fsin,甚至強硬fsin通常更爲精準,但考慮到fsin從未勝過我的sin實現,我會繼續我的sin現在,也是我的sin是完全可移植,其中fsin是僅適用於x86 。
  • 我需要這個實時計算,所以我會交易精度的速度,我認爲我會罰款4-5小數的精度。
  • 不能使用基於表的方法,我沒有使用它,它將高速緩存關閉,使得一切都變得更慢,沒有基於內存訪問或查找表的算法。
+1

這可能證明有用:[「使用Intel的SSE2指令的快速三角函數」](http://users.ece.utexas.edu/~adnan/comm/fast-trigonometric-functions-using.pdf) –

+0

@AlexReinking謝謝,但該文件看起來像幾個選項的概述,加上我認爲不會有用的半頁代碼,至少在我的情況下。 – user2485710

+1

你能更具體地說明你爲什麼認爲SSE2不會幫助你的情況嗎? –

回答

5

如果您能夠接受的近似值(我假設你是,如果你想擊敗硬件),你應該看看尼克的sin實現在DevMaster:

http://devmaster.net/posts/9648/fast-and-accurate-sine-cosine

他有兩個版本:「快速&馬虎」的方法和「慢速&準確」的方法。一對夫婦回覆某人估計相對誤差分別爲12%和0.2%。我自己做了一個實現,並在我的機器上查找1/14和1/8硬件時間的運行時間。

希望有幫助!

PS:如果你這樣做你自己,你可以重構慢/精確的方法,以避免乘法和在尼克的版本略有提高,但我不記得到底如何......

+0

這是一個很長的閱讀,我正在閱讀它,但現在我想我需要一些時間來處理和相關的選項。但看起來這些人或多或少都是遊戲開發人員,他們對此很滿意。 – user2485710

+1

「你可以重構緩慢/準確的方法,以避免乘法和稍微改進Nick的版本」當霍納形式是一個多項式評估方案的改進時,應該避免大膽地聲稱所謂的「快速和準確」實現。這篇博文的標題應該是「快速和不準確的正弦」,因爲這是兩個版本。 –

+0

@PascalCuoq所有的近似值在定義上都不太準確,再加上在計算世界中,我不知道事情可能會有什麼不同。 – user2485710

11

如果您需要超過-π...π,使用絕對精度優化正弦值的近似值:

X *(1 + X * X *(-0.1661251158026961831813227851437597220432 + X * X *(8.03943560729777481878247432892823524338e-3 + X * X * -1 。

float xx = x * x; 
float s = x + (x * xx) * (-0.16612511580269618f + xx * (8.0394356072977748e-3f + xx * -1.49414020045938777495e-4f)); 

也許optimized depending on the characteristics of your target architecture:4941402004593877749503989396238510717e-4))

它可以實現。另外,在鏈接的博客文章中沒有提到,如果您正在使用匯編實現這一點,請使用FMADD指令。如果使用C或C++實現,如果使用的是例如fmaf() C99標準函數,請確保生成FMADD。仿真版本比乘法和加法要昂貴得多,因爲fmaf()所做的並不完全等同於乘法和加法(因此僅實現它是不正確的)。

罪之間的差異(x)和在-π到π圖之間的上述多項式這樣:

graphpipi

的多項式優化降低它和sin之間的差(X)之間-π和π,不只是有人認爲是一個好主意的東西。

如果您只需要[-1 ... 1]定義間隔,則可以通過忽略其餘部分使多項式在該間隔內更加準確。該定義間隔再次運行the optimization algorithm生產:

X *(1 + X * X *(-1.666659904470566774477504230733785739156e-1 + X * X *(8.329797530524482484880881032235130379746e-3 + X * X *( - 1.928379009208489415662312713847811393721e-4) ))

的絕對誤差圖:

graph11

如果這是你太準確,有可能optimize a polynomial of lower degree for the same objective那麼絕對誤差會大一些,但你能救一個或兩個倍增。

+0

我不能按照你的推理,你選擇什麼算法來導出第一個和其他公式?請記住,我需要爲所有其他功能執行此操作,所以我需要一個算法。 – user2485710

+2

@ user2485710那麼,你的問題是關於罪,所以我回答了關於罪。無論如何,使用的方法是Remez算法,它提供的內容在我的答案已經提供的鏈接中非常清楚地解釋:http://lolengine.net/blog/2011/12/21/better-function-approximations。它的工作原理沒有必要理解使用它(我不)。 –

+1

@ user2485710 **需要理解的是多項式近似的原理(否則你最終試圖用一個形式爲aX^2 + bX的多項式逼近sin,並且你必須在每個地方調用abs()是荒謬的,正如Xavier Holt的答案中的「Nick's version」一樣)。您還需要有關浮點的基本事實,以便知道將X的係數固定爲1是有益的。我使用了LolRemez,可以從我已經提供的鏈接中獲得,但是使用它的過程很複雜,因爲以上所有內容都是 –