在Python中高效生成和使用百万随机数的方法
我正在做一个编程项目,这个项目需要用Python进行大量的蒙特卡罗模拟,也就是需要生成很多随机数。几乎所有的随机数,甚至可以说是全部,都可以通过Python自带的随机模块来生成。
我对编程还不太熟悉,不太了解哪些方法高效,哪些方法低效。比如说,是先生成一个随机数的列表,然后再遍历这个列表更快,还是每次调用函数时都生成一个新的随机数,这个函数会在一个很大的循环中被调用?
或者有没有其他更聪明的方法呢?
5 个回答
Python自带的random
模块,比如random.random()
和random.randint()
,可以每秒生成大约30万次随机数。
因为你可能在做数值计算,所以你很可能会用到numpy
。它的性能更好,如果你一次生成一个数组的随机数,而不是一个一个地生成。这样的话,速度可以达到每秒60千次乘以1024(数组长度),大约是每秒6000万次。
在Linux和OSX上,你也可以读取/dev/urandom
。我的硬件和软件(OSX笔记本)大约能达到每秒10MB。
肯定还有更快的方法可以大量生成随机数,比如:
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。
一些常见的加密算法,比如AES和Blowfish,在我的设备上分别能达到每秒112MB和70MB。此外,现代处理器让AES的速度更快,能达到每秒700MB。你可以查看这个链接,了解在几种硬件组合上的测试结果(链接已失效)。如果你使用较弱的ECB模式,只要输入不同的数据,速度可以达到每秒3GB。
流密码更适合这个任务,比如RC4在我的硬件上能达到每秒300MB,使用最流行的加密算法通常能得到更好的结果,因为这些算法在优化上投入了更多的精力。
import random
for x in (random.randint(0,80) for x in xrange(1000*1000)):
print x
括号里面的代码一次只会生成一个项目,所以它在内存使用上是安全的。
每次都生成一个随机数。因为循环内部只关心一个随机数,所以在循环里生成并使用这个随机数。
举个例子:
# 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
显然,从实际的角度来看,这真的没什么关系,除非你要处理数十亿次的循环。但是,如果你一次只用一个随机数,为什么要费力去生成那么多个呢?