NEON 加速 12 位到 8 位

Posted

技术标签:

【中文标题】NEON 加速 12 位到 8 位【英文标题】:NEON acceleration for 12-bit to 8-bit 【发布时间】:2013-09-10 14:25:54 【问题描述】:

我有一个 12 位数据的缓冲区(存储在 16 位数据中) 并且需要转换成8位(移位4)

NEON 如何加速这一处理?

感谢您的帮助

卜拉欣

【问题讨论】:

这有点棘手,但可以做到——到目前为止你尝试过什么? 【参考方案1】:

冒昧地假设了下面解释的一些事情,但是与天真的非 NEON 版本相比,这种代码(未经测试,可能需要一些修改)应该提供良好的加速:

#include <arm_neon.h>
#include <stdint.h>

void convert(const restrict *uint16_t input, // the buffer to convert
             restrict *uint8_t output,       // the buffer in which to store result
             int sz)                        // their (common) size

  /* Assuming the buffer size is a multiple of 8 */
  for (int i = 0; i < sz; i += 8) 
    // Load a vector of 8 16-bit values:
    uint16x8_t v = vld1q_u16(buf+i);
    // Shift it by 4 to the right, narrowing it to 8 bit values.
    uint8x8_t shifted = vshrn_n_u16(v, 4);
    // Store it in output buffer
    vst1_u8(output+i, shifted);
  


我在这里假设的事情:

您正在使用无符号值。如果不是这样的话,无论如何也很容易适应(uint* -> int*, *_u8->*_s8 and *_u16->*_s16) 由于这些值是 8 x 8 加载的,我假设缓冲区长度是 8 的倍数以避免边缘情况。如果不是这种情况,您可能应该人为地将其填充为 8 的倍数。

最后,NEON 文档中使用的 2 个资源页面:

大约loads and stores 个向量。 关于shifting vectors。

希望这会有所帮助!

【讨论】:

您不需要设置 q 标志,除非您还设置了 r 标志。这里没有什么可以饱和的。 没错,NEON 文档中的复制粘贴很糟糕!修好了。 谢谢。我会做一些测试。我正在尝试将此类代码包含到 Qt 4.8 应用程序中,并且需要删除“const 限制”。 buf+i 更改为 input+i。数据从 12 位无符号转换为 16 位,现在转换为 8 位无符号。【参考方案2】:
prototype : void dataConvert(void * pDst, void * pSrc, unsigned int count);
    1:
    vld1.16 q8-q9, [r1]!
    vld1.16 q10-q11, [r1]!
    vqrshrn.u16 d16, q8, #4
    vqrshrn.u16 d17, q9, #4
    vqrshrn.u16 d18, q10, #4
    vqrshrn.u16 d19, q11, #4
    vst1.16 q8-q9, [r0]!
    subs r2, #32
    bgt 1b

q 标志:饱和度

r 标志:四舍五入

在签名数据的情况下将 u16 更改为 s16。

【讨论】:

以上是关于NEON 加速 12 位到 8 位的主要内容,如果未能解决你的问题,请参考以下文章

使用 NEON 指令加速级联双二阶 - 它是如何工作的?

linux kernel态下使用NEON对算法进行加速

linuxARM板子开启浮点和neon加速

这些opencv函数是由ARM NEON加速的吗? [关闭]

VNNI 指令的 NEON 仿真

神经网络AI加速器技术