我在python中有以下代码:
results=[]
for i in range(1,7000000):
a=(random.sample(range(1, 45), 6))
results.append(a)
有没有办法可以使用线程或任何其他方法来使代码运行得更快?目前,它只需要20多分钟。
答案 0 :(得分:1)
由于the GIL,这里的线程化并没有太大的好处,但这是一个可以用numpy
解决的问题,它可以完全在C层执行工作,从而节省大量的时间和内存来启动。可以在不到一秒的时间内创建具有给定范围值的7M乘6大小的2D阵列:
import numpy as np
results = np.random.randint(1, 45, (7000000, 6), np.uint8)
这一般会更快,内存效率更高;一个7M长的list
六 - tuple
s(在64位版本的Python上)占用绝对最小值约700 MB(可能更多,给定分配器开销)。 numpy
数组将占用大约40 MB。同样很容易证明,创建具有所有内部list
的{{1}}具有不可避免的成本;单独对tuple
数组进行微基准测试表明,所有随机数生成仅需要大约420 ms,但是从numpy
数组转换为numpy
六 - list
s最有效的方式使成本高达12.5秒;如果你的机器与我的机器类似,那么它实际上是任何纯Python解决方案性能的上限,因为它是Python支付的原始成本,用于创建tuple
并填充{{ 1}}:
tuple
list
比>>> %timeit -r5 arr = np.random.randint(1, 45, (7000000, 6), np.uint8)
420 ms ± 875 µs per loop (mean ± std. dev. of 5 runs, 1 loop each)
>>> %timeit -r5 arr = list(map(tuple, np.random.randint(1, 45, (7000000, 6), np.uint8)))
12.5 s ± 254 ms per loop (mean ± std. dev. of 5 runs, 1 loop each)
更快(大约需要2.5秒),但是再次,这是唯一可能的,因为C级加速器辅助(并且它会使用更多的内存,这要归功于{{1内存效率稍差一点。)
如果没有np.random.randint(1, 45, (7000000, 6), np.uint8).tolist()
,我建议的最好方法就是避免一遍又一遍地重新创建list(map(tuple, ...))
,在循环外创建一次并重复使用它,例如:
list
但这不太可能挽救很多; numpy
模块执行了大量的Python级别的工作,包含了1-2个C级随机生成器,并且Python级别的工作将比完全加速的C模块的任何东西慢得多 做。