ARM-NEON:基于参数的条件寄存器交换

Posted

技术标签:

【中文标题】ARM-NEON:基于参数的条件寄存器交换【英文标题】:ARM-NEON: Conditional register swapping based on parameters 【发布时间】:2014-03-07 19:45:56 【问题描述】:

我正在 NEON 中编写一个用于进行颜色交换的图像处理子程序,即,我从一个数组中顺序加载 R、G、B 通道,并根据某些配置,置换其中的一些通道。

最多有 6 个排列

  (RGB) ->  (RGB),(RBG),(GRB),(GBR),(BRG),(BGR) 

最有效的方法是为每种情况使用一个单独的子程序和相应的 VSWP 指令。由于子程序会做其他几件事,我宁愿把所有东西都放在一个子程序中,即使效率不高,

还阅读了条件执行和分支是不可取的。所以,如果我想把它放在一个带有无分支代码的块中,我唯一想到的是

New_R = a(0)*R+a(1)*G+a(2)*B
New_G = a(3)*R+a(4)*G+a(5)*B
New_B = a(6)*R+a(7)*G+a(8)*B

每行和每列中只有一个a(i)每次=1,其余为=0

问题:有什么更聪明的方法吗?考虑到它必须被编码为 NEON?

【问题讨论】:

【参考方案1】:

VTBL.8 是 NEON 中最强大的字节交换工具。

将 3x8 字节加载到寄存器 d0,d1,d2 看起来像

  R G B R G B R G | B R G B R G B R | G B R G B R G B |
  0 1 2 3 4 5 6 7   8 9 a b c d e f ....            17

VTBL d3,  d0,d1,d2 , d6  ;; select bytes to d3 from d0,d1,d2 based on d6
VTBL d4,  d0,d1,d2 , d7
VTBL d5,  d0,d1,d2 , d8

其中 d6,d7,d8 编码要在新字节中读取的位置。 例如'0 1 2 3 4 5 6 7' 用于原始排列,'0 2 1 3 5 4 6 8', '7 ...' 用于交换 G 和 B。常量向量 d6..d8 只需加载例程开始时一次。

另一种可能性是使用交错读取对以下序列进行编码;

VLD3.8  d0,d1,d2 , [r0]    ; // Read R, G, B to separate registers
VLD3.8  d3,d4,d5 , [r0]    ; // Make a second copy (or use some other instruction)

VBIT d3, d1, d6              ; // d3 is now either R or G
VBIT d4, d2, d7              ; // d4 is now either G or B
VBIT d5, d0, d8              ; // d5 is now either B or R

VBIT d0, d4, d9              ; // d0 is now R or (G or B)
VBIT d1, d5, d10             ; // d1 is now G or (B or R)
VBIT d2, d3, d11             ; // d2 is now B or (R or G)

虽然示例中使用了 6 个寄存器作为条件码,但 3 个独立的寄存器应该足够了——如果需要使用反向逻辑,也可以使用 VBIF。

【讨论】:

无话可说。我之前的问题只是关于 VTBL,但根本没想到它也可以用于排列。谢谢 我认为这不是最有效的方法,因为 VTBL 相当复杂并且不能在单个时钟中执行。不过这很容易。您可能想尝试使用 interleaved read VLD3.8 将 RGB 分离到不同的通道,d1=R、d2=G、d3=B,并使用 VBIT 或 VSEL 复制完整的寄存器。使用VLD3.8 d0, d2, d4, [r0]!; VLD3.8 d1, d3, d5, [r0]! 允许将完整的寄存器 q0 分配给红色通道。 是的,我已经进行了交错阅读并调整了您之前对这个案例的回答。但是我看不到如何使用 VBIT o VSEL 来处理一般情况,即在前面的答案中,我只需要加载一次 d6..d8。对不起,如果我问的很明显,我很新。 我喜欢 VBIT 选项,谢谢。此外,也许第二个负载可以替换为 2 vmov(如果寄存器选择正确,一个带有 q,另一个带有 d),从而提高循环计数。 @AkiSuihkonen:这取决于您所针对的特定内核,但对于高功率部件VTBL 确实非常快,并且执行此操作的最面向未来的方式(即@ 987654326@ 并没有因为 arm 内核变得越来越复杂而变得更慢——在越来越多的处理器上它将是单周期)。

以上是关于ARM-NEON:基于参数的条件寄存器交换的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有隐式锁定最新的64位Intel CPU的情况下用寄存器交换堆栈顶部?

如何在 XMM 寄存器之间交换值?

Marvell交换芯片88E6321/88E6320驱动总结-寄存器篇

故障处理之Cisco 3650交换机配置无法保存

CISCO-路由器交换机密码恢复

有条件地将零移入寄存器?