ARM Neon:将相邻的两个像素相加至平均四个相邻像素

时间:2016-09-09 01:49:21

标签: assembly arm neon

我有4个车道d0,d1,d2,d3我希望平均四个相邻:

d0[0] = (d0[0] + d0[1] + d0[2] + d0[3]) / 4
d0[1] = (d0[4] + d0[5] + d0[6] + d0[7]) / 4
d0[2] = (d1[0] + d1[1] + d1[2] + d1[3]) / 4 
...

以下霓虹灯代码是否正确?

vpaddl.u8 d0, d0
vpaddl.u8 d1, d1

vpaddl.u8 d2, d2
vpaddl.u8 d3, d3

vpadd.u16 d0, d0, d2
vshrn.u16 d0, q0, #2

如果是,有更快的方法吗?

编辑1

上面的代码不正确。我想出了以下内容:

vpaddl.u8 d0, d0
vpaddl.u8 d1, d1
vpaddl.u8 d2, d2
vpaddl.u8 d3, d3
vuzp.u16 q0, q1
vadd.u16 q0, q0, q1
vshrn.u16 d0, q0, #2

哪个有效。这非常类似于Notlikethat'的第二个建议。接受了答案,但采用的方式不太优化。

1 个答案:

答案 0 :(得分:3)

经过一段时间playing around之后,我会说在给定的约束条件下,你的一般方法可能与你将得到的一样好。有超过4个寄存器值的数据同时处理,和/或有机会吸收算法中其他地方重新排列向量的成本,结论可能会有所不同,但其他可行选项非常有限。

但是,您在第二轮缩减中忘记了d1d3,并且第一轮可以简化为两条指令,因为与vpadd不同,{{1}确实有一个Q寄存器形式。修复这些最终结果:

vpaddl

就纯指令计数而言, 可以通过进行部分转置然后直接累积两个成对约简来降低,因此:

vpaddl.u8 q0, q0
vpaddl.u8 q1, q1
vpadd.u16 d0, d0, d1
vpadd.u16 d1, d2, d3
vshrn.u16 d0, q0, #2

但是Q-form vuzp.16 q0, q1 vpaddl.u8 q0, q0 vpadal.u8 q0, q1 vshrn.u16 d0, q0, #2 确实非常昂贵我可以找到指令时间,vuzp的累积也不是免费的,所以几乎可以肯定最终整体表现会比更直接的版本更差。