今天花费了很多时间在想办法提高Python的随机数生成的速度,因为我需要生成clickhouse的测试数据。
我每生成1亿行数据,每行包括2个随机的uint32,1个uint16,1个uint8和一个随机时间,花费的时间大约在60分钟左右。
1.random.randint
我最初生成uint32的代码长成这样:
import random
UINT32upBound=0xffffffff
for i in range(0,10**4):
random.randint(0,UINT32upBound)
真的太慢了。
2./dev/urandom->os.urandom
然后我想到使用Linux系统的/dev/urandom
,这是系统自带的随机数生成器,应该比较快。
参考网址:How to get numbers from /dev/random using Python? - Stack Overflow
随后我把代码修改了:
import os
for i in range(0,10**4):
int(os.urandom(4).hex(),16)
确实有少量的提速,但不明显。
然后我看到问答:unix - Creating a large file of random bytes quickly - Super User
和:encryption - Fast Way to Randomize HD? - Unix & Linux Stack Exchange
里面提到/dev/urandom
生成随机数的速度确实不够快,更快的方法是使用openssl的AES算法,但不能在Python中使用。
dd if=<(openssl enc -aes-256-ctr -pass pass:"$(dd if=/dev/urandom bs=128 count=1 2>/dev/null | base64)" -nosalt < /dev/zero) of=filename bs=1M count=100 iflag=fullblock
3.fastrand ×
然后我找到一个放在GitHub上的Python库:lemire/fastrand: Fast random number generation in Python (using PCG)
我尝试了,还是不够快。
4.numpy
随后我看到了另外一个回答:Efficient way to generate and use millions of random numbers in Python - Stack Overflow
里面提到了:random.random()只有300k/s,/dev/urandom有10M/S,如果使用numpy进行大规模生成,速度可以达到60M/S。
然后我就使用numpy:
import numpy as np
l= np.random.randint(low=-2147483648, high=0x7FFFFFFF, size=10**4)
for i in range(0,10**4):
l[i]+2147483648
注意:np.random.random_integers方法被弃用了
这里说明一下,0x7FFFFFFF是int32的最大值,-2147483648是int32的最小值。
因为我需要uint32的随机数,但randint函数只能生成int32范围的随机数,所以在结果处加上int32的min值-2147483648。
上面的代码速度非常快。