Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/google-apps-script/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么非独立numba jitt';教育职能重要吗?_Python_Jit_Numba - Fatal编程技术网

Python 为什么非独立numba jitt';教育职能重要吗?

Python 为什么非独立numba jitt';教育职能重要吗?,python,jit,numba,Python,Jit,Numba,在python中,您可以定义多个以任意顺序相互调用的函数,并且在运行时将调用这些函数。一旦这些函数存在,它们在脚本中定义的顺序就无关紧要了。例如,下面的选项是有效的,可以使用 import numpy as np def func1(arr): out = np.empty_like(arr) for i in range(arr.shape[0]): out[i] = func2(arr[i]) # calling func2 here which is d

在python中,您可以定义多个以任意顺序相互调用的函数,并且在运行时将调用这些函数。一旦这些函数存在,它们在脚本中定义的顺序就无关紧要了。例如,下面的选项是有效的,可以使用

import numpy as np

def func1(arr):
    out = np.empty_like(arr)
    for i in range(arr.shape[0]):
        out[i] = func2(arr[i])  # calling func2 here which is defined below
    return out

def func2(a):
    out = a + 1
    return out
func1
可以调用
func2
,即使
func2
是在
func1
之后定义的

然而,如果我用修饰这些函数,我会得到一个错误

import numpy as np
import numba as nb


@nb.jit("f8[:](f8[:])", nopython=True)
def func1(arr):
    out = np.empty_like(arr)
    for i in range(arr.shape[0]):
        out[i] = func2(arr[i])
    return out

@nb.jit("f8(f8)", nopython=True)
def func2(a):
    out = a + 1
    return out

>>> TypingError: Failed in nopython mode pipeline (step: nopython frontend)
    Untyped global name 'func2': cannot determine Numba type of <class 
    'numba.ir.UndefinedType'>

为什么会这样?我觉得纯python模式可以工作,因为python是动态类型化的,而不是编译的,而numba使用JIT,根据定义编译函数(因此可能需要对每个函数中发生的一切都有全面的了解?)。但我不明白,如果numba遇到一个它没有看到的函数,为什么它不在范围内搜索所有函数。

短版本-删除
“f8[:](f8[:])”

你的直觉是对的。Python函数是在调用时查找的,这就是为什么它们可以无序定义的原因。使用
dis
(反汇编)模块查看python字节码可以清楚地表明这一点-每次调用函数
a
时,都会将名称
b
作为全局查找

def a():
    return b()

def b():
    return 2

import dis
dis.dis(a)
#  2           0 LOAD_GLOBAL              0 (b)
#              2 CALL_FUNCTION            0
#              4 RETURN_VALUE
在nopython模式下,numba需要静态地知道被调用的每个函数的地址——这使代码变得快速(不再执行运行时查找),同时也为其他优化打开了大门,如内联


也就是说,numba可以处理这个案子。通过指定类型签名(
“f8[:]”(f8[:])“
),可以强制提前编译。省略它,一个数字将根据第一个函数调用它,它将工作。

感谢您的解释。我确实注意到,省略签名(但仍然用jit装饰函数)似乎是可行的。但是,对于我的用例,我将保留签名,因为我希望在开始对函数进行操作之前获得正确的错误消息,以防将某些不正确的类型传递给函数。再次感谢@PyRsquared还请注意,显式声明非连续数组[:]通常会阻止SIMD矢量化,并可能导致运行时变慢(只需将
out=a+1
替换为
out=np.sin(a)
,即可看到相当明显的效果。但如果显式声明连续数组[::1]该函数在非连续数组上不再工作。@max9111非常好的观察,谢谢!因此,在本例中,为了获得最佳性能(使用SIMD),您建议使用
f[::1]
?我不完全确定numpy数组在内存中的存储方式,但是对于@PyRsquared,您可以使用ndarray.flags(例如A=B[0:-1:2])检查这些内容->A是B)上的非连续视图。您必须选择它。如果您可以将函数限制为连续数组…另一种可能是使用np.ASCONTIGOUUSARRAY,但这有复制数组的缺点。有时您需要显式创建连续副本,例如,有时不需要。这取决于算法。。。
def a():
    return b()

def b():
    return 2

import dis
dis.dis(a)
#  2           0 LOAD_GLOBAL              0 (b)
#              2 CALL_FUNCTION            0
#              4 RETURN_VALUE