4

我正試圖優化嵌入式系統(FLAC解碼,Windows CE,ARM 926 MCU)中的一些代碼。具有固有功能的前導零計算

default implementation使用宏和查找表:

/* counts the # of zero MSBs in a word */ 
#define COUNT_ZERO_MSBS(word) (\ 
(word) <= 0xffff ? \ 
    ((word) <= 0xff? byte_to_unary_table[word] + 24 : \ 
       byte_to_unary_table[(word) >> 8] + 16) : \ 
    ((word) <= 0xffffff? byte_to_unary_table[word >> 16] + 8 : \ 
       byte_to_unary_table[(word) >> 24]) \ 
) 

static const unsigned char byte_to_unary_table[] = { 
    8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 
    3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
}; 

然而,大多數的CPU已經有專門的指令,bsr在x86和clz在ARM(http://www.devmaster.net/articles/fixed-point-optimizations/),這應該是更有效的。

在Windows CE上,我們有固有功能_CountLeadingZeros,應該調用該值。然而,它比宏觀慢了4倍(以1000萬次迭代測量)。

(應該)依賴專用的ASM指令的內部函數有可能如此慢4倍?

回答

5

檢查拆卸。你確定編譯器插入了指令嗎?在備註一節有這樣的文字:

此功能可以通過 調用運行時函數來實現。

我懷疑這就是你的情況。

請注意,CLZ指令僅在ARMv5及更高版本中可用。你需要告訴編譯器,如果你想的ARMv5代碼:

/QRarch5 ARM5 Architecture 
/QRarch5T ARM5T Architecture 

(微軟錯誤地使用,而不是「的ARMv5」「ARM5」)

+0

我會檢查生成的代碼。如果它真的是一個函數調用(而不是真正的內部函數),調用開銷將解釋爲什麼它如此緩慢。 – Wizard79 2010-10-28 19:02:44