我目前正在python中编写一个需要生成大量随机数的应用程序.FAST。目前我有一个方案,使用numpy生成一个巨大的批次中的所有数字(一次大约约500,000)。虽然这似乎比python的实现更快。我仍然需要它更快。有任何想法吗?我愿意用C语言编写它并将其嵌入到程序中或者用它来完成它。
对随机数的限制:
有什么想法吗?预先计算这些数字并将它们存储在一个文件中会使这更快吗?
谢谢!
答案 0 :(得分:12)
你可以通过做你最初描述的内容(生成一堆随机数并相应地乘以和除以),从mtrw上面的内容中加快一点速度......
此外,您可能已经知道这一点,但在使用大型numpy数组时,请确保就地执行操作(* =,/ =,+ =等)。它使大型阵列的内存使用量产生巨大差异,同时也会提高速度。
In [53]: def rand_row_doubles(row_limits, num):
....: ncols = len(row_limits)
....: x = np.random.random((num, ncols))
....: x *= row_limits
....: return x
....:
In [59]: %timeit rand_row_doubles(np.arange(7) + 1, 1000000)
10 loops, best of 3: 187 ms per loop
与:相比:
In [66]: %timeit ManyRandDoubles(np.arange(7) + 1, 1000000)
1 loops, best of 3: 222 ms per loop
这不是一个巨大的差异,但如果你真的担心速度,那就是它。
只是为了表明它是正确的:
In [68]: x.max(0)
Out[68]:
array([ 0.99999991, 1.99999971, 2.99999737, 3.99999569, 4.99999836,
5.99999114, 6.99999738])
In [69]: x.min(0)
Out[69]:
array([ 4.02099599e-07, 4.41729377e-07, 4.33480302e-08,
7.43497138e-06, 1.28446819e-05, 4.27614385e-07,
1.34106753e-05])
同样,对于你的“行总和为一部分”......
In [70]: def rand_rows_sum_to_one(nrows, ncols):
....: x = np.random.random((ncols, nrows))
....: y = x.sum(axis=0)
....: x /= y
....: return x.T
....:
In [71]: %timeit rand_rows_sum_to_one(1000000, 13)
1 loops, best of 3: 455 ms per loop
In [72]: x = rand_rows_sum_to_one(1000000, 13)
In [73]: x.sum(axis=1)
Out[73]: array([ 1., 1., 1., ..., 1., 1., 1.])
老实说,即使你在C中重新实现了一些东西,我也不确定你能不能在这个问题上打败numpy ......但我可能会非常错误!
答案 1 :(得分:6)
编辑创建的函数返回完整的数字集,而不是一次只返回一行。 编辑2 使功能更加pythonic(和更快),为第二个问题添加解决方案
对于第一组数字,您可以考虑numpy.random.randint
或numpy.random.uniform
,其中包含low
和high
个参数。在指定范围内生成7 x 1,000,000个数字的数组似乎需要<我的2 GHz机器上0.7秒:
def LimitedRandInts(XLim, N):
rowlen = (1,N)
return [np.random.randint(low=0,high=lim,size=rowlen) for lim in XLim]
def LimitedRandDoubles(XLim, N):
rowlen = (1,N)
return [np.random.uniform(low=0,high=lim,size=rowlen) for lim in XLim]
>>> import numpy as np
>>> N = 1000000 #number of randoms in each range
>>> xLim = [x*500 for x in range(1,8)] #convenient limit generation
>>> fLim = [x/7.0 for x in range(1,8)]
>>> aa = LimitedRandInts(xLim, N)
>>> ff = LimitedRandDoubles(fLim, N)
返回[0,xLim-1]中的整数或[0,fLim]中的浮点数。在我的2 GHz单核机器上整数版需要~0.3秒,双倍~0.66。
对于第二组,我使用了@Joe Kingston的建议。
def SumToOneRands(NumToSum, N):
aa = np.random.uniform(low=0,high=1.0,size=(NumToSum,N)) #13 rows by 1000000 columns, for instance
s = np.reciprocal(aa.sum(0))
aa *= s
return aa.T #get back to column major order, so aa[k] is the kth set of 13 numbers
>>> ll = SumToOneRands(13, N)
这需要约1.6秒。
在所有情况下,result[k]
都会为您提供第k组数据。
答案 2 :(得分:4)
尝试r = 1664525*r + 1013904223
从“更快的发电机”
在“Numerical Recipes in C”第2版,Press等人,isbn 0521431085,p。 284.
np.random当然“更随机”;看到
Linear congruential generator。
在python中,像这样使用np.uint32
:
python -mtimeit -s '
import numpy as np
r = 1
r = np.array([r], np.uint32)[0] # 316 py -> 16 us np
# python longs can be arbitrarily long, so slow
' '
r = r*1664525 + 1013904223 # NR2 p. 284
'
一次生成大块:
# initialize --
np.random.seed( ... )
R = np.random.randint( 0, np.iinfo( np.uint32 ).max, size, dtype=np.uint32 )
...
R *= 1664525
R += 1013904223
答案 3 :(得分:1)
让你的代码并行运行肯定不会受到伤害。尝试使用Parallel Python
为SMP进行调整答案 4 :(得分:1)
正如其他人已经指出的那样,numpy
是一个非常好的开始,快速且易于使用。
如果您需要大规模的随机数,请考虑eas-ecb或rc4。两者都可以并行化,你应该达到几GB / s的性能。
答案 5 :(得分:-1)
只是行动中numpy
的一个简单示例:
data = numpy.random.rand(1000000)
无需循环,您可以传入要生成的数量。