Python布朗运动模拟:如何快速生成大量[-1,1]随机数?
如何高效生成大量[-1, 1]范围内的随机数?
我尝试生成大量属于集合[-1, 1]的随机数,发现np.random.Generator.choice是效率最差的方法,而最优方法是使用np.random.Generator.random并通过布尔值转整数实现。我想知道是否存在更优的大量生成此类随机数的方式?
我需要在网格中模拟m个粒子在d维带反射面封闭容器内的运动,共进行n次迭代,每次迭代后需检测碰撞条件。为简化问题,假设d=2。由于采用网格模型,粒子的运动可简化为生成-1和+1。目前我逐个处理粒子,生成随机数后逐个访问,且随系统内粒子数量减少,生成的随机数也相应减少(此部分可优化,但非本次问询重点)。
本次核心问题是:如何最快生成大量属于集合[-1,1]的随机数?
我测试了五种方法,四种基于NumPy,一种基于random模块:
- 使用
np.random.Generator.choice([-1,1],size=(m,2)),耗时595.6秒:
n=int(5e6) m=1000 rng=np.random.default_rng() tic=time.time() for i in range(n): a=rng.choice([-1,1], size=(m,2)) for j in range(m): #此无用循环用于演示我会逐行访问数据 b=a[j] print("choice",time.time()-tic)
- 通过均匀分布[0,1)转换为-1和+1,代码为
(rng.random(size=(m,2))>0.5+0)*2-1,耗时527.6秒(注:+0用于将True转为1,False转为0):
n=int(5e6) m=1000 rng=np.random.default_rng() tic=time.time() for i in range(n): a=(rng.random(size=(m,2))>0.5+0)*2-1 for j in range(m): b=a[j] print("operate",time.time()-tic)
- 使用
np.sign实现类似逻辑,代码为np.sign(rng.random(size=(m,2))-0.5),耗时543.5秒:
n=int(5e6) m=1000 rng=np.random.default_rng() tic=time.time() for i in range(n): a=np.sign(rng.random(size=(m,2))-0.5) for j in range(m): b=a[j] print("sign",time.time()-tic)
- 使用
np.random.Generator.integers并做额外处理,代码为(rng.integers(2,size=(m,2))*2)-1,耗时553.8秒:
n=int(5e6) m=1000 rng=np.random.default_rng() tic=time.time() for i in range(n): a=(rng.integers(2,size=(m,2))*2)-1 for j in range(m): b=a[j] print("integer",time.time()-tic)
- 现场使用
random.random()生成,耗时约750秒,效率极低。
令我困惑的是,rng.choice()效率远低于预期,虽已知其在小集合表现不佳,但因m较大本以为会有所改善;同时布尔值转整数的方法效率最高也出乎预料。因此我想请教:生成m*d个属于[-1,1]的随机数的最快方式是什么?是我测试过的方法之一,还是有遗漏的更优方案?
内容的提问来源于stack exchange,提问作者ck1987pd
相关产品推荐
相关产品推荐

