У меня есть огромный numpy массив значений uint64 (65 миллионов), созданный xxha sh .xxh64_intdigest (ключ) . Я хочу посмотреть несколько хэшей в al oop в этом массиве (нужно искать один за другим).
Я перепробовал так много комбинаций и много поискал в сети; но я не уверен, что это лучшая реализация!
Я тестировал чистые python, numba и cython. Самая быстрая реализация на Cython (с использованием C указателей с prange и nogil) была почти такой же быстрой, как и реализация numba.
Q1. Есть ли другой способ повысить производительность, например, использовать векторы?
Q2. На np.empty существует огромное python взаимодействие (arrlen, dtype = bool). Можно ли их уменьшить?
Q3. Почему объявление типов переменных в numba замедляет код?
Может быть создан хеш-массив по этому коду:
import random
import string
def randomString(stringLength=10):
letters = string.ascii_letters
return ''.join(random.choice(letters) for i in range(stringLength))
# hash to be searched
hashkey=xxhash.xxh64_intdigest(randomString(30))
# create array of hashes
arrlen=int(1e6)
hasharr=np.empty(arrlen,dtype=np.uint64)
for i in range(arrlen):
hasharr[i]=xxhash.xxh64_intdigest(randomString(20) )
Вот реализации numba:
def lookup_py(x,y):
mask = x==y
return mask
@jit(parallel=True)
def lookup_nb1(x,y):
mask = x==y
return mask
@jit('b1[:](u8[:],u8)', parallel=True)
def lookup_nb2(x,y):
mask = x==y
return mask
Параллельный код Cython:
%%cython -a --compile-args=/openmp --link-args=/openmp --force
cimport cython
cimport numpy as np
import numpy as np
from numpy cimport ndarray as ar
from libc.stdlib cimport malloc, free
from cython.parallel import prange
@cython.boundscheck(False)
@cython.wraparound(False)
cpdef lookup_cy(ar[np.uint64_t] hashlist, unsigned long long hashkey):
cdef int i
cdef unsigned long arrlen = hashlist.shape[0]
cdef ar[np.uint8_t,cast=True] mask = np.empty(arrlen, dtype=bool)
cdef np.uint8_t * ptr_mask = &mask[0]
cdef np.uint64_t* ptr_hashlist = &hashlist[0]
with nogil:
for i in range(arrlen):
ptr_mask[i]=(ptr_hashlist[i]==hashkey)
return mask
и время:
%timeit lookup_py(hasharr,hashkey)
%timeit lookup_nb1(hasharr,hashkey)
%timeit lookup_nb2(hasharr,hashkey)
%timeit lookup_cy(hasharr,hashkey)
544 µs ± 8.12 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
190 µs ± 8.61 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
159 µs ± 8.37 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
147 µs ± 4.55 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)