我正在处理由两部分组成的ARM NEON代码。第一部分计算从添加到某些计算值的基地址开始的各种地址(存储器)(结果是非常远的存储器地址)。第二部分必须从第一部分中计算的地址加载数据并使用它们。第一部分和第二部分都是高度可并行化的,并且只使用NEON并行性。
我需要找到组合这两部分的最佳方法:使用第一阶段的地址输出加载数据。
我尝试过并且似乎工作的是最简单的解决方案:
//q8 & q9 have 8 computed addresses
VMOV.32 r0, d16[0] //move addresses to standard registers
VMOV.32 r1, d16[1]
VMOV.32 r2, d17[0]
VMOV.32 r3, d17[1]
VLD1.8 d28[0], [r0] //load uchar (deinterleaving in d28 and d29)
VLD1.8 d29[0], [r1] //otherwise do not interleave and use VUZP
VLD1.8 d28[1], [r2]
VLD1.8 d29[1], [r3]
VMOV.32 r0, d18[0]
VMOV.32 r1, d18[1]
VMOV.32 r2, d19[0]
VMOV.32 r3, d19[1]
VLD1.8 d28[2], [r0]
VLD1.8 d29[2], [r1]
VLD1.8 d28[3], [r2]
VLD1.8 d29[3], [r3]
...
//data loaded in d28 and d29
在这个例子中,我使用了四个R寄存器(可以使用更少或更多),并且我在d28和d29中对数据进行去交错,模拟在阵列上工作的标准VLD2.8。
由于这个问题(在NEON中计算地址并从这些地址加载)经常发生在我身上,有没有更好的方法? 感谢
答案 0 :(得分:1)
你所做的可能有用,但你不应该这样做。
虽然ARM-> NEON传输是灵活的,但NEON-> ARM传输不是。它们导致管道失速每次启动时浪费大约14个周期。
在你的情况下,没有浪费28个周期。而且我确信使用ARM进行数学运算会花费更少的时间。
坚持使用ARM。在处理多个32位数据(如地址)时,ARMv7可以从其双(三)发布功能中获益匪浅。 (乘法除外)