我正在开发一个
Python库,它对长位字符串执行许多按位操作,我想找到一个能够最大化其速度的位串类型.我已经尝试了内置的Python int类型,numpy,
bitstring和
bitarray,而且令人惊讶的是,Python ints似乎在按位运算方面取得了成功.我用google搜索的所有内容都说numpy对于像这样的矢量化操作要快得多.我是不是以某种方式使用了numpy错误?我可以使用另一个Python库,它实际上改进了Python的内置int类型吗?
from timeit import timeit
import random
size = 10000
def int_to_bits(i):
result = []
for _ in range(size):
result.append(i % 2)
i >>= 1
return result
x = random.randrange(2**size)
y = random.randrange(2**size)
print(x.bit_length(), y.bit_length())
x_bits = int_to_bits(x)
y_bits = int_to_bits(y)
t = timeit(
stmt='a & b',
setup='a = %d; b = %d' % (x, y)
)
print("raw ints:", t)
t = timeit(
stmt='a & b',
setup=('import numpy;'
'a = numpy.array(%r, dtype=int);'
'b = numpy.array(%r, dtype=int)') % (x_bits, y_bits)
)
print('numpy int array:', t)
t = timeit(
stmt='a & b',
setup=('import numpy;'
'a = numpy.array(%r, dtype=bool);'
'b = numpy.array(%r, dtype=bool)') % (x_bits, y_bits)
)
print('numpy bool array:', t)
t = timeit(
stmt='a & b',
setup=('import numpy;'
'a = numpy.packbits(%r);'
'b = numpy.packbits(%r)') % (x_bits, y_bits)
)
print('numpy packed bits:', t)
t = timeit(
stmt='a & b',
setup=('import bitstring;'
'a = bitstring.BitString(%r);'
'b = bitstring.BitString(%r)') % (x_bits, y_bits)
)
print('bitstring:', t)
t = timeit(
stmt='a & b',
setup=('import bitarray;'
'a = bitarray.bitarray(%r);'
'b = bitarray.bitarray(%r)') % (x_bits, y_bits)
)
print('bitarray:', t)
结果:
10000 10000
raw ints: 0.29606562735373115
numpy int array: 7.400762747057885
numpy bool array: 1.1108355715984288
numpy packed bits: 1.3064737574273284
bitstring: 380.9796937642803
bitarray: 1.4451143449501842
编辑:
关于Python ints / longs上的单个操作如何与整个numpy位数组上的向量操作相比,似乎存在很多混淆.一个10,000位的Python int / long值,当被视为一个位掩码时(使用&运算符就像我们可以用int或C/C++中的long一样)可以直接比作长度为10,000的numpy bool数组,因为它们两者都包含相同数量的位,尽管以2种不同的方式表示.对于我尝试的表示10,000位的其他方式也是如此,包括使用numpy压缩位数组,numpy int数组和其他库中的位数组/字符串类型.它们都是可比较的,因为它们都在相同的位序列上计算相同的功能.这里最重要的是我可以表示所有10,000位,并且我可以对它们执行按位操作.如果任何人都可以建议一种更有效的方式来表示允许使用按位运算符(&,|和〜)的长,固定长度的位序列,那就是我正在寻找的.
如果你仍然对Python int / long值如何存储与numpy bool数组或numpy二进制值int数组相同的信息感到困惑,请参考上面代码中的int_to_bits函数;它演示了如何从Python int / long中提取位,这表明执行&两个10,000位int的操作基本上与在10,000个布尔值的列表或数组上逐个元素执行操作相同.