2013-02-08 204 views
1

在iOS 6項目中,我有一個包含兩個字節字(16位)的緩衝區,需要通過查找錶轉換爲四個字節字(32位)。我將這些值硬編碼到表中,然後使用兩個字節緩衝區的值來確定要檢索哪個32位表值。這裏有一個例子:如何使用NEON在ARM彙編中實現16位 - > 32位查找表?

void map_values(uint32_t *dst,uint16_t *src,uint32_t *lut,int buf_length){ 
    int i=0; 
    for(i=0;i<buf_length;i++){ 

     *dst = *(lut+(*src)); 
     dst++; 
     src++; 
    } 
} 

問題是,它太慢了。可以通過使用NEON一次處理4個輸出字節來加速嗎?問題是,我很擔心如何從src緩衝區獲取值,並將其用作查找表的輸入,以確定要檢索的值。此外,表格和輸出緩衝區中的字長也是相同的,但不是來源。所以,我只能讀取兩個16位字作爲輸入,而不是我需要的四個32位字輸出。有任何想法嗎?也許有更好的方法來解決這個問題嗎?從鐺

電流輸出的asm(鐺-O3 -arch的ARMv7 lut.c -S):

.section __TEXT,__text,regular,pure_instructions 
    .section __TEXT,__textcoal_nt,coalesced,pure_instructions 
    .section __TEXT,__const_coal,coalesced 
    .section __TEXT,__picsymbolstub4,symbol_stubs,none,16 
    .section __TEXT,__StaticInit,regular,pure_instructions 
    .syntax unified 
    .section __TEXT,__text,regular,pure_instructions 
    .globl _map_values 
    .align 2 
    .code 16      @ @map_values 
    .thumb_func _map_values 
_map_values: 
@ BB#0: 
    cmp r3, #0 
    it eq 
    bxeq lr 
LBB0_1:         @ %.lr.ph 
             @ =>This Inner Loop Header: Depth=1 
    ldrh r9, [r1], #2 
    subs r3, #1 
    ldr.w r9, [r2, r9, lsl #2] 
    str r9, [r0], #4 
    bne LBB0_1 
@ BB#2:         @ %._crit_edge 
    bx lr 


.subsections_via_symbols 
+1

有兩個問題。首先,你需要2個間接指導來達到你的價值。第二個是,你會跳過一個64k大陣列,這將垃圾你左右緩存。出於測試目的,您可以將* src中的值限制爲8位值,我想你會看到速度的急劇增加。霓虹燈可能會有幫助,因爲IIRC它有直接通向二級緩存的路徑,通常這個路徑大於256k,應該能夠容納整個陣列。您應該發佈當前生成的程序集。 – 2013-02-08 16:30:55

+0

裝配看起來沒問題(在這種情況下)。 Loopunrolling可能會有所幫助,但這取決於輸入數據的長度。如果你可以保證總是len%4 == 0或len%8 == 0,那麼你幾乎可以隱藏所有的負載延遲。但仍然,你的lut不適合l1緩存。 – 2013-02-08 17:55:31

回答

3

查找表(幾乎)不可引導。非常小的查找表可以使用vtbl指令來處理,但查找表太大了。

你在查找表中使用什麼?如果這些數值可以在沒有太多工作的情況下實時計算而不是查看它們,那對您而言可能實際上是一個重大的勝利。

+0

我需要將16位RGB圖像轉換爲32位RGBA。因此,輸入圖像是輸出圖像數據的一半。換句話說,每個RGB輸入16位,而RGBA輸出則爲32位。 – Synthetix 2013-02-08 17:46:06

+0

什麼是16b格式?在Accelerate的vImage子框架中,您可能已經爲您執行了轉換。 – 2013-02-08 18:19:48

+0

RGB565到RGBA8。 – Synthetix 2013-02-08 18:32:50

1

我首先想到的是,你可能會得到一些運氣出vtablelookupAccelerate的vecLib部分框架。簽名是:

vUInt32 vtablelookup (
    vSInt32 Index_Vect, 
    uint32_t *Table 
); 

其中vSInt32vUInt32是128位分別填充32位有符號/無符號整數。我相信這個功能是由ARM上的NEON支持的。最大的問題將是將你的src數組轉換爲32位索引,這可能會減慢速度,甚至導致查找的矢量化速度增加。