用numbanjit
修饰的函数(它是jit(nopython=True)
的别名)在本地操作中从numpy
得到不同的结果(简单的@jit(nopython=False)
也会从numpy
得到不同的结果):
In [1]: import numpy as np
from numba import njit
def npfun(arr):
arr -= arr[3]
@njit
def jitfun(arr):
arr -= arr[3]
arr1 = np.ones((6,2))
arr2 = arr1.copy()
npfun(arr1)
jitfun(arr2)
arr1 == arr2
Out[1]: array([[ True, True],
[ True, True],
[ True, True],
[ True, True],
[False, False],
[False, False]], dtype=bool)
看起来,numpy
计算rhs并将其作为副本传递,而numba
将rhs视为一个视图。这样做有什么技术原因吗?在
numpy 1.13.3
numba 0.35
你正在做的手术:
以前在纽比中是未定义的行为。它是最近才被定义的,在NumPy 1.13.0,发布了June 7th this year。新的、定义好的行为总是表现得好像复制了所有输入,尽管当它可以检测到不需要复制时,它试图避免实际复制。在
看起来Numba目前并没有尝试模仿新的行为,无论是因为它有多新,还是因为Numba的特定关注点。在
解决方法
如果您使用显式的就地操作,加上
out
参数,而不是扩充赋值:replace,这将有助于Numba与
^{pr2}$这使得jitted版本(虽然使用@jit,而不是@njit)的性能与NumPy版本相同。值得注意的是,尝试@njit这个函数现在将失败,告诉您njit无法处理
out
参数。在我看到您已经opened an issue on this,所以有一个机会,对扩充赋值的处理将被更改为匹配NumPy。在
为什么会发生这种情况
正如hpaulj所说,Numba输出相当于在数组的行上循环。Python抖动不能处理NumPy底层的C代码;它需要Python来处理。支持NumPy方法的原因(在某种程度上)是因为Numba开发人员费尽心思将NumPy数组操作解码为标量对象上的显式Python迭代,然后将迭代传递给LLVM。从documentation:
前面提到的^{} 收集索引并在索引上迭代。如果被迭代的对象在迭代过程中发生了变化,这会使事情变得棘手。在
相关问题 更多 >
编程相关推荐