2013-02-08 203 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位索引,这可能会减慢速度,甚至导致查找的矢量化速度增加。