Почему я получаю OverflowError и WindowsError с numpy memmap и как это решить?

В отношении моего другого вопроса -a-numpy-array?noredirect=1#comment56918583_34581021" title="MemoryError">здесь этот код работает, если я использую небольшой фрагмент моего набора данных с dtype='int32', а использование float64 приводит к TypeError< /strong> в моем основном процессе после этой части из-за правил safe, поэтому я буду работать с int32, но, тем не менее, мне любопытно, и я хочу знать об ошибках, которые я получаю.

fp = np.memmap("E:/TDM-memmap.txt", dtype='int32', mode='w+', shape=(len(documents), len(vocabulary)))
matrix = np.genfromtxt("Results/TDM-short.csv", dtype='int32', delimiter=',', skip_header=1)
fp[:] = matrix[:]

Если я использую полные данные (где shape=(329568, 27519)) с этими dtypes:

Я получаю сообщение OverflowError при использовании int32 или int

и

Я получаю WindowsError при использовании float64

Почему и как я могу это исправить?

Изменить: добавлены трассировки

Трассировка для int32

Traceback (most recent call last):
File "C:/Users/zeferinix/PycharmProjects/Projects/NLP Scripts/NEW/LDA_Experimental1.py", line 123, in <module>
    fp = np.memmap("E:/TDM-memmap.txt", dtype='int32', mode='w+', shape=(len(documents), len(vocabulary)))
File "C:\Python27\lib\site-packages\numpy\core\memmap.py", line 260, in __new__
    mm = mmap.mmap(fid.fileno(), bytes, access=acc, offset=start)
WindowsError: [Error 8] Not enough storage is available to process this command

Трассировка для float64

Traceback (most recent call last):
File "C:/Users/zeferinix/PycharmProjects/Projects/NLP Scripts/NEW/LDA_Experimental1.py", line 123, in <module>
    fp = np.memmap("E:/TDM-memmap.txt", dtype='float64', mode='w+', shape=(len(documents), len(vocabulary)))
File "C:\Python27\lib\site-packages\numpy\core\memmap.py", line 260, in __new__
    mm = mmap.mmap(fid.fileno(), bytes, access=acc, offset=start)
OverflowError: cannot fit 'long' into an index-sized integer

Изменить: добавлена ​​другая информация

Другая информация, которая может помочь: у меня есть жесткий диск объемом 1 ТБ (931 ГБ для использования) с 2 разделами, диск D (22,8 ГБ без 150 ГБ), где мои рабочие файлы включают это script и где будет записана карта памяти и Диск E (406 ГБ свободно из 781 ГБ), где хранятся мои торрент-материалы. Сначала я попытался записать файл mmap на Диск D, и он сгенерировал файл 1 903 283 КБ для int32 и 3 806 566 КБ. strong> файл для float64. Я подумал, может быть, из-за того, что на нем не хватает места, поэтому я получаю эти ошибки, поэтому я попробовал Диск E, которого должно быть более чем достаточно, но он сгенерировал файл того же размера и выдал ту же ошибку.


person ZeferiniX    schedule 04.01.2016    source источник
comment
Вы не сможете прочитать этот файл за один раз, используя np.genfromtxt — результирующий массив займет ~ 36 ГБ ОЗУ, используя int32, и вдвое больше для int или float64. Смысл использования массива с отображением в память здесь заключается в том, что он позволяет вам читать файл небольшими фрагментами, а затем записывать каждый фрагмент в массив с отображением в память, чтобы вам не приходилось хранить все это в памяти сразу. Взгляните еще раз на мой ответ здесь, чтобы увидеть, как это может работать.   -  person ali_m    schedule 04.01.2016
comment
@ali_m добавил трассировку для int32 и float64, оба отчета memmap.py   -  person ZeferiniX    schedule 04.01.2016
comment
@ali_m У меня есть жесткий диск объемом 1 ТБ (доступно 931 ГБ) с 2 разделами, Drive D (22,8 ГБ без 150 ГБ)`, где мои рабочие файлы включают этот скрипт и где будет записана карта памяти, и Drive E ( 406 ГБ бесплатно из 781 ГБ), где хранятся мои торренты. Сначала я попытался записать файл mmap в Drive D, и он сгенерировал txt-файл 1 903 283 КБ для int32 и 3 806 566 КБ txt-файл для поплавок64. Я подумал, может быть, из-за нехватки места, поэтому я получаю эти ошибки, поэтому я попробовал Drive E, которого должно быть более чем достаточно, но он сгенерировал тот же размер файла и выдал ту же ошибку.   -  person ZeferiniX    schedule 04.01.2016
comment
@ali_m готово, я использую 32-битную версию numpy.   -  person ZeferiniX    schedule 04.01.2016
comment
@ali_m Извините за двусмысленность, да, я имею в виду файл, сгенерированный np.memmap. Я добавил расширение .txt, когда создавал файл, поэтому я принял его за txt-файл, мой плохой.   -  person ZeferiniX    schedule 04.01.2016


Ответы (1)


Я не думаю, что можно сгенерировать такой большой файл np.memmap, используя 32-битную сборку numpy, независимо от того, сколько у вас места на диске.

Ошибка возникает, когда np.memmap пытается внутренне вызвать mmap.mmap. Второй аргумент mmap.mmap указывает длину файла в байтах. Для массива 329568 на 27519, содержащего 64-битные (8-байтовые) значения, длина будет составлять 72555054336 байт (т. е. ~ 72 ГБ).

Значение 72555054336 необходимо преобразовать в целочисленный тип, который можно использовать в качестве индекса. В 32-битном Python индексы должны быть 32-битными целыми значениями. Однако наибольшее число, которое может быть представлено 32-битным целым числом, намного меньше 72555054336:

print(np.iinfo(np.int32(1)).max)
# 2147483647

Даже для 32-битного массива потребуется длина 36277527168 байт, что примерно в 16 раз больше, чем самое большое представимое 32-битное целое число.

Я не вижу простого способа обойти эту проблему, кроме перехода на 64-битный Python/numpy. Есть и другие очень веские причины для этого — 32-битный Python может адресовать максимум 3 ГБ ОЗУ, даже если на вашей машине доступно 8 ГБ.


Даже если бы вы могли сгенерировать np.memmap такого большого размера, следующая строка

matrix = np.genfromtxt("Results/TDM-short.csv", dtype='int32', delimiter=',', skip_header=1)

определенно потерпит неудачу, поскольку требует создания массива в ОЗУ размером 32 ГБ. Единственный способ, которым вы могли бы прочитать этот CSV-файл, - это более мелкие фрагменты, как в моем ответе здесь, на который я ссылался в комментарии выше.

Как я уже упоминал в комментариях к вашему другому вопросу, вам следует преобразовать матрицу TermDocumentMatrix в матрицу scipy.sparse, а не записывать ее в файл CSV. Это потребует гораздо меньше места для хранения и ОЗУ, поскольку можно использовать тот факт, что почти все счетчики слов имеют нулевое значение.

person ali_m    schedule 04.01.2016
comment
Я вижу, имеет смысл. Спасибо за точные расчеты и объяснение! Вероятно, откажусь от этого подхода, поскольку он неэффективен. Я не знаю никаких других способов поработать над этим, прежде чем я начал спрашивать, сначала попробую scipy.sparse, прежде чем переключиться на 64-битный numpy, если это не удастся, еще раз спасибо! - person ZeferiniX; 04.01.2016
comment
Стоит научиться делать такие вычисления, так как они могут быстро сказать вам, возможно ли то, что вы пытаетесь сделать. - person ali_m; 04.01.2016