将 Numba jitclass 与来自字典和元组的输入一起使用
Using Numba jitclass with input from dicts and tuples
我正在努力优化我拥有的一些代码,这些代码大部分包含在单个 python class 中。它对 python 对象的操作很少,所以我认为使用 Numba 会是一个很好的匹配,但是我在创建对象的过程中需要大量的参数,而且我不认为我完全理解 Numba 的相对较新的字典支持 (documentation here)。我拥有的参数都是单个浮点数或整数,并被传递到对象中,存储起来,然后在整个 运行 代码中使用,如下所示:
import numpy as np
from numba import jitclass, float64
spec = [
('p', dict),
('shape', tuple), # the shape of the array
('array', float64[:,:]), # an array field
]
params_default = {
par_1 = 1,
par_2 = 0.5
}
@jitclass(spec)
class myObj:
def __init__(self,params = params_default,shape = (100,100)):
self.p = params
self.shape = shape
self.array = self.p['par_2']*np.ones(shape)
def inc_arr(self):
self.array += self.p['par_1']*np.ones(shape)
有很多我认为我不了解 Numba 为此需要什么。如果我想使用 nopython 模式使用 Numba 对此进行优化,是否需要将规范传递给 jitclass 装饰器?如何定义字典的规范?我还需要声明形状元组吗?我查看了在 jitclass 装饰器上找到的 documentation 以及 dict numba 文档,但我不确定该怎么做。当我 运行 上述代码时,出现以下错误:
TypeError: spec values should be Numba type instances, got <class 'dict'>
我是否需要以某种方式在规范中包含 dict 元素?从文档中不清楚正确的语法是什么。
或者,有没有办法让 Numba 推断输入类型?
spec
需要numba-specific类型组成,而不是python类型!
所以规范中的 tuple
和 dict
必须是 typed numba 类型(而且 afaik 只允许同质字典)。
所以要么你在一个 jitted 函数中指定你的 params_default
dict,如图 here or you explicitly type a numba dict as shown here.
对于这种情况,我将采用后一种方法:
import numpy as np
from numba import jitclass, float64
# Explicitly define the types of the key and value:
params_default = nb.typed.Dict.empty(
key_type=nb.typeof('par_1'),
value_type=nb.typeof(0.5)
)
# assign your default values
params_default['par_1'] = 1. # Same type required, thus setting to float
params_default['par_2'] = .5
spec = [
('p', nb.typeof(params_default)),
('shape', nb.typeof((100, 100))), # the shape of the array
('array', float64[:, :]), # an array field
]
@jitclass(spec)
class myObj:
def __init__(self, params=params_default, shape=(100, 100)):
self.p = params
self.shape = shape
self.array = self.p['par_2'] * np.ones(shape)
def inc_arr(self):
self.array += self.p['par_1'] * np.ones(shape)
正如已经指出的那样:据我所知,字典是同类类型的。因此所有 keys/values 必须属于同一类型。所以将 int
和 float
存储在同一个字典中是行不通的。
我正在努力优化我拥有的一些代码,这些代码大部分包含在单个 python class 中。它对 python 对象的操作很少,所以我认为使用 Numba 会是一个很好的匹配,但是我在创建对象的过程中需要大量的参数,而且我不认为我完全理解 Numba 的相对较新的字典支持 (documentation here)。我拥有的参数都是单个浮点数或整数,并被传递到对象中,存储起来,然后在整个 运行 代码中使用,如下所示:
import numpy as np
from numba import jitclass, float64
spec = [
('p', dict),
('shape', tuple), # the shape of the array
('array', float64[:,:]), # an array field
]
params_default = {
par_1 = 1,
par_2 = 0.5
}
@jitclass(spec)
class myObj:
def __init__(self,params = params_default,shape = (100,100)):
self.p = params
self.shape = shape
self.array = self.p['par_2']*np.ones(shape)
def inc_arr(self):
self.array += self.p['par_1']*np.ones(shape)
有很多我认为我不了解 Numba 为此需要什么。如果我想使用 nopython 模式使用 Numba 对此进行优化,是否需要将规范传递给 jitclass 装饰器?如何定义字典的规范?我还需要声明形状元组吗?我查看了在 jitclass 装饰器上找到的 documentation 以及 dict numba 文档,但我不确定该怎么做。当我 运行 上述代码时,出现以下错误:
TypeError: spec values should be Numba type instances, got <class 'dict'>
我是否需要以某种方式在规范中包含 dict 元素?从文档中不清楚正确的语法是什么。
或者,有没有办法让 Numba 推断输入类型?
spec
需要numba-specific类型组成,而不是python类型!
所以规范中的 tuple
和 dict
必须是 typed numba 类型(而且 afaik 只允许同质字典)。
所以要么你在一个 jitted 函数中指定你的 params_default
dict,如图 here or you explicitly type a numba dict as shown here.
对于这种情况,我将采用后一种方法:
import numpy as np
from numba import jitclass, float64
# Explicitly define the types of the key and value:
params_default = nb.typed.Dict.empty(
key_type=nb.typeof('par_1'),
value_type=nb.typeof(0.5)
)
# assign your default values
params_default['par_1'] = 1. # Same type required, thus setting to float
params_default['par_2'] = .5
spec = [
('p', nb.typeof(params_default)),
('shape', nb.typeof((100, 100))), # the shape of the array
('array', float64[:, :]), # an array field
]
@jitclass(spec)
class myObj:
def __init__(self, params=params_default, shape=(100, 100)):
self.p = params
self.shape = shape
self.array = self.p['par_2'] * np.ones(shape)
def inc_arr(self):
self.array += self.p['par_1'] * np.ones(shape)
正如已经指出的那样:据我所知,字典是同类类型的。因此所有 keys/values 必须属于同一类型。所以将 int
和 float
存储在同一个字典中是行不通的。