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

时间:2011-11-02 23:14:42

标签: python random

我正在进行编程项目的过程,该项目涉及Python中一些非常广泛的蒙特卡罗模拟,因此产生了大量的随机数。几乎所有这些(如果不是全部的话)都可以通过Python的内置随机模块生成。

我是一个编码新手,并且不熟悉有效率和低效率的做事方式。生成say,将所有随机数作为列表更快,然后遍历该列表,或者每次调用一个函数时生成一个新的随机数,这将是一个非常大的循环?

或者其他一些,无疑是更聪明的方法?

5 个答案:

答案 0 :(得分:4)

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

示例:

# 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

显然,实际上它并不重要,除非你正在处理数十亿甚至数十亿次迭代,但如果你一次只使用一个数字,为​​什么还要产生所有这些数字?

答案 1 :(得分:4)

Python内置random模块,例如random.random()random.randint(),(某些分布也可用,您可能需要高斯分布)大约300K样本/秒。

由于您正在进行数值计算,因此无论如何您可能使用numpy,如果您一次烹饪一个随机数字阵列而不是一次烹饪一个数字并且选择范围更广,则可以提供更好的性能。 60K / s * 1024(阵列长度),即~60M样本/秒。

您还可以在Linux和OSX上阅读/dev/urandom。我的hw / sw(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。此外,现代处理器使得速度更快,达到约700MB / s see this link to test runs on few hardware combinations。 (编辑:链接坏了)。你可以使用较弱的ECB模式,只要你输入不同的输入,并达到3GB / s。

流密码更适合于该任务,例如RC4在我的硬件上以300MB / s的速度达到最高,你可以从大多数流行的密码中获得最好的结果,因为更多的努力都用于优化这两者和软件。

答案 2 :(得分:4)

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

括号内的代码一次只生成一个项目,因此它的内存安全。

答案 3 :(得分:0)

有效且快速地生成10M随机数的代码:

import random
l=10000000
listrandom=[]
for i in range (l):
    value=random.randint(0,l)
    listrandom.append(value)
print listrandom

所花费的时间包括屏幕上打印时的I / O时间滞后:

real    0m27.116s
user    0m24.391s
sys 0m0.819s

答案 4 :(得分:0)

使用Numpy-

import numpy as np
np.random.randint(low="put the range like 1 to 100, so put '1' in 
low",high="100",size="1000000")