【问题标题】:Load 8bit uint8_t as uint32_t?将 8bit uint8_t 加载为 uint32_t?
【发布时间】:2011-04-10 04:27:32
【问题描述】:

我的图像处理项目使用灰度图像。我有 ARM Cortex-A8 处理器平台。我想使用NEON。

我有一个灰度图像(考虑下面的示例),在我的算法中,我只需要添加列。

如何将 四个 8 位像素值 并行加载,它们是 uint8_t,作为 四个 uint32_t 到 128- 之一位 NEON 寄存器?我必须使用什么内在函数来做到这一点?

我的意思是:

我必须将它们加载为 32 位,因为如果你仔细观察,我执行 255 + 255 的那一刻是 512,它不能保存在 8 位寄存器中。

例如

255 255 255 255 ......... (640 pixels)
255 255 255 255
255 255 255 255
255 255 255 255
.
.
.
.
.
(480 pixels) 

【问题讨论】:

    标签: arm neon intrinsics cortex-a


    【解决方案1】:
    【解决方案2】:

    取决于您的编译器和(可能缺少)扩展。

    即。对于 GCC,这可能是一个起点:http://gcc.gnu.org/onlinedocs/gcc/ARM-NEON-Intrinsics.html

    【讨论】:

      【解决方案3】:

      如果您需要总计 480 个 8 位值,那么从技术上讲,您需要 17 位中间存储。但是,如果您分两个阶段执行加法,即前 240 行,然后是下 240 行,您可以分别以 16 位进行。然后你可以将两半的结果相加得到最终的答案。

      实际上有一条 NEON 指令适用于您的算法,称为 vaddw。它将一个 dword 向量添加到一个 qword 向量,后者包含的元素的宽度是前者的两倍。在您的情况下, vaddw.u8 可用于将 8 个像素添加到 8 个 16 位累加器。然后,可以使用 vaddw.u16 将两组 8 个 16 位累加器添加到一组 8 个 32 位累加器中 - 请注意,您必须使用该指令两次才能获得两半。

      如有必要,您还可以使用 vmovn 或 vqmovn 将值转换回 16 位或 8 位。

      【讨论】:

        【解决方案4】:

        没有指令可以将你的 4 个 8bit 值加载到 4 个 32bit 寄存器中。

        您必须加载它们,然后使用 vshl 两次。 因为霓虹灯不能使用 32 个寄存器,所以你必须处理 8 个像素(而不是 4 个)

        您只能使用 16 位寄存器。应该够了……

        【讨论】:

          【解决方案5】:

          使用单通道加载指令 (vld1 <register>[<lane>], [<address]) 将 4 个字节加载到 q 寄存器中,然后使用两个移动长指令 (vmovl) 先将它们提升到 16 位,然后再提升到 32 位。结果应该类似于(在 GNU 语法中)

          vld1 d0[0], [<address>] @Now d0 = (*<addr>, *<addr+1>, *<addr+2>, *<addr+3>, <junk>, ... <junk> )
          vmovl.u8 q0, d0 @Now q1 = (d0, d1) = ((uint16_t)*<addr>, ... (uint16_t)*<addr+3>, <junk>, ... <junk>)
          vmovl.u16 q0, d2 @Now d0 = ((uint32_t)*<addr>, ... (uint32_t)*<addr+3>), d1 = (<junk>, ... <junk>)
          

          如果您可以保证&lt;address&gt; 是4 字节对齐的,那么请在加载指令中写入[&lt;address&gt;: 32],以节省一两个周期。但是,如果这样做并且地址未对齐,则会出错。

          嗯,我刚刚意识到你想使用内在函数,而不是汇编,所以这里和内在函数是一样的。

          uint32x4_t v8; // Will actually hold 4 uint8_t
          v8 = vld1_lane_u32(ptr, v8, 0);
          const uint16x4_t v16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(v8)));
          const uint32x4_t v32 = vmovl_u16(v16);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-07-23
            • 2017-06-13
            • 1970-01-01
            • 2016-08-17
            • 2020-04-15
            • 2014-05-26
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多