【发布时间】:2012-02-23 14:08:32
【问题描述】:
我已将部分算法从 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 寄存器中执行偏移计算? 谢谢。
【问题讨论】:
-
我认为您的 C 代码与描述不符。 C 对同一个字的多个字节进行异或运算,但问题说每个字节都用于索引下一个字节。代码显示不清晰,我们无法优化。
-
是的,你是对的。我编辑了它。它总是另一个词。
-
霓虹灯可能不是优化这一点的方法。代码是普通ARM指令集中的SIMD。您可以使用 64k 表(易于生成)并一次处理 16 位,也可以一次运行 32 位 EOR 并折叠结果。获取随机索引的算法会限制此内存,因此执行 EOR 的代码不会显着影响事情。
标签: android performance assembly arm neon