在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