我需要有庞大的布尔数组。所有值都应初始化为" 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
答案 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)。