логическая маскировка (индексация) numpy массив в Cython - PullRequest
0 голосов
/ 13 февраля 2020

У меня есть огромный 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...