2015-07-21 54 views
2

在某個庫(FFTW:離散傅立葉變換計算)中,我遇到了一個頭文件,其中包含以下注釋和一些#define。評論談到了一些編程技巧。 但我無法理解這個編程技巧究竟是什麼。 有人能解釋一下嗎?關於開源軟件中使用的某種編程技巧的查詢

/* hackery to prevent the compiler from ``optimizing'' induction 
    variables in codelet loops. The problem is that for each K and for 
    each expression of the form P[I + STRIDE * K] in a loop, most 
    compilers will try to lift an induction variable PK := &P[I + STRIDE * K]. 
    For large values of K this behavior overflows the 
    register set, which is likely worse than doing the index computation 
    in the first place. 

    If we guess that there are more than 
    ESTIMATED_AVAILABLE_INDEX_REGISTERS such pointers, we deliberately confuse 
    the compiler by setting STRIDE ^= ZERO, where ZERO is a value guaranteed to 
    be 0, but the compiler does not know this. 

    16 registers ought to be enough for anybody, or so the amd64 and ARM ISA's 
    seem to imply. 
*/ 

#define ESTIMATED_AVAILABLE_INDEX_REGISTERS 16 
#define MAKE_VOLATILE_STRIDE(nptr, x)     \ 
    (nptr <= ESTIMATED_AVAILABLE_INDEX_REGISTERS ?  \ 
     0 :            \ 
     ((x) = (x)^X(an_INT_guaranteed_to_be_zero))) 
#endif /* PRECOMPUTE_ARRAY_INDICES */ 

回答

1

優化:代替在每一個循環迭代發生時間重新計算所述陣列的索引的,一些編譯器預期的下一個地址,並把這些在寄存器因爲索引表達是可預測的。

問題:某些索引表達式(如I + STRIDE * K)可能會導致以這種方式使用大量寄存器,並且如果此數目超過寄存器總數,某些寄存器值將被推送到堆棧內存,包括其他變量該循環可能正在使用。

訣竅:爲了強制編譯器不使用此優化,將使用外部整數。添加或異或這個零並將其存儲在x中是一個無效操作,它會「跨出」步伐,從而導致索引表達式,從而通過優化分析使其不可預知。即使我們知道它的行爲非常像零,它不能再推斷這個變量的行爲。文件ifftw.h的相關提取物作爲此導出:

extern const INT X(an_INT_guaranteed_to_be_zero); 

#ifdef PRECOMPUTE_ARRAY_INDICES 
... 
#define MAKE_VOLATILE_STRIDE(nptr, x) (x) = (x) + X(an_INT_guaranteed_to_be_zero) 

#else 
... 
#define ESTIMATED_AVAILABLE_INDEX_REGISTERS 16 
#define MAKE_VOLATILE_STRIDE(nptr, x)     \ 
    (nptr <= ESTIMATED_AVAILABLE_INDEX_REGISTERS ?  \ 
     0 :            \ 
     ((x) = (x)^X(an_INT_guaranteed_to_be_zero))) 
#endif /* PRECOMPUTE_ARRAY_INDICES */ 

這種優化任一未遂完全避免,或者允許在該索引可以在可用的寄存器的數量放入一個猜測的條件。它允許優化的方式是使用一個常數零。

一些詞源:宏MAKE_VOLATILE_STRIDE從volatile關鍵字派生它的名稱,它指示值可能會在不同的訪問之間改變,即使它看起來沒有被修改。此關鍵字可防止優化編譯器優化掉後續讀取或寫入,從而錯誤地重新使用舊值或省略寫入。 (Wikipedia

爲什麼揮發性關鍵字,而不是XOR'ing外部值,是不夠的,我不知道。