2016-05-02 8 views
0

У меня есть функция python и хочу ускорить ее с помощью numba. Самая трудоемкая часть - поиск кортежа в наборе/dict. Может кто-нибудь дать идею, как решить это?Как ускорить задачу поиска dict в numba?

idNeg = np.array([[1,2,3], [4,5,6], ..., [7,8,9]]) 
validSet = {(1,2,3):True, (5,4,3):True, ..., (2,5,3):True} 
@jit 
def CalcNeg(idNeg, validSet): 
    l = len(idNeg) 
    for j in xrange(l): 
     corplc = np.random.choice([0, 2]) 
     idNeg[j, corplc] = random.randrange(0, VE.shape[0]) 
     while validSet.has_key((idNeg[j, 0], idNeg[j, 1], idNeg[j, 2])): 
      idNeg[j, corplc] = random.randrange(0, VE.shape[0]) 
    return idNeg 

Я попытался, как это, но скорость не изменяется по сравнению код без @jit.

+0

скорость не изменилась .. по сравнению с чем? –

+0

Встроенный чек должен быть очень быстрым. Попробуйте 'key in validSet', но это должно быть одно и то же. Использование вложенного 'dict' и проверка существования одного элемента кортежа за раз может помочь, но только если хеширование последних элементов происходит довольно медленно. –

+0

Зачем вам нужно проверять все три '(idNeg [j, 0], idNeg [j, 1], idNeg [j, 2])', если только один, если они меняются? вы не могли бы сделать 'if validSet.has_key ((idNeg [j, 0], idNeg [j, 1], idNeg [j, 2]): продолжить, а idNeg [j, corplc] в validSet: ...' –

ответ

1

Я не на 100% проясняю точный характер желаемых входов (содержимого или типичных фигур), но ключ к получению хороших показателей производительности в Numba заключается в возможности использовать функцию в режиме nopython (в отличие от python). В исходной функции используются структуры данных, в частности, dict, которые в настоящее время не поддерживаются.

Опять же, я не знаю конкретного варианта использования или допустим следующее изменение, но я взял validSet dict и преобразовал его ключи в реальный заданный объект, где значение в паре ключей, значение было True.

В качестве примера:

import numpy as np 
import numba as nb 
import random 

# Original function 
def CalcNeg(idNeg, validSet, N): 
    l = len(idNeg) 
    for j in xrange(l): 
     corplc = np.random.choice([0, 2]) 
     idNeg[j, corplc] = random.randrange(0, N) 
     while validSet.has_key((idNeg[j, 0], idNeg[j, 1], idNeg[j, 2])): 
      idNeg[j, corplc] = random.randrange(0, N) 
    return idNeg 

# Modified version, compiled in nopython mode (njit) 
@nb.njit 
def CalcNeg2(idNeg, validSet, N): 
    l = len(idNeg) 
    c = np.array([0,2]) 
    for j in xrange(l): 
     corplc = np.random.choice(c) 
     idNeg[j, corplc] = random.randrange(0, N) 
     #while validSet.has_key((idNeg[j, 0], idNeg[j, 1], idNeg[j, 2])): 
     while (idNeg[j, 0], idNeg[j, 1], idNeg[j, 2]) in validSet: 
      idNeg[j, corplc] = random.randrange(0, N) 
    return idNeg 

# Some test data 
N = 40 
M = 2000 
idNeg = np.random.random_integers(0, N, size=(M,3)) 
tmp = np.random.random_integers(0, N, size=(M,3)) 
validSet = {tuple(tmp[k,:]): True for k in xrange(tmp.shape[0])} 

# convert validSet to real python set for keys with value == True 
_validSet = {k for k,v in validSet.iteritems() if v is True} 

А теперь некоторые тайминги от IPython с ноутбука с помощью %timeit магии:

%timeit CalcNeg(idNeg, validSet, N) 
100 loops, best of 3: 7.84 ms per loop 

%timeit CalcNeg2(idNeg, _validSet, N) 
1000 loops, best of 3: 444 µs per loop 

Так что на моей машине, что еще более 18x скорость вверх. Я использую Numba 0.25. Как и примечание, переход к набору в исходной функции python дает небольшую разницу, но больше похоже на ускорение на 25%.

Если тестовые данные нереалистичны или если преобразование dict в набор не подходит, сообщите мне. Без особых подробностей трудно сказать, как подойти к проблеме.

+0

Привет, @JoshAdel, Спасибо за ваш ответ. Но после того, как я запустил код, он сказал: Ошибка в объекте (объектный режим) Внутренняя ошибка: NotImplementedError: Неизвестный оператор 'in'. Какую версию numba вы используете? Я использую 0,19.1 – maple

+0

@maple, как указано в ответе, я использую последнюю версию Numba, 0.25. Numba находится в очень активной разработке, и каждый выпуск обычно добавляет поддержку множества новых функций python и numpy, а также улучшает скорость компиляции и общую производительность. Больше, чем любой другой пакет, я настоятельно рекомендую использовать близкую к новейшей версии. – JoshAdel

 Смежные вопросы

  • Нет связанных вопросов^_^