3

我已将部分算法从 C 转换为 ARM 汇编程序(使用 NEON 指令),但现在它比原始 C 代码慢 2 倍。我怎样才能提高性能?

目标是 ARM Cortex-A9。

该算法从数组中读取 64 位值。从这个值中提取一个字节,然后将其用作另一个表的查找值。这部分完成了大约 10 次,每个结果表值与其他值进行异或运算,并将最终结果写入另一个数组。

像这样的东西:

result[i] = T0[ GetByte0( a[i1] ) ] ^ T1[ GetByte1( a[i2] ) ] ^ ... ^ T10[ (...) ];

在我的方法中,我在 Neon Registers 中加载整个数组“a”,然后在 arm 寄存器中移动右字节,计算偏移量,然后从表中加载值:

vldm.64 r0, {d0-d7}         //Load 8x64Bit from the input array

vmov.u8 r12, d0[0]          //Mov the first Byte from d0 into r12
add r12, r2, r12, asl #3    // r12 = base_adress + r12 << 3
vldr.64 d8, [r12]           // d8 = mem[r12]
.
.
.
veor d8, d8, d9             // d8 = d8 ^ d9
veor d8, d8, d10            // d8 = d8 ^d10      ...ect.

其中 r2 保存查找表的基址。

adress = Table_adress + (8* value_fromByte);

这一步(除了开始时的加载)大约做了 100 次。为什么这么慢?

还有"vld""vldr""vldm"之间的区别是什么- 哪个是最快的。如何仅在 Neon 寄存器中执行偏移计算?谢谢你。

4

4 回答 4

3

Neon 不能处理大于 VTBL 指令限制(如果我没记错的话是 32 字节)的查找。
查找表是如何创建的?如果只是计算,只需让 Neon 进行数学运算,而不是求助于查找。这样会快很多。

于 2012-02-24T03:10:51.440 回答
2

不要使用

vmov.u8 r12, d0[0]

将数据从 NEON 寄存器移动到 ARM 寄存器是您能做的最糟糕的事情。

也许你应该看看 VTBL 指令!你是什​​么字节范围 0..255 ?

于 2012-02-23T14:40:32.067 回答
1

可能你可以试试

ldrb     r12, [r0], #1
add      r3, r2, r12, asl #3
vld1.64  {d0}, [r3]

ldrb     r12, [r0], #1
add      r3, r2, r12, asl #3
vld1.64  {d1}, [r3]
veor     d0, d0, d1         // d8 = d8 ^ d1

ldrb     r12, [r0], #1
add      r3, r2, r12, asl #3
vld1.64  {d1}, [r3]
veor     d0, d0, d1         // d8 = d8 ^ d1

...

那将不是最好的解决方案。之后,您可以通过重新订购指令来提高性能。

于 2012-02-23T15:32:13.377 回答
0

尝试使用 NEON“内在函数”。基本上它们是编译成 NEON 指令的 C 函数。编译器仍然可以完成所有的指令调度,而你可以免费获得其他无聊的东西(移动数据)。

它并不总是完美地工作,但它可能比尝试手动编码更好。

寻找arm_neon.h

于 2012-02-24T11:29:24.750 回答