Я не на 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 в набор не подходит, сообщите мне. Без особых подробностей трудно сказать, как подойти к проблеме.
скорость не изменилась .. по сравнению с чем? –
Встроенный чек должен быть очень быстрым. Попробуйте 'key in validSet', но это должно быть одно и то же. Использование вложенного 'dict' и проверка существования одного элемента кортежа за раз может помочь, но только если хеширование последних элементов происходит довольно медленно. –
Зачем вам нужно проверять все три '(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: ...' –