在iOS 6项目中,我有一个包含两个字节字(16位)的缓冲区,需要通过查找表将其转换为四个字节字(32位)。我将值硬编码到表中,然后使用两个字节缓冲区的值来确定要检索的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位字输出。有任何想法吗?或许有更好的方法来解决这个问题吗?
来自clang的当前asm输出(clang -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
答案 0 :(得分:3)
查找表(几乎)不可向量。可以使用vtbl
指令处理非常小的查找表,但是您的查找表太大了。
你在使用查找表做什么?如果可以在没有太多工作的情况下动态计算这些值而不是查找它们,那对您来说实际上可能是一个重要的胜利。
答案 1 :(得分:1)
我的第一个想法是,你可能会在Accelerate框架的vecLib部分中从vtablelookup
获得一些运气。签名是:
vUInt32 vtablelookup (
vSInt32 Index_Vect,
uint32_t *Table
);
其中vSInt32
和vUInt32
分别是128位打包的32位有符号/无符号整数。我相信这个功能是由ARM上的NEON支持的。最大的问题是将你的src
数组转换为32位索引,这可能会减慢速度,从而使查找的矢量化速度有所提升。