Оказалось, что было 2 несвязанных проблемы, которые вызывали чрезмерное использование ОЗУ.
Во-первых, объект memmap полностью считывался с диска при обработке для многопроцессорных рабочих.
Это дублирование данных выделяло 6,7 ГБ ОЗУ для каждого рабочего.
Для решения этой проблемы яЯ создал общий RawArray
и загрузил в него данные, и на каждом работнике я использовал np.frombuffer
.
Во-вторых, и X.dot(Q)
, и (X.T * W)
привели к беспорядочному выделению еще одной X-образной матрицы, то есть еще 6,7 ГБ ОЗУ
Я создал вариант ответа из этой темы: https://stackoverflow.com/a/21096605/5572523
Поскольку моя матрица невысока, я нарезал строки:
def _block_slices(dim_size, block_size):
count = 0
while True:
yield slice(count, count + block_size, 1)
count += block_size
if count >= dim_size:
raise StopIteration
И теперь я могу выполнять итерации по пакетам данных (также добавлено немного дополнительного ускорения при работе с weight = 0)
Я установил max_elements = 2 ** 27
, потому что я использую float64, поэтому в результате получается матрица размером 1 ГБ (если я не ошибаюсь).
Итак, (X.T * W).dot(X)
превратился в:
def weighted_outer_prod(X, W):
n, d = X.shape
max_rows = max(1, int(max_elements / d))
sigma = np.zeros([d, d])
for mm in _block_slices(n, max_rows):
sigma += batch_weighted_outer_prod(X[mm, :], W[mm])
return sigma
def batch_weighted_outer_prod(batch, W):
nz = W > 0
buff = np.empty(batch[nz].shape)
np.multiply(batch[nz], W[nz, np.newaxis], out=buff)
sigma = buff.T.dot(batch[nz])
del(buff)
return sigma
И np.sum(X.dot(Q) * X, axis=1)
превратился в: (не обращая внимания на название функции)
def calc_l_k(X, Q):
max_rows = max(1, int(max_elements / d))
l_k = np.empty(n)
for mm in _block_slices(n, max_rows):
l_k[mm] = batch_l_k(X[mm, :], Q)
return l_k
def batch_l_k(batch, Q):
buff = np.empty(batch.shape)
np.dot(batch, Q, out=buff)
np.multiply(buff, batch, out=buff)
l_k = -0.5 * np.sum(buff, axis=1)
del(buff)
return l_k
Теперь он работает с X формы [1 мил, 900], и я надеюсь, что это будетпо-прежнему работать с более высокими размерами.