0

我编写了这个非常简单的 NEON 实现来从 RGBA 转换为 RGB。它有效,但我想知道是否还有其他方法可以进一步提高性能。

我尝试使用预取大小并进一步展开循环,但性能并没有太大变化。顺便说一句,在预取维度方面是否有任何经验法则?我在网上找不到任何有用的东西。此外,在“ARMv8 指令集概述”中,我看到还有一个用于存储的预取,这有什么用?

目前我在 iPhone5s 上转换 1280x720 图像需要大约 1.7 毫秒。

// unsigned int * rgba2rgb_neon(unsigned int * pDst, unsigned int * pSrc, unsigned int count);
_rgba2rgb_neon:
    cmp     w2, #0x7
    b.gt    loop

    mov     w0, #0
    ret

loop:
    prfm    pldl1strm, [w1, #64]

    ld4.8b  {v0, v1, v2, v3}, [w1], #32
    ld4.8b  {v4, v5, v6, v7}, [w1], #32

    prfm    pldl1strm, [w1, #64]

    st3.8b  {v0, v1, v2}, [w0], #24
    st3.8b  {v4, v5, v6}, [w0], #24

    subs    w2, w2, #16
    b.gt    loop

done:
    ret
4

2 回答 2

5

首先(因为我假设您的目标是 iOS),vImage(Accelerate.framework 的一部分)为您提供这种转换,如vImageConvert_RGBA8888toRGB888。这具有在所有 iOS 和 OS X 系统上都可用的优势,因此您无需为 arm64、armv7s、armv7、i386、x86_64 编写单独的实现。

现在,可能是您自己编写此转换作为练习,而不是因为您根本不知道该转换已经可用。在这种情况下:

  • 避免使用ld[34]st[34]。它们很方便,但通常比使用ld1和置换慢。
  • 对于像这样完全常规的数据访问模式,不需要手动预取。
  • 用 加载四个 16b RGBA 向量,用三个指令ld1.16b从中提取三个 16b RGB 向量,然后用存储它们tbl.16bst1.16b
  • 或者,尝试使用非临时加载和存储 ( ldnp/ stnp),因为您的图像尺寸太大而无法放入缓存中。

最后,回答您的问题:存储的预取提示主要是有用的,因为某些实现可能对于未命中缓存的部分行写入有很大的停顿。特别是简单的实现可能会对任何未命中缓存的写入产生停顿。

于 2013-12-18T16:31:56.180 回答
2

如果你想用 alpha 通道做一些有趣的事情,除了把它放在你的肩膀上之外,另请参阅 vImageFlatten_RGBA8888toRGB888。

于 2014-01-13T22:59:16.453 回答