尝试实例化 NumPy RandomState 时出现 Numba 错误

Com*_*con 5 python numpy numba

我有一门课,我想用 Numba 加速。该类通过简单地使用特定种子创建 NumPy 的 RandomState 实例为每个实例使用“随机数生成器”(因此我可以稍后复制我的工作)。当我使用 Numba 的 autojit 时,我收到一个奇怪的错误,这在“常规”Python 中不会出现。

幸运的是,这种行为非常容易复制。这是一个说明错误的简单示例:

from numpy.random import RandomState
from numba import autojit

# ------- This works in "regular Python" ------------

class SillyClass1(object):
    def __init__(self, seed):
        self.RNG = RandomState(seed)
    def draw_uniform(self):
        return self.RNG.uniform(0,1)

test1 = SillyClass1(123456)

test1.draw_uniform()

# Output:
# 0.12696983303810094


# The following code -- exactly the same as above, but with the @autojit 
# decorator, doesn't work, and throws an error which I am having a hard  
# time understanding how to fix:

@autojit
class SillyClass2(object):
    def __init__(self, seed):
        self.RNG = RandomState(seed)
    def draw_uniform(self):
        return self.RNG.uniform(0,1)

test2 = SillyClass2(123456)

test2.draw_uniform()

# Output:
#
# ValueError                                Traceback (most recent call last)
# <ipython-input-86-a18f95c11a1b> in <module>()
#      10 
#      11 
# ---> 12 test2 = SillyClass2(123456)
#      13 
#      14 test2.draw_uniform()
# 
# ...
# 
# ValueError: object of too small depth for desired array
Run Code Online (Sandbox Code Playgroud)

我在 Ubuntu 13.10 上使用 Anaconda 发行版。

有什么想法吗?

编辑:我找到了一种解决方法,即简单地使用 Python 的标准“random.Random”而不是 NumPys 的“numpy.random.RandomState”

例子:

from random import Random 
@autojit
class SillyClass3(object):
    def __init__(self, seed):
        self.RNG = Random(seed)
    def draw_uniform(self):
        return self.RNG.uniform(0,1)

test3 = SillyClass3(123456)

test3.draw_uniform()

# Output:
# 0.8056271362589
Run Code Online (Sandbox Code Playgroud)

这适用于我的直接应用程序(尽管其他问题立即出现,万岁)。

但是,此修复不适用于我知道我需要使用 numpy.random.RandomState 的未来算法。所以我的问题仍然存在——有没有人对在 Numba 中使用 numy.random.RandomState 的原始错误和/或解决方法有任何见解?

Gre*_*ick 1

答案很晚,但问题是 Numba不支持Numpy 的RandomState对象(截至 2019 年 7 月)。它也不支持使用Python 标准库设置随机状态。

\n

但是,鉴于Numba 支持,您可以通过将参数传递到函数中,然后调用其中的方法np.random.seed,在 jitted 函数中使用 numpy 的 PRNG 。来自Numba 文档seednp.random.seed(seed)

\n
\n

Numba 支持 numpy.random 模块中的顶级函数,但不允许您创建单独的 RandomState 实例。\n与标准随机模块使用相同的算法(因此适用相同的注释),但具有独立的内部状态:从一个生成器播种或抽取数字不会影响另一个生成器。

\n
\n

代码示例

\n
import random, numba, numpy\n\n@numba.njit\ndef random_func(seed: int = 1234) -> str:\n    seeded_prng = numpy.random.seed(seed)\n    # Do random stuff\n    random_computation = numpy.random.uniform(0, 1)\n    return random_computation\n\n# Example Invocation\nseed = 1337\nrandom_result = random_func(seed)\nprint(random_result)\n
Run Code Online (Sandbox Code Playgroud)\n

哪个应该产生:

\n
0.2620246750155817\n
Run Code Online (Sandbox Code Playgroud)\n

如果您希望每个类实例具有不同的随机状态,则需要为每个类拥有一个单独的线程,因为 PRNG 与实例化它们的线程相关联。幸运的是,Numba 会自动处理此问题每个类都发生在自己的线程中:

\n
\n

从 0.28.0 版本开始,生成器是线程安全和分叉安全的。每个线程和每个进程都会产生独立的随机数流。

\n
\n

最后,如果您的目标是 CUDA,有许多方法可以让您直接使用支持 GPU 的 PRNG,这可能会很方便。请参阅Numba 文档中的此页面。

\n