使用 ARM neon 内部函数进行深度转换

Posted

技术标签:

【中文标题】使用 ARM neon 内部函数进行深度转换【英文标题】:depth transformation with ARM neon intrinsics 【发布时间】:2012-02-26 18:09:45 【问题描述】:

我正在尝试围绕 NEON 内在函数展开思考,并认为我可以从一个示例开始并提出一些问题。

在这个实验中,我想将 32 位 RGB 转换为 16 位 BGR。将以下代码转换为使用 NEON 内在函数是一个好的开始?我在这里遇到的问题是 16 位与我可以看到的任何内在内容都不匹配。有 16x4 16x8 等。但我只是没有运气围绕我需要如何处理这个问题。有什么建议吗?

这是我要转换的代码。

typedef struct 
    uint16_t b:5, g:6, r:5;
 _color16;

static int depth_transform_32_to_16_c (VisVideo *dest, VisVideo *src)

    int x, y;
    int w;
    int h;

    _color16 *dbuf = visual_video_get_pixels (dest);
    uint8_t *sbuf = visual_video_get_pixels (src);

    uint16x8

    int ddiff;
    int sdiff;

    depth_transform_get_smallest (dest, src, &w, &h);

    ddiff = (dest->pitch / dest->bpp) - w;
    sdiff = src->pitch - (w * src->bpp);

    for (y = 0; y < h; y++) 
        for (x = 0; x < w; x++) 
            dbuf->b = *(sbuf++) >> 3;
            dbuf->g = *(sbuf++) >> 2;
            dbuf->r = *(sbuf++) >> 3;

            dbuf++;
            sbuf++;
        

        dbuf += ddiff;
        sbuf += sdiff;
    

    return VISUAL_OK;

编辑:哦,出于某种原因,我正在考虑 16x3 位,但我们正在查看 5,6,5 = 16 位。我意识到我需要轮班。嗯。

【问题讨论】:

【参考方案1】:

NEON 使用 128 位宽的寄存器,因此从概念上讲,您要做的是读取 32 位 RGB 的四个像素,对它们进行按位运算,最终写出 16 位像素。一项观察是,为了获得最佳性能,您可能希望组合两个 128 位输入(8 个 32 位像素)并产生一个 128 输出。这将使您的内存访问更有效率。

另一种思考方式是,您正在获取内部循环内容并并行处理四个像素。使用原始代码有点困难的原因是一些“魔法”被隐藏了,因为您使用的是位域。如果您重写您的 C 代码以从 32 位工作到 16 位并使用移位/和/或该代码将更自然地转换为 SIMD,您可以可视化在该上下文中如何处理多个数据。

如果你只看每个 32 位组件 -> 16 位转换:

00000000RRRRRRRRGGGGGGGGBBBBBBBB
0000000000000000BBBBBGGGGGGRRRRR

这可以帮助您可视化您需要为四个像素并行执行的操作。移位、提取和组合。您可以将其视为 4 个 32 位通道,尽管对于某些位操作而言,寄存器宽度并不重要(例如,或 4 个 32 位寄存器或 8 个 16 位寄存器是相同的)。

粗略的伪代码:

读取(向量加载)128位寄存器=4个32位像素。 移动绿色(所有四个组件)到右位位置。 将绿色(使用 AND 掩码)屏蔽到另一个寄存器中。 (概念上仍处于 4x32 位“模式”) 移动红色(所有四个组件)到右位位置。 将红色掩码到另一个寄存器中。 蓝色移到右位位置。 将蓝色屏蔽到另一个寄存器中。 移动红色和蓝色到右位位置。 使用按位OR进行组合。 现在您将拥有 4 个 16 位值并进行 32 位对齐。 (到目前为止,概念上仍然是 4x32 位) 使用另一组 4 像素重复。 将这两组与 NEON 解压缩 (VUZP) 结合起来,生成一个 128 位/8 像素寄存器。 写入(矢量存储)这些像素。

【讨论】:

以上是关于使用 ARM neon 内部函数进行深度转换的主要内容,如果未能解决你的问题,请参考以下文章

使用 ARM NEON 执行比 C 代码需要更长的时间

将 SSE2 迁移到 Arm NEON 内部函数

使用 arm neon 进行 Rgb 到灰度转换

使用 NEON 内部函数存储非相邻 d 寄存器的最快方法

SAD 16*4 的 Arm-neon 优化版本未提供预期增益

如何使用 ARM NEON 内在函数将 u8 掩码转换为 u32 掩码?