您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

python位数组(性能)

python位数组(性能)

内置的int是相当漂亮优化,它已经支持&|<<

至少有一种基于GMP的任意长度整数的替代实现,称为gmpy2。(还有原来gmpyPyGMPSophie,和其他一些围绕同一个库包装,但我怀疑他们会拥有真正的性能差异。)

“位数组”概念有两个主要实现,bitarray(您链接一个)和bitstring,以及类似的一些库intbitset为您提供了一个类似集合的接口(也应该适合您的使用)。

因此,让我们将它们扔在一起并进行比较:

import random
import struct
import timeit
import bitarray
import bitstring
import gmpy2

n = random.randrange((1<<31)+1, 1<<32)

bs = bitstring.pack('<q', n)
ba = bitarray.bitarray(64)
ba.frombytes(struct.pack('<q', n))
gm = gmpy2.mpz(n)
py = n

for x in 'bs', 'ba', 'gm', 'py':
    def f(x=locals()[x]): x | x; x & x
    t = timeit.timeit(f, number=10000)
    print(x, t)

在我的Mac上,运行Python.org 64位cpython 3.3.2,这是我得到的:

bs 0.7623525890521705
ba 0.006623028079047799
gm 0.0016346259508281946
py 0.002280334010720253

这似乎足以立即撤消bitstring

另外,虽然我没有intbitset在这里展示,但是由于它和我发现的任何类似库都没有使用Python 3,因此从各种比较(使用intbitset.intbitset([i for i, bit in enumerate(bin(n)[2:]) if bit != '0']))中,它的速度比int我进行的每次测试都慢14到70倍,因此我也已将其驳回。

因此,让我们尝试另外三个代表:

ba 6.385123810963705
gm 1.5937359740491956
py 2.129726824001409

和数字保持。bitarray没有内置的那么快int。使用起来也比较笨拙(请注意,应该是“替代构造函数”的类方法是实例方法,没有快速简便的方法可以将int或int转换为int,我之所以进行测试x | xx & x是因为存在局限性在运营商上)。如果需要整数作为位数组,那很好。如果您需要对整数进行C风格的位计算,那不是最好的方法

至于gmpy2,它似乎比本地人快三分之一int。如果我们使数字大得多,例如1.5kbit,该怎么办?

gm 0.19562570203561336
py 0.29293217696249485

以下是Apple Python 2.7.5的数字:

('gm', 0.2890629768371582)
('py', 0.36592698097229004)

那么,值得吗?它使用起来不太友好,在您没有要求的其他一些操作上,它的运行速度较慢而不是更快,它需要LGPL许可的第三方C库,在内存溢出情况下错误处理行为要差得多(例如,您的应用可能会出现段错误而不是提高错误),并且StackOverflow上至少会有一个人出现并告诉您,只要提及GMP,它就很烂(我相信是因为旧版本中存在错误)。

但是,如果您需要这种额外的速度,也许值得。

另一方面,这是PyPy,3.2.3 / 2.1.0b1和PyPy 2.7.3 / 2.1.0,使用本机int类型- 与上述gmpy2的结果0.19562570203561336和0.2890629768371582进行了比较:

py 0.2135779857635498
('py', 0.20878291130065918)

因此,从cpython切换到PyPy所带来的好处几乎intgmpy2.mpz在Python 3中从切换到PyPy一样多,并且在Python 2中带来的好处更多。几乎可以肯定的是,它也将加速其余代码

python 2022/1/1 18:38:17 有229人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶