numpy 在python中生成1,000,000个以上随机数的最快方法

jmp7cifd  于 2023-01-13  发布在  Python
关注(0)|答案(8)|浏览(222)

我目前正在用python编写一个需要生成大量随机数的应用程序,FAST。目前我有一个使用numpy来生成大量随机数的方案(大约~500,000次)。虽然这看起来比python的实现要快。但我仍然需要它更快。有什么想法吗?我我愿意用C语言编写它,并将其嵌入到程序中,或者做它需要做的事情。
随机数的约束条件:

  • 一组7个数字,它们都可以有不同的界限:
  • 例如:[0-X1、0-X2、0-X3、0-X4、0-X5、0-X6、0-X7]
  • 目前,我正在生成一个7个数字的列表,随机值从[0 - 1),然后乘以[X1..X7]
  • 一组13个数字,加起来等于1
  • 目前只生成13个数字然后除以它们的总和

有什么想法吗?预先计算这些数字并将它们存储在文件中会使这更快吗?
谢谢!

pn9klfpd

pn9klfpd1#

你可以通过做你最初描述的事情(生成一堆随机数并相应地进行乘法和除法)来加快一点地铁站上面发布的东西。
另外,你可能已经知道了这一点,但是在处理大的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])

同样,对于“行和为1”部分...

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多少......不过,我可能错得很厉害!

swvgeqrz

swvgeqrz2#

EDIT创建了返回完整数字集的函数,而不是一次只返回一行。EDIT 2使函数更像Python(并且更快),添加第二个问题的解答

对于第一组数字,可以考虑numpy.random.randintnumpy.random.uniform,它们采用lowhigh参数,在我的2 GHz机器上,生成一个指定范围内的7 x 1,000,000个数字的数组似乎需要不到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秒。
第二盘,我采用了“乔·金斯顿”的建议。

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组数据。

dvtswwa3

dvtswwa33#

尝试r = 1664525*r + 1013904223
来自"Numerical Recipes in C"第二版中的"更快的生成器",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
xdyibdwo

xdyibdwo4#

让您的代码并行运行当然没有坏处。

7vux5j2d

7vux5j2d5#

正如其他人已经指出的,numpy是一个非常好的开始,快速,易于使用。
如果你需要大规模的随机数,可以考虑eas-ecb或者rc 4,它们都可以并行化,你应该可以达到几GB/s的性能。
可实现的数字张贴在这里

2guxujil

2guxujil6#

如果您可以访问多个内核,则可以使用dask.array并行执行计算:

import dask.array as da
x = da.random.random(size=(rows, cols)).compute()
# .compute is not necessary here, because calculations
# can continue in a lazy form and .compute is used
# on the final result
3b6akqbq

3b6akqbq7#

import random
for i in range(1000000):
print(random.randint(1, 1000000))

下面是一段Python代码,你可以用它生成100万个随机数,每行一个!

2izufjch

2izufjch8#

下面是numpy的一个简单示例:

data = numpy.random.rand(1000000)

不需要for循环,你可以传入你想生成多少个数字。

相关问题