Numba не может определить отпечаток пустого списка даже с подписью - PullRequest
1 голос
/ 04 октября 2019

Я использую подпись @jit, чтобы определить типы входящих аргументов. Но при вызове функции я получаю:

ValueError: cannot compute fingerprint of empty list

Я знаю, что список пуст, но моя подпись определяет его, поэтому я не уверен, почему Numba не использует эту подпись.

Я пыталсяразличные формы подписей (строковая форма и форма кортежа), и это все еще дает ошибку. Мне не понятно из документации, почему эти подписи не определяют аргументы как переданные, и все еще полагаются на выводящие типы.

@nb.jit("void(List(int64), int64, List(List(int64)))", nopython=True, cache=True)
def _set_indices(keys_as_int, n_keys, indices):
    for i, k in enumerate(keys_as_int):
        indices[k].append(i)
    indices = [([np.array(elt) for elt in indices])]

def group_by(keys):
    _, first_occurrences, keys_as_int = np.unique(keys, return_index=True, return_inverse=True)
    n_keys = max(keys_as_int) + 1
    indices = [[] for _ in range(max(keys_as_int) + 1)]
    print(str(keys_as_int) + str(n_keys) + str(indices))
    _set_indices(keys_as_int, n_keys, indices)
    return indices

result = group_by(['aaa', 'aab', 'aac', 'aaa', 'aac'])
print(str(result))

Я ожидал, что подпись будет принудительно вводить данные при входящейаргументы без необходимости выводить типы данных. Фактическая ошибка

<ipython-input-274-401e07cd4e63> in <module>
----> 1 result = group_by(['aaa', 'aab', 'aac', 'aaa', 'aac'])
      2 print(str(result))

<ipython-input-273-acdebb81069c> in group_by(keys)
      4     indices = [[] for _ in range(max(keys_as_int) + 1)]
      5     print(str(keys_as_int) + str(n_keys) + str(indices))
----> 6     _set_indices(keys_as_int, n_keys, indices)
      7     return indices

ValueError: cannot compute fingerprint of empty list

1 Ответ

1 голос
/ 05 октября 2019

Итак, я нашел обходной путь, чтобы ваш код заработал. Вот проблема github с почти той же проблемой, с которой вы столкнулись. Поэтому я попытался создать список с фиктивным значением -1, которое будет сброшено ближе к концу. Однако я столкнулся с «отраженным списком исключений». Подробнее об этом можно прочитать здесь . Поэтому мне пришлось использовать печатный список Нумбы. Вы можете проверить больше об этом типе данных здесь . Короче говоря, вот окончательный код, который работает в режиме без Python и возвращает правильный результат, как вы ожидаете.

import numba as nb
import numpy as np
from numba.typed import List

@nb.jit(nopython=True, cache=True)
def _set_indices(keys_as_int, n_keys, indices):
    # Do some operation
    for i, k in enumerate(keys_as_int):
        indices[k].append(i)

    # Drop the dummy element in the final result
    indices = [elem[1:] for elem in indices]

    # Return the final indices
    return indices

def group_by(keys):
    _, first_occurrences, keys_as_int = np.unique(keys, return_index=True,
                                                  return_inverse=True)
    n_keys = max(keys_as_int) + 1

    # Simply adding the dummy element doesn't work here
    # Error: cannot reflect element of reflected container: reflected list(reflected list(int64))
    # indices = [[-1] for _ in range(max(keys_as_int) + 1)]
    # A workaround is to create Numba's version of typed-list
    indices = List()
    for i in range(max(keys_as_int) + 1):
        l = List()
        l.append(-1)
        indices.append(l)

    print(str(keys_as_int), str(n_keys),  str(indices))
    indices = _set_indices(keys_as_int, n_keys, indices)
    return indices

result = group_by(['aaa', 'aab', 'aac', 'aaa', 'aac'])

# Conversion of Numba's typed list inside NoPython mode returns error
# Hence do it outside the function
result = [np.asarray(elem) for elem in result]
print(result)

Вот ссылка на блокнот Google colab с рабочим кодом. Перейдите к последней ячейке, если вы хотите копаться в исключении отраженного списка.

...