Python 无效使用参数类型为的函数
我使用的是Numba nonpython模式和一些NumPy函数Python 无效使用参数类型为的函数,python,numpy,numba,Python,Numpy,Numba,我使用的是Numba nonpython模式和一些NumPy函数 @njit def反转(W,复制=真): ''' 按元素反转输入连接矩阵中的权重。 换句话说,将节间强度矩阵更改为 节间距离矩阵。 如果未设置复制,此功能将*就地修改W* 参数 ---------- W:np.Ndaray 加权连通矩阵 抄送:布尔 退换商品 ------- W:np.Ndaray 逆连通矩阵 ''' 如果是副本: W=W.copy() E=np,其中(W) W[E]=1./W[E] 返回W 在此函数中,W是一个
@njit
def反转(W,复制=真):
'''
按元素反转输入连接矩阵中的权重。
换句话说,将节间强度矩阵更改为
节间距离矩阵。
如果未设置复制,此功能将*就地修改W*
参数
----------
W:np.Ndaray
加权连通矩阵
抄送:布尔
退换商品
-------
W:np.Ndaray
逆连通矩阵
'''
如果是副本:
W=W.copy()
E=np,其中(W)
W[E]=1./W[E]
返回W
在此函数中,W
是一个矩阵。但是我犯了以下错误。它可能与W[E]=1有关W[E]
行
File "/Users/xxx/anaconda3/lib/python3.7/site-packages/numba/dispatcher.py", line 317, in error_rewrite
reraise(type(e), e, None)
File "/Users/xxx/anaconda3/lib/python3.7/site-packages/numba/six.py", line 658, in reraise
raise value.with_traceback(tb)
numba.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend)
Invalid use of Function(<built-in function getitem>) with argument(s) of type(s): (array(float64, 2d, A), tuple(array(int64, 1d, C) x 2))
文件“/Users/xxx/anaconda3/lib/python3.7/site packages/numba/dispatcher.py”,第317行,错误\u重写
重放(类型(e),e,无)
文件“/Users/xxx/anaconda3/lib/python3.7/site-packages/numba/six.py”,第658行,重新播放
通过_回溯(tb)提升值
numba.errors.TypingError:在nopython模式管道中失败(步骤:nopython前端)
函数()与类型为(数组(float64,2d,A)、元组(数组(int64,1d,C)x 2)的参数一起使用无效
那么,使用NumPy和Numba的正确方法是什么?我知道NumPy在矩阵计算方面做得很好。在这种情况下,NumPy的速度是否足够快,以至于Numba不再提供加速功能?正如FBruzzesi在评论中提到的,代码没有编译的原因是您使用了“奇特的索引”,因为
W[E]
中的E
是np.where
的输出,是数组的元组。(这就解释了这个略显晦涩的错误消息:Numba不知道如何使用getitem
,也就是说,当其中一个输入是元组时,它不知道如何在括号中查找某些内容。)
Numba,只是没有多个维度。在您的情况下,这允许进行一个简单的修改:首先使用ravel
几乎无成本地将阵列变成一维,然后应用转换,然后再对其进行廉价的重塑
@njit
def invert2(W, copy=True):
if copy:
W = W.copy()
Z = W.ravel()
E = np.where(Z)
Z[E] = 1. / Z[E]
return Z.reshape(W.shape)
但这仍然比需要的慢,因为它通过不必要的中间数组传递计算,而不是在遇到非零值时立即修改数组。简单地做一个循环会更快:
@njit
def invert3(W, copy=True):
if copy:
W = W.copy()
Z = W.ravel()
for i in range(len(Z)):
if Z[i] != 0:
Z[i] = 1/Z[i]
return Z.reshape(W.shape)
无论W
的尺寸如何,此代码都有效。如果我们知道W
是二维的,那么我们可以直接在这两个维度上迭代,但是因为这两个维度的性能相似,所以我选择更一般的路线
在我的计算机上,假设一个300×300的数组W
,其中大约一半的条目是0,并且invert
是您没有编译的原始函数,则计时为:
In [80]: %timeit invert(W)
2.67 ms ± 49.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [81]: %timeit invert2(W)
519 µs ± 24.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [82]: %timeit invert3(W)
186 µs ± 11.1 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
因此,Numba给了我们相当大的加速(在它已经运行一次以消除编译时间之后),特别是在代码以Numba可以利用的高效循环方式重写之后。正如FBruzzesi在评论中提到的,代码没有编译的原因是您使用了“奇特的索引”,因为W[E]
中的E
是np.where
的输出,是数组的元组。(这就解释了这个略显晦涩的错误消息:Numba不知道如何使用getitem
,也就是说,当其中一个输入是元组时,它不知道如何在括号中查找某些内容。)
Numba,只是没有多个维度。在您的情况下,这允许进行一个简单的修改:首先使用ravel
几乎无成本地将阵列变成一维,然后应用转换,然后再对其进行廉价的重塑
@njit
def invert2(W, copy=True):
if copy:
W = W.copy()
Z = W.ravel()
E = np.where(Z)
Z[E] = 1. / Z[E]
return Z.reshape(W.shape)
但这仍然比需要的慢,因为它通过不必要的中间数组传递计算,而不是在遇到非零值时立即修改数组。简单地做一个循环会更快:
@njit
def invert3(W, copy=True):
if copy:
W = W.copy()
Z = W.ravel()
for i in range(len(Z)):
if Z[i] != 0:
Z[i] = 1/Z[i]
return Z.reshape(W.shape)
无论W
的尺寸如何,此代码都有效。如果我们知道W
是二维的,那么我们可以直接在这两个维度上迭代,但是因为这两个维度的性能相似,所以我选择更一般的路线
在我的计算机上,假设一个300×300的数组W
,其中大约一半的条目是0,并且invert
是您没有编译的原始函数,则计时为:
In [80]: %timeit invert(W)
2.67 ms ± 49.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [81]: %timeit invert2(W)
519 µs ± 24.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [82]: %timeit invert3(W)
186 µs ± 11.1 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
因此,Numba给了我们相当大的加速(在它已经运行一次以消除编译时间之后),特别是在代码以Numba可以利用的高效循环方式重写之后。Numba不支持“花式”索引,请检查。如果两个数组都不支持“奇特”索引,请检查。您应该沿着两个数组维度循环