【发布时间】:2017-10-29 10:13:32
【问题描述】:
我正在使用一些图像处理功能,我需要以最快的方式反转字节数组。如果我试图解释我的实际功能,那将是不合适的。这就是我要简化问题标准的原因。
Input Array:
37 3B 29 32 C5 E3 F3 5E 04 E2 CA B8 A1 1F 64 1D
E5 6F 7B 2C EA 6A FD 1F A5 6B 8F FA FB 7A F4 2A
DC 08 6D DB B8 D4 77 5D A2 44 E6 8A 59 9C 7D C2
8E FB C6 2A F8 EC 96 ED DC F8 00 2D 63 4C A4 F9
Length: 64
Output Array:
F9 A4 4C 63 2D 00 F8 DC ED 96 EC F8 2A C6 FB 8E
C2 7D 9C 59 8A E6 44 A2 5D 77 D4 B8 DB 6D 08 DC
2A F4 7A FB FA 8F 6B A5 1F FD 6A EA 2C 7B 6F E5
1D 64 1F A1 B8 CA E2 04 5E F3 E3 C5 32 29 3B 37
用 C++ 等高级语言来完成这项工作真的很容易。在 C++ 中,此实现可能如下所示:
void Reverse_array(unsigned char* pInData, int iLen, unsigned char* pOutData)
{
int indx = 0;
for(int i=iLen-1; i>=0; i--)
{
pOutData[indx++] = pInData[i];
}
}
但我确实需要找到最有效和优化的解决方案来完成这项工作。由于此任务将在移动设备中执行,我决定在 ARM 中使用带有 Neon Extension 的原始汇编语言来实现。现在,我将分享我为实现此任务所做的努力(仍然不完整)。
NEON_ASM_FUNC_BEGIN Reverse_array_arm_neon
push {r2-r8, lr}
#r0 First parameter, This is the address of <pInData>
#r1 Second Parameter, This is the iLen
#r2 Third Parameter, This is the address of <pOutData>
add r2, r2, r1
ands r3, r1, #7
add r2, r2, #8
loop_Reverse:
vld1.u8 {d0}, [r0]!
vrev64.u8 d1, d0
sub r2, r2, #16
vst1.u8 {d1}, [r2]!
subs r1, #8
bne loop_Reverse
pop {r2-r8, pc}
NEON_ASM_FUNC_END
我还检查了 StackOverFlow 的 How to reverse an array in assembly language ARM? 和 Reversing an array in assembly 解决方案,但我仍然需要更多有关此实现的知识。
- 有没有可能用arm汇编语言写出比c++更快的函数来解决这个问题?
- 使用 NEON 扩展功能实现此任务的正确方法是什么? (我的函数是不完整的,因为它不能以不能被 8 整除的不同长度工作)。
任何想法或信息都会对我有所帮助。谢谢你。
【问题讨论】:
-
对我来说,这听起来像是过早的优化——先尝试基准测试/分析
std::reverse,看看这是否真的是一个很好的优化候选者,然后再浪费大量时间和精力编写不可移植和不太健壮的代码哪一个可能会变得很少或没有好处? -
In和out是否重叠,或者它们甚至相同? -
当然,如果 std:reverse 没有针对 NEON 进行优化,NEON 版本会快很多,尤其是因为提升了对齐和较低的带宽要求。
-
@RajibTheKing:您可能会发现 this article 很有用 - 它更多地关注 x86/SSE/AVX,但许多技术可以有效地应用于其他 SIMD 架构,例如 NEON。