Numpy эффективное умножение больших матриц

Для хранения большой матрицы на диске я использую numpy.memmap.

Вот пример кода для проверки умножения больших матриц:

import numpy as np
import time

rows= 10000 # it can be large for example 1kk
cols= 1000

#create some data in memory
data = np.arange(rows*cols, dtype='float32') 
data.resize((rows,cols))

#create file on disk
fp0 = np.memmap('C:/data_0', dtype='float32', mode='w+', shape=(rows,cols))
fp1 = np.memmap('C:/data_1', dtype='float32', mode='w+', shape=(rows,cols))

fp0[:]=data[:]
fp1[:]=data[:]

#matrix transpose test
tr = np.memmap('C:/data_tr', dtype='float32', mode='w+', shape=(cols,rows))
tr= np.transpose(fp1)  #memory consumption?
print fp1.shape
print tr.shape

res = np.memmap('C:/data_res', dtype='float32', mode='w+', shape=(rows,rows))
t0 = time.time()
# redifinition ? res= np.dot(fp0,tr) #takes 342 seconds on my machine, if I multiplicate matrices in RAM it takes 345 seconds (I thinks it's a strange result)
res[:]= np.dot(fp0,tr) # assignment ?
print res.shape
print (time.time() - t0)

Итак, мои вопросы:

  1. Как ограничить потребление памяти приложением, которое использует эту процедуру, некоторым значением, например, до 100 МБ (или 1 ГБ или что-то еще). Также я не понимаю, как оценить потребление памяти процедурой (я думаю, что память выделяется только тогда, когда "data "переменная создается, но сколько памяти используется, когда мы используем файлы memmap?)
  2. Может быть, есть какое-то оптимальное решение для умножения больших матриц, хранящихся на диске? Например, возможно, данные не оптимально хранятся на диске или считываются с диска, не исправляются должным образом, а также точечный продукт использует только одно ядро. Может быть, мне следует использовать что-то вроде PyTables?

Также меня интересовали алгоритмы решения линейных систем уравнений (SVD и другие) с ограниченным использованием памяти. Может быть, эти алгоритмы называются внеядерными или итеративными, и я думаю, что есть какая-то аналогия, например, жесткий диск ‹-> ram, gpu ram ‹-> cpu ram, cpu ram ‹-> cpu cache.

Также здесь я нашел некоторую информацию об умножении матриц в PyTables.

Также я нашел это в R, но он мне нужен для Python или Matlab.


person mrgloom    schedule 14.10.2013    source источник
comment
Как ограничить потребление памяти приложением, которое использует эту процедуру, до некоторого значения, например до 100 МБ. Вы имеете в виду, что если приложение пытается использовать больше памяти, оно должно потерпеть неудачу? Использовать psutil.set_rlimit это просто, но, НАСКОЛЬКО, это работает только на Linux.   -  person Bakuriu    schedule 14.10.2013
comment
Нет, я имею в виду, что приложение должно работать как обычно, но использовать меньше заявленной памяти (вообще говоря, это будет медленнее с меньшим объемом памяти, но это полезно, когда мы хотим ограничить использование памяти приложения или если у нас недостаточно памяти, чтобы вместить все матрица). И я работаю на винде.   -  person mrgloom    schedule 14.10.2013
comment
Ваша строка res не имеет смысла (а res - самый большой массив ...). Перечитайте np.dot строку документации, вы найдете что-нибудь полезное ...   -  person seberg    schedule 15.10.2013
comment
что ты имеешь в виду? выходное значение должно быть C-смежным? а np.memmap для этого не подходит? или что?   -  person mrgloom    schedule 15.10.2013
comment
или ты про переопределение? и это должно быть res [:] =?   -  person mrgloom    schedule 15.10.2013
comment
Может быть, есть какое-то оптимальное решение для умножения больших матриц, хранящихся на диске? Hadoop es.wikipedia.org/wiki/MapReduce michael-noll.com/tutorials/   -  person inigoD    schedule 15.10.2013
comment
Я имею в виду, что вы не используете memmap, потому что для этого вам придется использовать аргумент out. Так что никакой res[...] = ... не этого сделает.   -  person seberg    schedule 15.10.2013
comment
О, и хотя это лучше в более новых версиях numpy, хотя первое транспонирование не копирует данные, точка может ожидать C-смежные массивы также для ввода, так что вам, вероятно, не следует транспонировать его (или безопасно в порядке fortran, а затем перенести в порядок c). Конечно, в целом могут быть варианты получше.   -  person seberg    schedule 15.10.2013
comment
Я не понимаю, это должно быть np.dot (fp0, tr, res)?   -  person mrgloom    schedule 18.10.2013
comment
Вы можете ограничить ресурсы, доступные для вашей программы, с помощью инструмента AppVerifier. Установите размер частного рабочего набора.   -  person RolKau    schedule 15.09.2015


Ответы (2)


Dask.array предоставляет интерфейс numpy для больших массивов на диске с использованием заблокированных алгоритмов и планирование задач. Он может легко выполнять умножение матриц вне ядра и другие простые операции.

Заблокированная линейная алгебра сложнее, и вы можете проверить некоторые академические работы по этой теме. Dask поддерживает факторизацию QR- и SVD-кодов на тонких и высоких матрицах.

Независимо от больших массивов, вам действительно нужны заблокированные алгоритмы, а не наивные обходы, которые будут неприятно поражать диск.

person MRocklin    schedule 01.05.2015

Рассмотрите возможность использования NumExpr для обработки: https://github.com/pydata/numexpr

... внутри NumExpr использует свою собственную векторизованную виртуальную машину, которая разработана на основе стратегии чтения по частям, чтобы эффективно работать с блоками данных оптимального размера в памяти. При правильной настройке он может легко превзойти наивные операции NumPy.

NumExpr может покрыть № 2 в вашем разбивке по проблеме. Если вы обращаетесь к №1, используя потоковый двоичный формат, вы можете использовать метод чтения фрагментов при загрузке файлов данных - например, так:

    with open('path/to/your-data.bin', 'rb') as binary:
        while True:
            chunk = binary.read(4096) # or what have you
            if not chunk:
                break

Если это слишком низко для вас, я бы порекомендовал вам взглянуть на библиотеку HDF5 и формат: http://www.h5py.org - это лучшее решение для двоичной сериализации структур на основе NumPy, о котором я знаю. Модуль h5py поддерживает сжатие, чтение по частям, типы данных, метаданные ... вы называете это.

Удачи!

person fish2000    schedule 08.05.2014
comment
Я не совсем понимаю, где numexpr можно использовать в умножении матриц, можете ли вы развернуть ответ и предоставить пример использования? Да, я знаю о hdf5 и pytables, но numpy.memmap более удобен, потому что его можно использовать как обычный массив numpy. - person mrgloom; 08.05.2014
comment
numpy.memmap - это операция "все или ничего", да?… Я предлагал hdf5, поскольку он поддерживает разбиение на части и потоковый ввод-вывод: hdfgroup.org/HDF5/doc/Advanced/Chunking/index.html - хотя простая загрузка тех же данных с помощью HDF5 может быть медленнее, чем файлы с отображением памяти, фрагментированное чтение в цикл обработки на основе фрагментов может быть более эффективным способом, который вы ищете. - person fish2000; 08.05.2014
comment
Что касается NumExpr, я не знаю, предлагает ли он оператор скалярного произведения, но я знаю, что он даст вам более быстрые операции просмотра - если бы вы переделали свои операции с массивом с помощью NumExpr, вам может не понадобиться, например, транспонирование, требующее больших затрат памяти. - person fish2000; 08.05.2014