1

我正在使用 OpenCV 在嵌入式系统(BeagleBone Black)上进行一些图像处理,并且需要编写一些代码以利用 NEON 优化。具体来说,我想编写一个 NEON 优化阈值函数,然后编写一个 NEON 优化腐蚀/膨胀函数。

这是我第一次编写 NEON 代码并且我没有编写汇编代码的经验,所以我一直在寻找 C 风格NEON 内在函数的示例和资源。我相信我可以将一些工作代码放在一起,但不知道应该如何构造向量。根据“ ARM 编译器中的 ARM NEON 支持”白皮书的第 2 页:

“这些寄存器可以保存 8、16、32 或 64 位项目的“向量”。在优化或移植用 C/C++ 编写的算法时,传统建议是使用机器的自然类型进行数据处理(在这种情况下) ARM 32 位)。然后可以在存储到内存之前通过强制转换和/或移位来丢弃不需要的位。

这到底是什么意思?我是否需要将我的 NEON 代码限制为使用uint32x4_t向量而不是向量uint8x16_t?我将如何加载寄存器?vst1q_u8或者这是否意味着我在使用将数据存储到内存时需要采取一些特殊步骤?

我确实找到了这个示例,它未经测试但使用了该uint8x16_t类型。它是否遵守上面给出的“32 位”建议?

如果有人能详细说明上述报价并提供一个非常简单的工作示例,我将不胜感激。

4

1 回答 1

2

您链接的文档中的下一句给出了您的答案。

NEON 能够在指令中指定数据宽度并因此将整个寄存器宽度用于有用信息,这意味着保持算法的自然类型既可行又可取。

请注意,该文档区分了机器的自然类型(32 位)和算法的自然类型(在您的情况下为 uint8_t)。

该文档说,在过去,您会以使用 32 位整数的方式编写代码,以便它可以使用适合 32 位操作的高效机器指令。

对于 Neon,这不是必需的。使用您实际想要使用的数据类型更有用,因为 Neon 可以有效地对这些数据类型进行操作。

寄存器宽度的最佳选择(uint8x8_t 或 uint8x16_t)取决于您的算法。

举一个使用 Neon 内部函数添加两组 uint8_t 的简单示例:

#include <arm_neon.h>
void
foo (uint8_t a, uint8_t *b, uint8_t *c)
{
  uint8x16_t t1 = vld1q_u8 (a);
  uint8x16_t t2 = vld1q_u8 (b);
  uint8x16_t t3 = vaddq_u8 (a, b);
  vst1q_u8 (c, t3);
} 
于 2013-10-17T09:23:30.460 回答