c - 64位/32位除法更快的ARM / NEON算法



我正在研究一种代码,其中两个地方有64位乘32位固定点除法,结果采用32位。这两个地方加起来占了我总时间的20%以上。所以我觉得如果我能去掉64位除法,我就能很好地优化代码。在NEON中,我们可以有一些64位指令。有谁能建议一些例程来解决瓶颈,使用一些更快的实现吗?

或者如果我可以用C语言中的32位/32位除法来表示64位/32位除法,那也可以吗?

如果有人有什么想法,你能帮我吗?

我过去做过很多定点运算,我自己也做了很多研究,寻找快速的64/32位除法。如果你在谷歌上搜索"ARM部门",你会发现大量关于这个问题的链接和讨论。

ARM架构的最佳解决方案,在硬件上甚至不能使用32位分割,在这里:

http://www.peter-teichmann.de/adiv2e.html

这个汇编代码非常旧,汇编程序可能不理解它的语法。然而,将代码移植到您的工具链中是值得的。对于您的特殊情况,这是迄今为止我见过的最快的除法代码,相信我:我已经对它们进行了基准测试:-)

上次我这样做的时候(大约5年前,对于CortexA8),这段代码比编译器生成的代码快10倍。

这段代码没有使用NEON。NEON移植会很有趣。但我不确定它是否会大大提高性能。

编辑:

我发现代码与汇编移植到GAS (GNU工具链)。下面的代码正在运行和测试:

鸿沟。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;
}

最新更新