【问题标题】:Numba nopython mode cannot accept 2-D boolean indexingNumba nopython 模式不能接受二维布尔索引
【发布时间】:2019-09-12 23:33:40
【问题描述】:

我正在尝试使用numba(目前我正在使用numba 0.45.1)加速代码,但遇到了布尔索引问题。代码如下:

from numba import njit
import numpy as np

n_max = 1000

n_arr = np.hstack((np.arange(1,3),
                   np.arange(3,n_max, 3)
                   ))

@njit
def func(arr):
    idx =  np.arange(arr[-1]).reshape((-1,1)) < arr -2
    result = np.zeros(idx.shape)
    result[idx] = 10.1
    return result

new_arr = func(n_arr)

运行代码后,我会立即收到以下消息

TypingError: Invalid use of Function(<built-in function setitem>) with argument(s) of type(s): (array(float64, 2d, C), array(bool, 2d, C), float64)
 * parameterized
In definition 0:
    All templates rejected with literals.
In definition 1:
    All templates rejected without literals.
In definition 2:
    All templates rejected with literals.
In definition 3:
    All templates rejected without literals.
In definition 4:
    All templates rejected with literals.
In definition 5:
    All templates rejected without literals.
In definition 6:
    All templates rejected with literals.
In definition 7:
    All templates rejected without literals.
In definition 8:
    TypeError: unsupported array index type array(bool, 2d, C) in [array(bool, 2d, C)]
    raised from C:\Users\User\Anaconda3\lib\site-packages\numba\typing\arraydecl.py:71
In definition 9:
    TypeError: unsupported array index type array(bool, 2d, C) in [array(bool, 2d, C)]
    raised from C:\Users\User\Anaconda3\lib\site-packages\numba\typing\arraydecl.py:71
This error is usually caused by passing an argument of a type that is unsupported by the named function.
[1] During: typing of setitem at C:/Users/User/Desktop/all python file/5.5.5/numba index broadcasting2.py (29)

请注意,最后一行的(29) 对应于第 29 行,即result[idx] = 10.1,这是我尝试为索引为idx(一个二维布尔索引)的结果赋值的行。


我想解释一下,在 @njit 中包含该声明 result[idx] = 10.1 是必须的。尽管我想在@njit 中排除这条语句,但我不能,因为这条线正好位于我正在处理的代码的中间。

如果我坚持将赋值语句result[idx] = 10.1 包含在@njit 中,究竟需要更改什么才能使其工作?如果可能的话,我希望看到一些代码示例,其中涉及可以运行的@njit 内的二维布尔索引。

谢谢

【问题讨论】:

    标签: python python-3.x numpy indexing numba


    【解决方案1】:

    Numba 目前不支持二维数组的精美索引。见:

    https://numba.pydata.org/numba-doc/dev/reference/numpysupported.html#array-access

    但是,您可以通过使用 for 循环显式重写函数而不是依赖广播来获得等效的行为:

    from numba import njit
    import numpy as np
    
    n_max = 1000
    
    n_arr = np.hstack((np.arange(1,3),
                       np.arange(3,n_max, 3)
                       ))
    
    def func(arr):
        idx =  np.arange(arr[-1]).reshape((-1,1)) < arr -2
        result = np.zeros(idx.shape)
        result[idx] = 10.1
        return result
    
    @njit
    def func2(arr):
        M = arr[-1]
        N = arr.shape[0]
        result = np.zeros((M, N))
        for i in range(M):
            for j in range(N):
                if i < arr[j] - 2:
                    result[i, j] = 10.1
    
        return result
    
    new_arr = func(n_arr)
    new_arr2 = func2(n_arr)
    print(np.allclose(new_arr, new_arr2))  # True
    

    在我的机器上,使用您提供的示例输入,func2func 快​​大约 3.5 倍。

    【讨论】:

    • 有趣。看到在这种情况下广播比@njit 中的for循环慢,我想知道这对于大多数大数据操作是否成立?我问这个是因为虽然我在这个例子中只在numpy数组中进行广播,但将来我会在tensorflow设置中进行广播,所以知道这个问题的答案真的很棒。
    猜你喜欢
    • 2017-08-08
    • 2020-06-15
    • 2017-05-24
    • 2020-05-09
    • 1970-01-01
    • 2016-12-10
    • 1970-01-01
    • 2020-09-15
    • 1970-01-01
    相关资源
    最近更新 更多