【问题标题】:Efficient mod 3 in x86 assemblyx86 组装中的高效 mod 3
【发布时间】:2017-05-27 02:18:59
【问题描述】:

DIV 指令在现代处理器上非常昂贵。有没有更快的方法来减少 x86 程序集中的 64 位整数 mod 3?

【问题讨论】:

标签: assembly x86-64 micro-optimization


【解决方案1】:

有一些算法,基于通过乘以除数的倒数来执行除法。这方面的论文有很多,最常被引用的一篇是:

Torbjörn Granlund 和 Peter L. Montgomery。 “使用乘法除以不变整数。” ACM SIGPLAN 通知。卷。 29,第 6 期,1994 年 8 月,第 61-72 页(online)

当启用优化时,您的 C/C++ 编译器很可能已经使用了该算法的变体。例如,我的 Intel 编译器版本 13 会变成这样:

#include <stdint.h>
uint64_t mod3 (uint64_t a)
{
    return a % 3;
}

进入这个(我的行尾注释):

mod3    PROC
; parameter 1: rcx
        mov       r8, 0aaaaaaaaaaaaaaabH      ;; (scaled) reciprocal of 3
        mov       rax, rcx
        mul       r8                          ;; multiply with reciprocal
        shr       rdx, 1                      ;; quotient
        lea       r9, QWORD PTR [rdx+rdx*2]   ;; back multiply with 3
        neg       r9
        add       rcx, r9                     ;; subtract from dividend 
        mov       rax, rcx                    ;; remainder
        ret
mod3    ENDP

【讨论】:

  • 还有:Niels Möller 和 Torbjörn Granlund。 "Improved division by invariant integers.",更适合现代处理器。但对于这种特殊情况,可能效率不高。
  • 确实,我见过的所有 x86-64 编译器都应用这种算法,生成几乎相同的代码。唯一的区别是英特尔倾向于做neg+add,而不是sub。我从来没有想出一个很好的理由。他们的文档没有表明addsub 快。所以要么这只是编译器内部实现的一个怪癖,要么他们在自己的处理器上有一些有趣的内部信息说不同。
  • 令人印象深刻,实际上速度更快。
  • @Joshua 64 位除法非常慢。即使在像 Kaby 这样的新事物上,使用 64 位 div 计算 0/3 也需要超过 30 个周期,这是 最佳 的情况,它会上升到近 50 个周期以获得更高的股息(或者在考虑所有可能的股息时接近 100 个周期/除数)。
猜你喜欢
  • 2020-04-01
  • 2015-11-21
  • 2020-04-30
  • 1970-01-01
  • 1970-01-01
  • 2012-07-24
  • 2015-11-20
  • 2016-01-17
  • 1970-01-01
相关资源
最近更新 更多