У меня есть 2D UINT8 numpy массив размером (149797, 64) . Каждый из элементов имеет значение 0 или 1. Я хочу упаковать эти двоичные значения в каждой строке в значение UINT64 , чтобы в результате я получил массив UINT64 формы 149797. Я попробовал следующий код с использованием функции numpy bitpack.
test = np.random.randint(0, 2, (149797, 64),dtype=np.uint8)
col_pack=np.packbits(test.reshape(-1, 8, 8)[:, ::-1]).view(np.uint64)
Для выполнения функции packbits требуется около 10 мс . Простое изменение формы самого этого массива, похоже, занимает около 7 мс . Я также попытался перебрать массив 2d numpy, используя операции сдвига для достижения того же результата; но не было никакого улучшения скорости.
Наконец, я также хочу скомпилировать его, используя numba для процессора.
@njit
def shifting(bitlist):
x=np.zeros(149797,dtype=np.uint64) #54
rows,cols=bitlist.shape
for i in range(0,rows): #56
out=0
for bit in range(0,cols):
out = (out << 1) | bitlist[i][bit] # If i comment out bitlist, time=190 microsec
x[i]=np.uint64(out) # Reduces time to microseconds if line is commented in njit
return x
Это занимает около 6 мс используя njit .
Вот параллельная версия njit
@njit(parallel=True)
def shifting(bitlist):
rows,cols=149797,64
out=0
z=np.zeros(rows,dtype=np.uint64)
for i in prange(rows):
for bit in range(cols):
z[i] = (z[i] * 2) + bitlist[i,bit] # Time becomes 100 micro if i use 'out' instead of 'z[i] array'
return z
Это немного лучше с 3,24 мс время выполнения (google colab dual core 2.2Ghz) В настоящее время лучшим решением является решение python с swapbytes (Paul's) , то есть 1,74 мс .
Как мы можем ускорить процесс это преобразование? Есть ли возможность использовать векторизацию (или распараллеливание), bitarrays et c, для достижения ускорения?
Ref: numpy packbits pack в массив uint16
На 12-ядерном компьютере (процессор Intel Xeon® R E5-1650 v2 @ 3,50 ГГц),
метод Паулса: 1595,0 микросекунд (это делает я полагаю, не использовать многоядерный)
Код Numba: 146.0 микросекунд (вышеупомянутая параллельная-numba)
т.е. около 10-кратного ускорения !!!