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 的原始错误和/或解决方法有任何见解?
答案很晚,但问题是 Numba不支持Numpy 的RandomState对象(截至 2019 年 7 月)。它也不支持使用Python 标准库设置随机状态。
但是,鉴于Numba 支持,您可以通过将参数传递到函数中,然后调用其中的方法np.random.seed,在 jitted 函数中使用 numpy 的 PRNG 。来自Numba 文档:seednp.random.seed(seed)
\n\nNumba 支持 numpy.random 模块中的顶级函数,但不允许您创建单独的 RandomState 实例。\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)\nRun Code Online (Sandbox Code Playgroud)\n哪个应该产生:
\n0.2620246750155817\nRun Code Online (Sandbox Code Playgroud)\n如果您希望每个类实例具有不同的随机状态,则需要为每个类拥有一个单独的线程,因为 PRNG 与实例化它们的线程相关联。幸运的是,Numba 会自动处理此问题每个类都发生在自己的线程中:
\n\n\n从 0.28.0 版本开始,生成器是线程安全和分叉安全的。每个线程和每个进程都会产生独立的随机数流。
\n
最后,如果您的目标是 CUDA,有许多方法可以让您直接使用支持 GPU 的 PRNG,这可能会很方便。请参阅Numba 文档中的此页面。
\n