2010-06-20 33 views
0

我正在學習循環展開,以避免依賴造成的停頓。我在互聯網和文獻中發現了很多例子,但是我沒有找到關於如何使用算法獲得優化代碼的解釋(當然有一種這樣的算法的情況)。特別是,我不知道如何確定循環展開多少次。可以事先計算嗎?循環應展開多少次?

回答

1

經驗法則是,你放鬆,使:

  • 操作都在「自然」 boundries 4,8,16,32 ..做字節
  • 你不引入過多的寄存器壓力(即你不開始雜耍寄存器內存)
  • 你不重新開始重複完全相同的指令序列,並在

基本上你解開只要你可以把更多的資源來工作的當你不再能衡量任何表現收益時,你停下來。

1

你在編寫一個編譯器嗎?否則,你真的不應該循環展開自己。你應該很可能相信編譯器爲你做適當的循環展開,它發現它適用。

+1

不*嚴格*真實 - 有些情況下,手動循環展開可以產生比編譯器更好的結果 - 但是,一般來說,最好讓編譯器執行它。對於一些較新的微架構,最好讓硬件進行循環展開。 – 2010-06-20 20:41:13

+0

這是一個有效的觀點,我同意。 – aioobe 2010-06-20 20:43:15

+0

我不是自己解開它。我正在爲微控制器編寫一些C代碼,並在檢查編譯器輸出的機器代碼的同時,發現這些循環已經展開。我只是想知道它是如何工作的。我不打算手工做。 – 2010-06-20 20:50:12

0

我想補充我的答覆,因爲雖然TorbjörnGyllebring的回答是不錯的,它是不完整的IMO

有因展開不同的改進:

算法改進 - 例如你的instruciton集允許處理四個而不是單個字節。 Torbjörn完美地回答了這個問題。

減少循環開銷當循環體小,循環的開銷(典型地,增量+ +比較跳)消耗的時間量顯著。

total cost = N * (loop body + loop overhead) 

與展開一次,你

total cost = N/2 * (2 * loop body + loop overhead) 
      = N * loop body + N/2 * loop overhead 

如果與循環體循環的開銷很小,展開會給你增加代碼大小的成本毫無斬獲。示例:當循環體循環開銷爲10倍時,展開最多可以讓您提高5%。

更好的配對 - 對於具有多個管道(或準配對,如寄存器重命名和微碼生成)的架構,展開可能會給出更好的配對機會。同樣,只有當循環體很小時纔會顯着,但是公式不能像上面那樣容易。

展開並非無害 - 請記住,即使在「好」的情況下展開也幾乎使循環的代碼大小加倍。這可能會清除緩存中的其他代碼或數據。在現代桌面體系結構中,代碼大小問題已經足夠嚴格,所以經驗法則是全局優化代碼大小,並且僅爲本地熱點優化速度。

1

有時它甚至對而不是展開循環(對於Core2和更高處理器),因爲它們有一個「循環流檢測器」(他們稱之爲LSD)。 只需在「英特爾優化指南」中查看即可。

如果代碼適合在非常小的隊列中,那麼處理器不需要從L1指令緩存中取出/解碼指令,這可以提供一些性能。

+0

+1。最近我遇到了這個問題,當我的軟件流水線循環是原始「愚蠢」(但非常小)的代碼速度的一半! – 2010-07-15 01:42:16