我正在研究一个代码,其中两个地方有64位乘32位定点分割,结果以32位进行。这两个地方共占用了我总时间的20%以上。所以我觉得如果我能删除64位除法,我可以很好地优化代码。在NEON中,我们可以有一些64位指令。任何人都可以建议通过使用更快的实现来解决瓶颈问题。
或者如果我能用C中的32位/ 32位除法进行64位/ 32位除法,那还可以吗?
如果有人有任何想法,你能帮帮我吗?
答案 0 :(得分:4)
我过去做了很多定点运算,并且自己做了大量的研究,寻找快速的64/32位分区。如果你谷歌搜索'ARM部门',你会发现吨很棒的链接和关于这个问题的讨论。
ARM架构的最佳解决方案,即使32位除法可能无法在硬件中使用,也可以在这里:
http://www.peter-teichmann.de/adiv2e.html
这个汇编代码非常旧,你的汇编程序可能无法理解它的语法。但是,值得将代码移植到您的工具链中。这是我迄今为止看到的特殊案例中最快的部门代码,请相信我:我对它们进行了基准测试: - )
上次我这样做(大约5年前,对于CortexA8),这段代码比编译器生成的代码快10倍。
此代码不使用NEON。一个NEON端口会很有趣。不确定它是否会提高性能。
修改强>
我发现汇编程序的代码移植到GAS(GNU工具链)。此代码正在运行和测试:
<强> Divide.S 强>
.section ".text"
.global udiv64
udiv64:
adds r0,r0,r0
adc r1,r1,r1
.rept 31
cmp r1,r2
subcs r1,r1,r2
adcs r0,r0,r0
adc r1,r1,r1
.endr
cmp r1,r2
subcs r1,r1,r2
adcs r0,r0,r0
bx lr
<强> C代码:强>
extern "C" uint32_t udiv64 (uint32_t a, uint32_t b, uint32_t c);
int32_t fixdiv24 (int32_t a, int32_t b)
/* calculate (a<<24)/b with 64 bit immediate result */
{
int q;
int sign = (a^b) < 0; /* different signs */
uint32_t l,h;
a = a<0 ? -a:a;
b = b<0 ? -b:b;
l = (a << 24);
h = (a >> 8);
q = udiv64 (l,h,b);
if (sign) q = -q;
return q;
}