【问题标题】:Random sample in numbanumba 中的随机样本
【发布时间】:2020-11-19 21:34:55
【问题描述】:

出于性能原因,我经常使用 numba,而对于我的代码,我需要随机抽取样本而不进行替换。我发现,我可以为此使用 numpy.random 函数,但我注意到它与 random.sample 函数相比非常慢。难道我做错了什么?如何提高 numba 功能的性能?我将我的代码归结为这个最小的例子:

import numpy as np
import numba as nb

def func2():
    List = range(100000)
    for x in range(20000):
        random.sample(List, 10)

@nb.njit()
def func3():
    Array = np.arange(100000)
    for x in range(20000):
        np.random.choice(Array, 10, False)

print(timeit(lambda: func2(), number=1))
print(timeit(lambda: func3(), number=1))
>>>0.1196
>>>20.1245

编辑:我现在使用自己的示例函数,比 np.random.choice 快得多。

@nb.njit()
def func4():
    for x in range(20000):
        rangeList = list(range(100000))
        result = []
        for x in range(10):
            randint = random.randint(0, len(rangeList) - 1)
            result.append(rangeList.pop(randint))
        return result
print(timeit(lambda: func4(), number=count))
>>>0.1767

【问题讨论】:

  • 性能下降replace=False,尝试设置为True
  • 是的,但我想拥有它而无需更换!
  • 这不是我问题的真正答案。
  • 它解释了为什么随机样本有时比 numpys 随机选择更快。还有如何通过使用np.random.default_rng().choice 来克服这个问题。你在问你是否做错了什么,答案是:取决于

标签: python performance numba


【解决方案1】:

因为我做了一些时间测量,我想向你展示结果(关于你的问题我的 cmets)

import numpy as np
from timeit import timeit
import numba as nb
import random

def func2():
    List = range(100000)
    for x in range(1000):
        random.sample(List, 10)

@nb.njit()
def func3():
    Array = np.arange(100000)
    for x in range(1000):
        np.random.choice(Array, 10, replace=False)

def func4():
    Array = np.arange(100000)
    for x in range(1000):
        np.random.choice(Array, 10, replace=False)

def func5():
    Array = np.arange(100000)
    for x in range(1000):
        np.random.default_rng().choice(Array, 10, replace=False)

print(f"random.sample {timeit(lambda: func2(), number=1)}")
print(f"np.random.choice JIT incl. compiling {timeit(lambda: func3(), number=1)}")
print(f"np.random.choice JIT excl. compiling {timeit(lambda: func3(), number=1)}")
print(f"np.random.choice {timeit(lambda: func4(), number=1)}")
print(f"np.random.default_rng.choice {timeit(lambda: func5(), number=1)}")

给你:

random.sample 0.0090606
np.random.choice JIT incl. compiling 1.9129443
np.random.choice JIT excl. compiling 0.8365084999999999
np.random.choice 1.8339632999999997
np.random.default_rng.choice 0.049018499999999854

【讨论】:

  • 我也注意到了,但如果我没有做错任何事情,有没有办法提高我的 numba 函数的性能?
  • 我认为这真的取决于你的实际用例来优化这个..
  • 如果我不使用 numba,我的代码的其余部分会很慢......
  • 是的,所以您使用np.random.choice 来解决上述问题?还是还有更多?
  • 目前我的代码工作方式不同,但原则上能够有效地使用 np.random.choice / random.sample,应该会显着加快我的代码。我想我现在将看看 random.sample 是如何编码的,然后检查我是否可以更改该函数以使用 numba。
猜你喜欢
  • 2012-01-31
  • 1970-01-01
  • 1970-01-01
  • 2018-11-02
  • 1970-01-01
  • 1970-01-01
  • 2020-09-08
  • 2018-10-24
  • 2012-10-14
相关资源
最近更新 更多