如果发生递归,numba什么时候进行实时编译



当我有一个函数在不更改类型的情况下递归调用自己,但处理一个大对象(作为参数传递(时。。。这在幕后是如何运作的?

我的函数(很小,但调用次数很多(是在第一次调用时及时编译的,但尚未完成(因为递归(,还是只有在函数的第一次调用完成时才完成编译?

例如

@njit
def myfct(large_object):
a, tail_condition = do_things_1(intermediate_result)
if tail_condition == True:
return a
intermediate_result = myfct(large_object)
b = do_things_2(a, intermediate_result)
return b
final_result = myfct(ref_to_large_object)

myfct是什么时候编译的?它是在第6行第二次被调用之前就已经编译过了,还是只有在我得到final_result并且一切都已经完成时才编译?如果是后一种情况,我该怎么避免呢?

每个签名编译一次函数。如果您没有提供显式签名,则会在第一次使用每个签名时对其进行编译:

@nb.njit
def f(n):
return n * f(n-1) if n > 1 else 1
f(4)           # Compiled here
f(5)           # Already compiled
f(5.1)         # Compiled again

如果提供显式签名,则在声明时编译函数:

@nb.njit([nb.int32(nb.int32)])
def f(n):
return n * f(n-1) if n > 1 else 1
f(5)           # Already compiled
f(5.1)         # Crashes. No attempt to compile an additional signature.

提供多个显式签名:

@nb.njit([nb.int32(nb.int32), nb.float64(nb.float64)])
def f(n):
return n * f(n-1) if n > 1 else 1
f(5)           # Already compiled
f(5.1)         # Already compiled

您可以通过在numba.core.dispatcher.Dispatcher.compile()中放置断点来自行检查。

最新更新