Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 一种生成大型随机字节数组的有效方法_Python_Random_Bytearray - Fatal编程技术网

Python 一种生成大型随机字节数组的有效方法

Python 一种生成大型随机字节数组的有效方法,python,random,bytearray,Python,Random,Bytearray,我需要创建一个特定大小的大bytearry,但在运行之前还不知道它的大小。字节需要相当随机。字节数组大小可能小到几KBs,但大到几MB。我不想逐字节迭代。这太慢了--我需要类似于numpy.random的性能。但是,我没有可用于此项目的numpy模块。在标准python安装中有什么东西可以做到这一点吗?还是我需要 对于那些询问时间的人: >>> timeit.timeit('[random.randint(0,128) for i in xrange(1,100000)]',s

我需要创建一个特定大小的大bytearry,但在运行之前还不知道它的大小。字节需要相当随机。字节数组大小可能小到几KBs,但大到几MB。我不想逐字节迭代。这太慢了--我需要类似于numpy.random的性能。但是,我没有可用于此项目的numpy模块。在标准python安装中有什么东西可以做到这一点吗?还是我需要

对于那些询问时间的人:

>>> 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
>>> 

只包括numpy有什么不对?无论如何,这将创建一个随机N位整数:

import random
N = 100000
bits = random.getrandbits(N)
因此,如果需要查看第j位的值是否已设置,可以执行
位&(2**j)=(2**j)

编辑:他要求的是字节数组而不是位数组。Ned的答案更好:
your_byte_array=bytearray((随机.getrandbits(8)表示x范围(N)中的i))

在itertools中可能有一些东西可以帮助我们,总是有


我的计时表明,这比xrange(1100000)中的i的随机.randint(0128)大约快五倍

bytearray(os.urandom(1000000))
这似乎可以按照您的需要快速执行,事实上,我的计时比您的numpy更好(尽管我们的机器可能会大不相同):


有几种可能,有些比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]
基于
b''的任何内容。join
将使用临时对象填充最终bytearray消耗的内存的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
这将以180 MB/s的速度生成伪随机数据。(没有硬件AES加速,单核)这只是上述纯python代码速度的5倍

补遗 有一个纯python加密库正在等待编写。将上述技术与hashlib和流密码技术结合在一起看起来很有希望。这里有一个提示,一个快速字符串异或(42MB/s


打开
/dev/uradom
?Python提供了一个到/dev/uradom的可移植接口:参见我的(第二个)答案。这很好。我是否错过了将long转换为bytearray或bytebuffer的一些明显的方法?无法使用NumPy,因为我的环境限制我只能使用数量非常有限的外部包。@Paul-Ned有解决方案。对不起,我的阅读理解能力很差,把它误读成了位数组。如果你想把它作为一个单行程序,你可以用bytearray((random.getrandbits(8)for i in xrange(N))KISS原则:不要导入你实际上不需要的包。查看我的计时。我正在寻找大约30-100倍的加速。在我编写的机器上,使用
random.getrandbits(8)
作为
random.randint的替代品(0,256)
的速度大约是6倍。我想补充一点,随机模块生成伪随机数据的速度比
os.urandom
快,至少在Linux上是这样。----------------------------------------
In[102]:timeit.timeit(lambda:bytearray(os.urandom(2**16)),number=100)
Out[102]:0.03401689900783822
-------------------------------------
在[103]中:timeit.timeit(lambda:(random.getrandbits(8*2**16)).to_字节(2**16,sys.byteorder),number=100)
输出[103]:0.01772290701046586
操作系统随机()
可以在Linux上阻塞。请参阅。
lambda n:(b''.join(map(struct.Struct("!Q").pack,itertools.imap(
    random.getrandbits,itertools.repeat(64,(n+7)//8)))))[:n]
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
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))
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)))