为什么numba和numpy在就地操作上表现不同?

2024-09-30 08:19:48 发布

您现在位置:Python中文网/ 问答频道 /正文

用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.3numba 0.35


Tags: importnumpyfalsetruedefnpjitarr
2条回答

你正在做的手术:

arr -= arr[3]

以前在纽比中是未定义的行为。它是最近才被定义的,在NumPy 1.13.0,发布了June 7th this year。新的、定义好的行为总是表现得好像复制了所有输入,尽管当它可以检测到不需要复制时,它试图避免实际复制。在

看起来Numba目前并没有尝试模仿新的行为,无论是因为它有多新,还是因为Numba的特定关注点。在

解决方法

如果您使用显式的就地操作,加上out参数,而不是扩充赋值:replace,这将有助于Numba

arr -= arr[3] 

^{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

  • Synthesize a Python function that implements the array expression: This new Python function essentially behaves like a Numpy ufunc, returning the result of the expression on scalar values in the broadcasted array arguments. The lowering function accomplishes this by translating from the array expression tree into a Python AST.
  • Compile the synthetic Python function into a kernel: At this point, the lowering function relies on existing code for lowering ufunc and DUFunc kernels, calling numba.targets.numpyimpl.numpy_ufunc_kernel() after defining how to lower calls to the synthetic function.

The end result is similar to loop lifting in Numba’s object mode.

前面提到的^{}收集索引并在索引上迭代。如果被迭代的对象在迭代过程中发生了变化,这会使事情变得棘手。在

相关问题 更多 >

    热门问题