相对于我的纯python图论库中的类似MATLAB代码,我遇到了时间性能非常差的函数,所以我试图在这个函数中分析一些操作。
我跟踪了以下结果
In [27]: timeit.timeit( 'permutation(138)[:4]', setup='from numpy.random import permutation', number=1000000)
Out[27]: 27.659916877746582
将其与MATLAB中的性能进行比较
>> tic; for i=1:1000000; randperm(138,4); end; toc
Elapsed time is 4.593305 seconds.
我可以将此更改为np.random.choice
,而不是像我原先写的那样np.random.permutation
,从而大大提高了效果。
In [42]: timeit.timeit( 'choice(138, 4)', setup='from numpy.random import choice', number=1000000)
Out[42]: 18.9618501663208
但它仍然没有接近matlab的性能。
在纯python中是否有另一种获取此行为的方法,时间性能接近MATLAB时间性能?
答案 0 :(得分:3)
根据this solution
显示如何使用基于argsort
/ argpartition
的技巧模拟np.random.choice(..., replace=False)
的行为,您可以重新创建MATLAB的randperm(138,4)
,即NumPy的np.random.choice(138,4, replace=False)
,np.argpartition
为:
np.random.rand(138).argpartition(range(4))[:4]
或np.argsort
喜欢这样 -
np.random.rand(138).argsort()[:4]
让我们将这两个版本用于与MATLAB版本进行性能比较。
在MATLAB上 -
>> tic; for i=1:1000000; randperm(138,4); end; toc
Elapsed time is 1.058177 seconds.
使用np.argpartition
-
In [361]: timeit.timeit( 'np.random.rand(138).argpartition(range(4))[:4]', setup='import numpy as np', number=1000000)
Out[361]: 9.063489798831142
使用np.argsort
-
In [362]: timeit.timeit( 'np.random.rand(138).argsort()[:4]', setup='import numpy as np', number=1000000)
Out[362]: 5.74625801707225
最初建议使用NumPy -
In [363]: timeit.timeit( 'choice(138, 4)', setup='from numpy.random import choice', number=1000000)
Out[363]: 6.793723535243771
似乎可以使用np.argsort
来提高边际绩效。
答案 1 :(得分:2)
这需要多长时间?我估计1-2秒。
def four():
k = np.random.randint(138**4)
a = k % 138
b = k // 138 % 138
c = k // 138**2 % 138
d = k // 138**3 % 138
return (a, b, c, d) if a != b and a != c and a != d and b != c and b != d and c != d else four()
更新1:首先我使用random.randrange
,但np.random.randint
使整个事情的速度提高了一倍。
更新2:由于NumPy的随机功能似乎要快得多,我试过这个,这是另一个因素〜1.33更快:
>>> def four():
a = randint(138)
b = randint(138)
c = randint(138)
d = randint(138)
return (a, b, c, d) if a != b and a != c and a != d and b != c and b != d and c != d else four()
>>> import timeit
>>> from numpy.random import randint
>>> timeit.timeit(lambda: four(), number=1000000)
2.3742770821572776
这比原版快22倍:
>>> timeit.timeit('permutation(138)[:4]', setup='from numpy.random import permutation', number=1000000)
51.80568455893672
(字符串vs lambda
没有明显区别)