展開循環的好處如下:
由於展開能夠消除分支以及一些管理歸納變數的程式碼,因此可以攤銷一些分支開銷。
展開可以積極排程(或管道化)循環以掩蓋一些延遲。如果有足夠的空閑暫存器使變數保持活動狀態,因為通過展開相關性鏈展露了關鍵路徑,這將非常有用。
如果迭代次數是可預測的,並且循環中沒有條件分支,則英特爾(R) 奔騰(R) 4 處理器可以正確預測迭代次數為 16 次或更少的內部循環的退出分支。因此,如果循環體不是太大,並且已知可探測的迭代次數,則可以展開內部循環,直到它們的迭代次數達到最大值 16。對於奔騰 III 或奔騰 II 處理器,請不要展開迭代次數大於 4 的循環。
展開循環的可能開銷如下:
展開過度或展開非常大的循環時,可能導致程式碼篇幅增加。如果展開后的循環不能再放入跟蹤快取 (TC),這將有害無益。
展開循環體中包含分支的循環時,會增加對 BTB 容量的需求。如果展開后循環的迭代次數是 16 或更少,則分支預測應該能正確預測循環體中改變方向的分支。
彙編/編譯器編碼規則 12。(影響度 H,通用性 M)
通常情況下,將小循環一直展開到分支與歸納變數的開銷小於循環執行時間的約 10%。
彙編/編譯器編碼規則 13。(影響度 H,通用性 M)
避免過度展開循環,否則可能會導致 TC 反覆。
彙編/編譯器編碼規則 14。(影響度 M,通用性 M)將頻繁執行的循環與迭代次數可以預測的循環展開,使迭代次數降到 16 或更少,除非這會增加程式碼篇幅使得工作集不能再放入跟蹤快取。如果循環體包含一個以上的條件分支,則通過展開使迭代次數等於 16/(條件分支數)。
以下循環展開示例顯示在進行展開的同時如何使其它優化方法成為可能:
展開之前:
do i=1,100
if (i mod 2 == 0) then a(i) = x
else a(i) = y
enddo
展開之後
do i=1,100,2
a(i) = y
a(i+1) = x
enddo
在本例中,執行 100 次的循環將 x 賦給偶數編號的每個元素,將 y 賦給每個奇數編號的元素。通過展開循環,可以在每個迭代中同時執行兩個賦值,從而消除循環體中的一個分支。