【问题标题】:64bit/32bit division faster algorithm for ARM / NEON?ARM / NEON的64位/ 32位划分更快的算法?
【发布时间】:2013-11-09 22:29:27
【问题描述】:

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

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

如果有人有什么想法,可以请你帮帮我吗?

【问题讨论】:

  • 为什么要结束投票?

标签: c arm


【解决方案1】:

我过去做过很多定点运算,我自己也做过很多研究来寻找快速的 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;
}

【讨论】:

  • 语法真的很奇怪,但如果我没记错的话,你链接的算法只是有条件地减去适合的除数的每个二次幂倍数(使用条件代码而不是分支)并保持一致。这个对吗?如果是这样,如果编译器不错,您可能可以用 C 编写完全相同的东西并获得相同的性能。
  • 好吧,如果编译器不错,你应该得到相同的结果。以我的经验,只要你所做的一切都是 32 位算术,ARM 编译器就会做得很好。一旦你使用 64 位整数(这里需要,因为你不能在 C 中表达进位标志),它们就会切换到哑模式并生成不太好的代码。
  • a 为 -2147483648 时,此代码将失败。在这种情况下,a a&lt;0 ? -a:a; 中的 -a 会溢出。在常见的实现中,结果是 -2147483648,然后a &gt;&gt; 8 的结果是实现定义的,通常会导致稍后计算错误的商。
  • 编译器不会使用carry 执行多字指令。这不会映射到 C。如果你有 long long 类型,它可能是可能的,但我怀疑 assembler 忽略了一些编译器不会的边界情况。请参阅:非常重要:FDIV64 仅适用于无符号整数,商必须适合 32 位!
  • 链接好像坏了。
猜你喜欢
  • 2020-05-28
  • 2010-12-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-26
  • 2012-10-26
  • 2012-02-15
相关资源
最近更新 更多