8

我正在编写一个代码,其中在两个地方有 64 位乘 32 位定点除法,结果取 32 位。这两个地方加起来占了我总时间的 20% 以上。所以我觉得如果我可以去掉 64 位除法,我可以很好地优化代码。在 NEON 中,我们可以有一些 64 位指令。任何人都可以建议一些例程来通过使用更快的实现来解决瓶颈。

或者,如果我可以在 C 中按照 32 位/32 位除法进行 64 位/32 位除法,那也可以吗?

如果有人有一些想法,你能帮帮我吗?

4

1 回答 1

5

我过去做了很多定点算术,并且自己做了很多研究来寻找快速的 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;
}
于 2013-03-05T03:35:16.467 回答