Ошибка понижения Numba при переназначении «следующей» ссылки элемента связанного списка

Следующий код является моей реализацией связанного списка с использованием numba (связанные примеры можно увидеть здесь, здесь и здесь). Функция 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


person Brandt    schedule 10.11.2017    source источник


Ответы (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
person Mike Müller    schedule 11.11.2017
comment
Бегает, да. Но на самом деле медленнее, чем чистый питон (без @jit). Если вы timeit, украшенная версия с @jit делает ~ 180 us, а чистый python - ~ 80 us. - person Brandt; 13.11.2017
comment
Для меня это больше похоже на вариант использования PyPy. - person Mike Müller; 13.11.2017
comment
Привет Майк, просто чтобы дать вам обновление. Существует проблема с обработкой рассматриваемой здесь ошибки: github.com/numba/numba/issues/ 2606 . Благодарность - person Brandt; 21.11.2017