在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
有兩個問題。首先,你需要2個間接指導來達到你的價值。第二個是,你會跳過一個64k大陣列,這將垃圾你左右緩存。出於測試目的,您可以將* src中的值限制爲8位值,我想你會看到速度的急劇增加。霓虹燈可能會有幫助,因爲IIRC它有直接通向二級緩存的路徑,通常這個路徑大於256k,應該能夠容納整個陣列。您應該發佈當前生成的程序集。 – 2013-02-08 16:30:55
裝配看起來沒問題(在這種情況下)。 Loopunrolling可能會有所幫助,但這取決於輸入數據的長度。如果你可以保證總是len%4 == 0或len%8 == 0,那麼你幾乎可以隱藏所有的負載延遲。但仍然,你的lut不適合l1緩存。 – 2013-02-08 17:55:31