我在numba的网站上查看了急切的编译,但不知道如何指定类型:
他们使用的例子是:
from numba import jit, int32
@jit(int32(int32, int32))
def f(x, y):
# A somewhat trivial example
return x + y
# source: http://numba.pydata.org/numba-doc/latest/user/jit.html#eager-compilation
正如您所看到的,它得到2个变量作为输入,并返回一个单独的变量。它们都应该是int32。
理解decorator的一种方法是@jit(int32(int32, int32))
可以理解为:
@jit
(type_of_returned_value
(type_of_x
,type_of_b
((
如果这是正确的(是正确的吗?(,那么如何为多个输入和输出指定它?
像这样:
@nb.jit
def filter3(a,b):
return a > b
@nb.jit
def func3(list_of_arrays_A, list_of_arrays_B, list_of_arrays_C, list_of_arrays_D, 2d_numpy_array_of_objects):
for i in range(len(list_of_arrays_A)):
for j in range(list_of_arrays_A[i].size):
if filter3(list_of_arrays_A[i][j],list_of_arrays_B[i][j]):
2d_numpy_array_of_objects[i][j] = 1
elif filter3(list_of_arrays_B[i][j],list_of_arrays_A[i][j]):
2d_numpy_array_of_objects[i][j] = 0
elif filter3(list_of_arrays_C[i][j],list_of_arrays_D[i][j]):
2d_numpy_array_of_objects[i][j] = 0
else:
2d_numpy_array_of_objects[i][j] = 1
'''
My intention: Since i need to speed up a function which is only called once, (but takes forever if **not** done with numba), I need to speed up its numba-compilation
总是可以使用numba.typeof
来干扰变量的类型。例如
import numpy as np
import numba as nb
N=10000
simple_list= [np.zeros(1) for x in range(N)]
nb.typeof(simple_list)
# reflected list(array(float64, 1d, C))
或:
from numba.typed import List
typed_list=List()
for _ in range(N):
typed_list.append(np.zeros(1))
nb.typeof(typed_list)
# ListType[array(float64, 1d, C)]
因此,您可以提前编译提供以下签名:
@nb.jit([nb.void(nb.typeof(typed_list)),
nb.void(nb.typeof(simple_list))])
def fun(lst):
pass
值得注意的细节:
- 我正在提前编译两个不同版本的函数:一个用于numba的TypedList(
nb.void(nb.typeof(typed_list)
(,另一个用于python的list(nb.void(nb.typeof(simple_list))
( - 我不使用签名字符串,而是使用签名本身(例如这里描述的(,因为如果我正确理解的话,
TypedList
或反射列表不存在签名字符串(更多信息如下( - 由于函数
fun
不返回任何内容,因此函数的返回类型为void
,因此签名中为nb.void(...)
然而,有趣的是simple_list
版本有多少额外的开销:
%timeit fun(simple_list) # 185 ms ± 4.23 ms
%timeit fun(typed_list) # 1.18 µs ± 69.3 ns
即大约CCD_ 14的因子!原因也很清楚:为了检查传递的列表是否真的是reflected list(array(float64, 1d, C))
类型,numba必须查看列表中的每个元素。另一方面,对于TypedList
,它要简单得多:列表中不能有超过一个类型——不需要迭代整个列表!
因此,人们应该更喜欢创建和使用TypedList
,而不仅仅是为了消除弃用警告。
可能不可能为reflected list
或TypedList
提供字符串,因为现在使用以下代码来解析签名:
def _parse_signature_string(signature_str):
# Just eval signature_str using the types submodules as globals
return eval(signature_str, {}, types.__dict__)
并且由于CCD_ 20没有CCD_ 21或CCD_。
一旦函数被编译(提前或及时(,就可以在相应的Dispatcher
-对象中看到签名,例如通过:
[x.signature for x in fun.overloads.values()]
# [(ListType[array(float64, 1d, C)],) -> none,
# (reflected list(array(float64, 2d, C)),) -> none]
这可以用来计算函数的右返回类型(这里none
表示void
(。