Numba在重新分配' next'链表元素的链接

时间:2017-11-10 22:21:59

标签: python numba

以下代码是我使用numba实现的链接列表(可以看到相关示例hereherehere)。 remove函数删除位置index处的元素。 (请注意,这里假设index始终是有效位置) 要删除此类元素(index),我们会执行element[index-1].next -> element[index+1]之类的分配。但是当我这样做时,numba似乎并不喜欢:

from numba import deferred_type,optional
from numba import int64
from numba import jitclass,njit

list_type = deferred_type()

spec = [
    ('data',int64),
    ('next',optional(list_type))
]
@jitclass(spec)
class List(object):
    def __init__(self,data,next):
        self.data = data
        self.next = next

    def prepend(self, data):
        return List(data, self)

list_type.define(List.class_type.instance_type)

def length(stack):
    i = 0
    while stack is not None:
        stack = stack.next
        i+=1
    return i

@njit
def remove(stack,index):
    prev = None
    if index == 0:
        stack = stack.next
    else:
        cur = stack
        i = 0
        while cur is not None:
            if index == i:
                break
            i = i+1
            prev = cur
            cur = cur.next
        prev.next = cur.next
    return stack

def runme():
    from numpy.random import randint
    a = randint(0,100,10)

    list_ = None

    for n in a:
        if list_ is None:
            list_ = List(n,None)
        else:
            list_ = list_.prepend(n)
    print(length(list_))

    indexes = list(range(len(a)))
    for i in indexes[::-1]:
        list_ = remove(list_,i)
    print(length(list_))

if __name__ == '__main__':
    runme()

它在第prev.next = cur.next行中断,出现以下错误:

numba.errors.LoweringError: Failed at nopython (nopython mode backend)
No definition for lowering ?instance.jitclass.List#14bebc8<data:int64,next:?DeferredType#140432587762264>.next = ?DeferredType#140432587762264
File "numba_test.py", line 43
[1] During: lowering "(prev).next = $70.2" at numba_test.py (43)

看起来prev.next无法重新分配,但我不确定这里发生了什么。

我正在使用 numba 0.35.0 python 3.6.2

有什么想法吗?

感谢。

当前状态

错误是Numba中的错误。有关详细信息,请转到相应的问题:https://github.com/numba/numba/issues/2606

1 个答案:

答案 0 :(得分:1)

看起来nopython模式确实支持此功能。只需使用“普通”jit装饰器即可。如果需要,这可以回到普通的Python:

from numba import jit

@jit
def remove(stack,index):
    prev = None
    if index == 0:
        stack = stack.next
    else:
        cur = stack
        i = 0
        while cur is not None:
            if index == i:
                break
            i = i+1
            prev = cur
            cur = cur.next
        prev.next = cur.next
    return stack

因为njit等同于jit(nopython=True)

测试输出:

10
0