摘要 SAD(绝对差和)的霓虹灯实现总线错误

Posted

技术标签:

【中文标题】摘要 SAD(绝对差和)的霓虹灯实现总线错误【英文标题】:Bus error on neon implementation of summary SAD (Sum of Absolute Difference) 【发布时间】:2012-10-24 15:17:51 【问题描述】:

我正在尝试编写 16 个 uint8_t 大小的输入的绝对差和的霓虹灯版本:

inline static int f_sad_16(const uint8_t* a, const uint8_t* b)

  int sad = 0;
  for (int i = 0; i < 16; i++) 
    sad += abs(static_cast<int>(a[i]) - static_cast<int>(b[i]));
  
  return sad;

我写的霓虹代码:

inline static int f_sad_16_neon(const uint8_t* a, const uint8_t* b)

  int32_t r[4] =  0, 0, 0, 0 ;
  uint8x16_t va, vb, vr;

  va = vld1q_u8(a);
  vb = vld1q_u8(b);

  vr = vabdq_u8(va, vb);

  uint16x8_t vr1 = vpaddlq_u8 (vr );
  uint32x4_t vr2 = vpaddlq_u16(vr1);
  uint64x2_t vr3 = vpaddlq_u32(vr2);

  vst1q_u64 (reinterpret_cast<uint64_t*>(r), vr3);

  return r[0] + r[2];

由于某种原因,我收到了总线错误。我的测试程序对两个输入使用__attribute__ ((aligned (16))) gcc 指令,我可以通过分配给它们的内存地址看到输入是 16 字节对齐的。

问题的根源是什么?

【问题讨论】:

你在哪条源代码线上得到了总线错误? 【参考方案1】:

您需要确保 r 正确对齐 - 更改:

int32_t r[4] =  0, 0, 0, 0 ;

到:

int32_t r[4] =  0, 0, 0, 0  __attribute__ ((aligned(16)));

但请注意,此例程不太可能有益,因为它使用大量标量和 NEON 指令,这意味着它的性能很可能与您的原始标量实现相似。

【讨论】:

你是对的,对齐 r[4] 消除了总线错误。我还在寻找你提到的错误,我的测试程序显示了预期的结果。如果您有一个测试用例会显示错误,我很乐意看到它。 对不起 - 我收回关于错误的看法 - 我读代码太快了。不过,我对性能的评论仍然存在 - 您的 NEON 代码不太可能比体面的标量实现快得多。 是的。在一个小型骨架测试中,我看到了在常规 C 代码上启用 -O3 的 ~x1.7 加速与 gcc (4.6.3) 的对比。经过重新思考,我得到了一个适合 128 uint8 上 SAD 需求的解决方案,这是我正在编码的算法需要的 SAD 值。使用 vpadalq_u8 将 16 个 uint8 的总和减少到 8 个 uint16 并累加。在第 8 次迭代之后,使用 vpaddlq 将部分总和减少到 1 SAD 值。这给我的测试程序带来了 ~x7.5 的加速。所有测试运行均在 Cortex-A9 上进行。

以上是关于摘要 SAD(绝对差和)的霓虹灯实现总线错误的主要内容,如果未能解决你的问题,请参考以下文章

基于51单片机的霓虹灯控制器的设计

基于51单片机的霓虹灯控制器的设计

裁剪的高效霓虹灯实现

Flutter 小技巧之霓虹灯文本的「故障」效果的实现

七彩霓虹灯能够实现两种效果(更新版本号2)

为 iOS 编译半浮动霓虹灯指令