是否可以有效地初始化非零值的bytearray?

时间:2016-11-30 13:25:44

标签: python python-3.x python-bytearray

我需要有庞大的布尔数组。所有值都应初始化为" True":

arr = [True] * (10 ** 9)

但如上所述,它需要太多内存。所以我决定使用bytearray

arr = bytearray(10 ** 9)  # initialized with zeroes

是否可以使用bytearray初始化b'\x01'b'\x00'初始化一样有效?

我知道我可以用零初始化bytearray并反转我的逻辑。但如果可能的话,我不愿意这样做。

timeit

>>> from timeit import timeit
>>> def f1():
...   return bytearray(10**9)
... 
>>> def f2():
...   return bytearray(b'\x01'*(10**9))
... 
>>> timeit(f1, number=100)
14.117428014000325
>>> timeit(f2, number=100)
51.42543800899875

3 个答案:

答案 0 :(得分:4)

简单,使用序列乘法:

arr = bytearray(b'\x01') * 10 ** 9

相同的方法适用于使用零(bytearray(b'\x00') * 10 ** 9)初始化,并且通常是首选,因为将整数传递给bytes构造函数之前一直是混淆的源头(人们有时认为它们可以制作单个元素bytes,其值为整数。)

您希望首先初始化单个元素bytearray,然后相乘,而不是乘以bytes并将其传递给bytearray构造函数,这样可以避免将峰值内存需求加倍(并且需要从一个巨大的数组中读取并写入另一个,在简单的memset之上 - 在任何解决方案需要的单个数组上执行操作。)

在我的本地测试中,bytearray(b'\x01') * 10 ** 9的运行速度与bytearray(10 ** 9)一样快;每个循环花费约164毫秒,而bytes对象乘以434毫秒,然后将其传递给bytearray构造函数。

答案 1 :(得分:3)

您使用的是numpy吗?你可以这样做:

import numpy as np
np.ones(10,dtype=bool)

返回:

array([ True,  True,  True,  True,  True,  True,  True,  True,  True,  True], dtype=bool)

此外,您可以使用ndarray.tobytes()轻松转换回字节,如下所示:

x = np.ones(10,dtype=bool)
x.tobytes()
# returns: b'\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01'

有关详细信息,请参阅this answer

答案 2 :(得分:3)

考虑使用NumPy来做这类事情。在我的计算机上,np.ones(使用布尔“dtype”初始化所有1值的数组)与裸bytearray构造函数一样快:

>>> import numpy as np
>>> from timeit import timeit
>>> def f1(): return bytearray(10**9)
>>> def f2(): return np.ones(10**9, dtype=np.bool)
>>> timeit(f1, number=100)
24.9679438900057
>>> timeit(f2, number=100)
24.732190757000353

如果您不想使用第三方模块,另一个具有竞争性能的选项是创建一个元素bytearray,然后展开它,而不是创建一个大的字节串并将其转换为一个bytearray。

>>> def f3(): return bytearray(b'\x01')*(10**9)
>>> timeit(f3, number=100)
24.842667759003234

由于我的计算机似乎比您的计算机慢,所以这是您原始选项的性能以供比较:

>>> def fX(): return bytearray(b'\x01'*(10**9))
>>> timeit(fX, number=100)
56.61828187300125

所有情况下的成本都将通过分配一个十进制千兆字节的RAM并写入其中的每个字节来占主导地位。 fX的速度大约是其他三个函数的两倍,因为它必须执行两次。使用这样的代码时,要记住的一个好的经验法则是:最小化分配数量。可能值得下降到可以明确控制分配的低级语言(如果您还不知道任何此类语言,我建议Rust)。