Python中生成和使用数百万随机数的有效方法

2024-05-16 01:32:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在进行一个编程项目,这个项目涉及到Python中相当广泛的Monte Carlo模拟,因此产生了大量的随机数。几乎所有这些(如果不是全部的话)都可以由Python的内置随机模块生成。

我是个编程新手,不熟悉高效低效的做事方式。是更快地生成所有随机数作为一个列表,然后遍历该列表,还是每次调用一个函数时生成一个新的随机数,这个函数将处于一个非常大的循环中?

或者其他更聪明的方法?


Tags: 模块项目方法函数列表编程方式内置
3条回答

每次生成一个随机数。由于循环的内部工作只关心单个随机数,因此在循环内生成并使用它。

示例:

# do this:
import random

for x in xrange(SOMEVERYLARGENUMBER):
    n = random.randint(1,1000) # whatever your range of random numbers is
    # Do stuff with n

# don't do this:
import random

# This list comprehension generates random numbers in a list
numbers = [random.randint(1,1000) for x in xrange(SOMEVERYLARGENUMBER)]

for n in numbers:
    # Do stuff with n

显然,实际上这并不重要,除非你要处理数十亿次的迭代,但是如果你一次只使用一个,为什么还要费心生成所有这些数字呢?

Python内置的random模块,例如random.random()random.randint()(一些发行版也可用,您可能希望使用gaussian)可以处理大约300K个样本/s

由于您正在进行数值计算,因此可能无论如何都要使用numpy,如果您一次生成一个随机数数组,而不是一次生成一个随机数,并且可以选择更广泛的分布,那么性能会更好。60K/s*1024(阵列长度),约为60M个采样/s

您还可以在Linux和OSX上阅读/dev/urandom。我的硬件/软件(osx笔记本电脑)管理约10MB/s

当然,必须有更快的方法来集体生成随机数,例如:

from Crypto.Cipher import AES
from Crypto.Util import Counter
import secrets

aes = AES.new(secrets.token_bytes(16), AES.MODE_CTR, secrets.token_bytes(16), counter=Counter.new(128))
data = "0" * 2 ** 20
with open("filler.bin", "wb") as f:
    while True:
        f.write(aes.encrypt(data))

在单个i5-4670K内核上产生200MB/s

像aes和blowfish这样的普通密码在我的堆栈上分别管理112MB/s和70MB/s。此外,现代处理器使aes的速度更快,最高可达700MB/ssee this link to test runs on few hardware combinations。(编辑:链接断开)。您可以使用较弱的ECB模式,前提是向其提供不同的输入,并实现高达3GB/s的速度

流密码更适合这项任务,例如RC4在我的硬件上以300MB/s的速度拔得头筹,你可能会从大多数流行的密码中得到最好的结果,因为你花了更多的精力来优化它们和软件。

import random
for x in (random.randint(0,80) for x in xrange(1000*1000)):
    print x

括号之间的代码一次只能生成一个项,因此是内存安全的。

相关问题 更多 >