为什么numba和numpy在现场操作中表现不同?

问题描述 投票:1回答:2

用qumbxswpoi的别名numba njit装饰的函数产生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) 评估rhs并将其作为副本传递,而numpy将rhs视为视图。有没有技术理由这样做?

numba numpy 1.13.3

python numpy numba in-place
2个回答
3
投票

你正在做的操作:

numba 0.35

曾经是NumPy中未定义的行为。它最近才被定义,在arr -= arr[3] ,释放NumPy 1.13.0。新的,定义的行为总是表现为它复制了所有输入,尽管它试图避免在检测到它不需要时实际制作副本。

看起来Numba目前没有尝试模仿新行为,无论是因为它有多新,还是因为Numba特有的担忧。


2
投票

Workaround

如果你使用June 7th this year参数的显式就地操作,而不是增强赋值,它将帮助Numba:replace

out

arr -= arr[3] 

这使得jitted版本(虽然使用@jit,而不是@njit)与NumPy版本完全相同。值得注意的是,尝试@njit这个函数现在会失败,告诉你比njit无法处理np.subtract(arr, arr[3], out=arr) 参数。

我已经看到你已经out,所以有可能改变增强作业的处理以匹配NumPy。

Why this happens

正如hpaulj所说,Numba输出相当于循环遍历数组的行。 Python JITter无法对NumPy底层的C代码做任何事情;它需要Python才能使用。支持NumPy方法(在某种程度上)的原因是Numba开发人员遇到了将NumPy数组操作解码为标量对象的显式Python迭代的麻烦,然后可以将其传递给LLVM。来自opened an issue on this

  • 合成一个实现数组表达式的Python函数:这个新的Python函数本质上就像一个Numpy ufunc,它在广播数组参数中的标量值上返回表达式的结果。降低功能通过从数组表达式树转换为Python AST来实现这一点。
  • 将合成Python函数编译到内核中:此时,降低函数依赖于现有代码来降低ufunc和DUFunc内核,在定义如何降低对合成函数的调用之后调用documentation

最终结果类似于Numba对象模式中的循环提升。

上述numba.targets.numpyimpl.numpy_ufunc_kernel()收集索引并迭代它们。如果被迭代的对象在迭代过程中发生变异,则会使事情发生变化。

© www.soinside.com 2019 - 2024. All rights reserved.