Python Numba список списков кортежей - PullRequest
0 голосов
/ 26 ноября 2018

Я пытаюсь ускорить мой алгоритм с помощью numba, после каких-либо дальнейших улучшений, которые были оставлены с помощью numpy и оптимизации.

У меня есть функция, которая выполняет некоторые вычисления в большом 2-кратном вложенном цикле:

import random
from numba import njit

@njit()
def decide_if_vaild():
    return bool(random.getrandbits(1))

@njit()
def decide_what_bin(bins):
    return random.randint(0, bins-1)

@njit()
def foo(bins, loops):
    results = [[] for _ in range(bins)]

    for i in range(loops):
        for j in range(i+1, loops):
            happy = decide_if_vaild()
            bin = decide_what_bin(bins)
            if happy:
                results[bin].append( (i,j) )
                # or
                # results[bin].append( [i,j] )
    return results

if __name__ == '__main__':
    x = foo(3,100)

Если я запускаю этот минимальный пример выше, я (как и ожидалось) получаю ошибку при печати:

  File "C:\Users\xxx\AppData\Local\Programs\Python\Python36\lib\site-packages\numba\typeinfer.py", line 104, in getone
    assert self.type is not None
numba.errors.InternalError: 
[1] During: typing of call at C:/Users/xxx/minimal_example.py (21)
--%<-----------------------------------------------------------------

File "minimal_example.py", line 21

Проблема заключается в: "results [bin] .append ((i, j)) ", где я пытаюсь добавить кортеж (также не работает со списками) в список.

Количество бинов известно заранее, но сколько элементов (2-кортеж или список илиnp.array) зависит от того, как часто define_if_vaild оценивается как True, и, поскольку я не знаю, как часто это будет происходить, а вычисления достаточно дороги, я не знаю другого обходного пути.

Любые хорошие идеи, какЯ мог бы сгенерировать результат в функции с привязкой и вернуть его или передать глобальный контейнер, который эта функция могла бы заполнить?

Это, вероятно, возвращается к:

numba.errors.LoweringError: Failed at nopython (nopython mode backend)
list(list(list(int64))): unsupported nested memory-managed object

, где похожая проблема длясписок (list (int64)) (https://github.com/numba/numba/issues/2560)было разрешено в numba 0.39.0 с https://github.com/numba/numba/pull/2840

1 Ответ

0 голосов
/ 26 ноября 2018

Я реализовал следующий обходной путь, хотя он и не дает полного ответа на вопрос, но это может быть подходящим подходом для других, кто борется с этой проблемой:

@njit()
def foo(bins, loops):
    results = []
    mapping = []

    for i in range(loops):
        for j in range(loops+1, size):
            happy = decide_if_vaild()
            bin = decide_what_bin(bins)
            if happy:
                results.append( (i,j) )
                mapping.append( bin )
    return results, mapping

Это вернет список кортежей (поддерживается по состоянию на numba 0.39.0) и список отображений, где mapping [i] содержит корзину для результатов [i].Теперь jit-компилятор работает без сбоев, и я могу распаковать результаты вне jit.

...