Pau*_*aul 29 python random bytearray
我需要创建一个特定大小的大型字节,但在运行时之前不知道大小.字节需要相当随机.字节数大小可以小到几KB,但可以大到几MB.我不想逐字节迭代.这太慢了 - 我需要与numpy.random类似的性能.但是,我没有可用于此项目的numpy模块.是否有标准python安装的一部分可以做到这一点?或者我需要使用C编译自己的?
对于那些要求时间的人:
>>> timeit.timeit('[random.randint(0,128) for i in xrange(1,100000)]',setup='import random', number=100)
35.73110193696641
>>> timeit.timeit('numpy.random.random_integers(0,128,100000)',setup='import numpy', number=100)
0.5785652013481126
>>>
Run Code Online (Sandbox Code Playgroud)
Ned*_*der 41
urandom即使在Windows上,os模块也提供:
bytearray(os.urandom(1000000))
Run Code Online (Sandbox Code Playgroud)
这看起来像你需要的那样快,事实上,我得到的时间比你的numpy好(虽然我们的机器可能会大不相同):
timeit.timeit(lambda:bytearray(os.urandom(1000000)), number=10)
0.0554857286941
Run Code Online (Sandbox Code Playgroud)
只包括numpy有什么问题?无论如何,这会创建一个随机的N位整数:
import random
N = 100000
bits = random.getrandbits(N)
Run Code Online (Sandbox Code Playgroud)
因此,如果你需要查看是否设置了第j位的值,你可以这样做 bits & (2**j)==(2**j)
编辑:他要求字节数组不是位数组.奈德的答案更好:your_byte_array= bytearray((random.getrandbits(8) for i in xrange(N))
有几种可能,比快一些os.urandom。还考虑是否必须从随机种子确定性地生成数据。对于必须重现故障的单元测试而言,这是非常宝贵的。
简短而精巧:
lambda n:bytearray(map(random.getrandbits,(8,)*n))
我已经将以上内容用于单元测试,它足够快,但是可以更快地完成吗?
使用itertools:
lambda n:bytearray(itertools.imap(random.getrandbits,itertools.repeat(8,n))))
itertools和struct每次迭代产生8个字节
lambda n:(b''.join(map(struct.Struct("!Q").pack,itertools.imap(
random.getrandbits,itertools.repeat(64,(n+7)//8)))))[:n]
Run Code Online (Sandbox Code Playgroud)
任何基于的东西b''.join都会用临时对象填充最终字节数组消耗的3-7倍的内存,因为它将所有子字符串排在队列中之后才将它们连接在一起,并且python对象有很多存储开销。
使用专用功能生产大块块可提供更好的性能,并避免填充内存。
import random,itertools,struct,operator
def randbytes(n,_struct8k=struct.Struct("!1000Q").pack_into):
if n<8000:
longs=(n+7)//8
return struct.pack("!%iQ"%longs,*map(
random.getrandbits,itertools.repeat(64,longs)))[:n]
data=bytearray(n);
for offset in xrange(0,n-7999,8000):
_struct8k(data,offset,
*map(random.getrandbits,itertools.repeat(64,1000)))
offset+=8000
data[offset:]=randbytes(n-offset)
return data
Run Code Online (Sandbox Code Playgroud)
randint:bytearray(getrandbits(8) for _ in xrange(n)):(由其他海报者解决)bytearray(map(getrandbits,(8,)*n))itertools和getrandbitsos.urandomitertools和struct注意:所有测试均使用10KB作为字符串大小。结果是一致的,直到中间结果充满记忆为止。
注意:os.urandom是为了提供安全的随机种子。应用程序使用自己的快速PRNG扩展该种子。这是一个示例,在计数器模式下使用AES作为PRNG:
import os
seed=os.urandom(32)
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
backend = default_backend()
cipher = Cipher(algorithms.AES(seed), modes.CTR(b'\0'*16), backend=backend)
encryptor = cipher.encryptor()
nulls=b'\0'*(10**5) #100k
from timeit import timeit
t=timeit(lambda:encryptor.update(nulls),number=10**5) #1GB, (100K*10k)
print("%.1f MB/s"%(1000/t))
Run Code Online (Sandbox Code Playgroud)
这将产生180 MB / s的伪随机数据。(无硬件AES加速,单核)仅是上述纯python代码速度的约5倍。
有一个纯python加密库正在等待编写。将上述技术与hashlib流密码技术结合在一起看起来很有希望。这是一个预告片,一个快速的字符串xor(42MB / s)。
def xor(a,b):
s="!%iQ%iB"%divmod(len(a),8)
return struct.pack(s,*itertools.imap(operator.xor,
struct.unpack(s,a),
struct.unpack(s,b)))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
16720 次 |
| 最近记录: |