为尾随0位的模实现更快的divmod()

shift-divmod的Python项目详细描述


Info:This is the README file for ShiftDivMod.
Author:Shlomi Fish <shlomif@cpan.org>
Copyright:© 2020, Shlomi Fish.
Date:2020-09-20
Version:0.4.3
https://travis-ci.org/shlomif/shift_divmod.svg?branch=master

目的

这个发行版实现了更快的divmod()(和.mod())操作 对于有大量尾随0位的模(其中div/mod基 对于整数n,可以被2 ** n整除。在

它应该产生与内置的divmod()函数相同的结果 正分子(它对负分子的行为目前是 未测试和未定义)。在

还提供了到C和gmplib(=GNU多精度)的端口: https://github.com/shlomif/shift_divmod/tree/master/gmp-shift_divmod

安装

pip3安装shift_divmod

使用

from shift_divmod import ShiftDivMod

base = 997
shift = 1200
modder = ShiftDivMod(base, shift)
# Alternative constructor which may require more
# work and eventualy calls the default constructor
modder = ShiftDivMod.from_int(base << shift)

x = 10 ** 500
# Same as divmod(x, (base << shift))
print( modder.divmod(x) )

注释

从中派生出此分布的代码被建议为 内置cpython3潜在改进的概念证明 此处的操作:https://bugs.python.org/issue41487。但是,更改cpython3 就这样被拒绝了。在

libdivide(https://github.com/ridiculousfish/libdivide)提供了一个 不同的,但也很有趣的优化划分的方法。在

基准:

在我的系统上,我在运行后得到了这些结果 python3 code/examples/shift_divmod_example.py bench(已重新格式化 为清楚起见):

^{pr2}$

可以注意到,基于shift_divmod的版本比 它比只完成1000次迭代中的25次的内置nops快得多 在被打断之前。注意,对于这个用例,使用GMP的模幂 似乎更快。在

对于C和gmplib版本:

  • mpz_mod运行基准测试大约需要160秒。在
  • shift_divmod运行基准测试大约需要35秒。在
  • pypy3在25秒内运行纯Python代码(!)。在

秘方:

代码利用了bitwise operations 速度很快,这段代码中出现了神奇的效果(为了清晰起见,添加了一些注释):

# Precalculating the object's field so that:
# self.shift : a non-negative integer signifying the bit shift
# self.base  : a non-negative integer which is shifted to
# form the modulu
# self.n = self.base << self.shift
# self.mask = ((1 << self.shift) - 1)
def divmod(self, inp):
    """calculate divmod(inp, self.n)"""
    if inp < self.n:
        return 0, inp
    div, mod = divmod((inp >> self.shift), self.base)
    return div, ((mod << self.shift) | (inp & self.mask))

(或等效但更官僚的C和gmplib代码。)

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java如何在表被注释到配置之前获取表的元数据?   java滚动条不会出现在JList上   java JOGL监视器GPU内存   java为什么要使用RecyclerView onDraw延迟   java定制Oppo Reno 2 Z CPH1951(手机型号)的固件(闪存文件)   java自定义线程池执行器   java如何解决发布版本中重复的jar条目[com/安卓/volley/R.class]?   java如何使用Bukkit API触发事件?   java在blazemeter jmeter RTE插件中使用ctrl+w输入   C#/Visual Studio的java JDT等价物   java为什么当maxread值很大而收到的消息数量很小时,卡夫卡消费者会无限期消费?   java游戏2。x:包含模板列表的绑定模型   带压缩的java日志旋转   运行时。exec用java运行程序读取它正在做什么