Ошибки памяти и ограничения списка?
Мне нужно производить большие и большие (очень) матрицы (цепи Маркова) для научных целей. Я выполняю исчисление, которое я помещаю в список из 20301 элемента (= одна строка моей матрицы). Мне нужны все эти данные в памяти, чтобы перейти к следующему шагу Маркова, но я могу хранить их в другом месте (например, в файле), если это необходимо, даже если это замедлит мой обход цепи Маркова. Мой компьютер (научная лаборатория): Биксенон 6 ядер /12 нитей каждый, 12 ГБ памяти, ОС: win64
Traceback (most recent call last):
File "my_file.py", line 247, in <module>
ListTemp.append(calculus)
MemoryError
Пример результатов исчисления: 9.233747520008198e-102 (да, больше 1/9000)
Ошибка возникает при сохранении 19766-го элемента:
ListTemp[19766]
1.4509421012263216e-103
Если я пойду дальше
Traceback (most recent call last):
File "<pyshell#21>", line 1, in <module>
ListTemp[19767]
IndexError: list index out of range
Таким образом, этот список имел ошибку памяти в цикле 19767 года.
Вопросы:
Есть ли предел памяти для списка? Это "ограничение по списку" или "глобальное ограничение по сценарию"?
Как обойти эти ограничения? Любые возможности в виду?
Поможет ли это использовать numpy, python64? Какие у них пределы памяти? А как насчет других языков?
4 ответа
Прежде всего, посмотрите, насколько большим может стать массив Python? и Numpy, проблема с длинными массивами
Во-вторых, единственное реальное ограничение связано с объемом вашей памяти и тем, как ваша система хранит ссылки на память. Для каждого списка нет ограничений, поэтому Python будет работать до тех пор, пока не будет исчерпан объем памяти. Две возможности:
- Если вы работаете в более старой ОС или системе, которая заставляет процессы использовать ограниченный объем памяти, вам может потребоваться увеличить объем памяти, к которому имеет доступ процесс Python.
- Разбейте список на части, используя порцию. Например, выполните первые 1000 элементов списка, выберите и сохраните их на диск, а затем выполните следующие 1000. Чтобы работать с ними, извлекайте по одному куску за раз, чтобы не допустить исчерпания памяти. По сути, это тот же метод, который используют базы данных для работы с большим количеством данных, чем умещается в ОЗУ.
MemoryError
Исключение, которое вы видите, является прямым результатом нехватки доступной оперативной памяти. Это может быть вызвано ограничением в 2 ГБ на программу, установленным Windows ( 32-разрядные программы), или отсутствием доступной оперативной памяти на вашем компьютере. (Эта ссылка на предыдущий вопрос).
Вы должны иметь возможность расширить 2 ГБ, используя 64-битную копию Python, при условии, что вы используете 64-битную копию Windows.
IndexError
будет вызвано, потому что Python ударил MemoryError
исключение перед вычислением всего массива. Опять же, это проблема памяти.
Чтобы обойти эту проблему, вы можете попробовать использовать 64-битную копию Python или, что еще лучше, найти способ записать результаты в файл. Для этого посмотрите на отображенные массивы памяти numpy.
Вы должны иметь возможность выполнить весь набор вычислений в одном из этих массивов, поскольку фактические данные будут записаны на диск, и только небольшая их часть будет храниться в памяти.
Python не ограничивает память. Тем не менее, вы получите MemoryError
если у вас не хватает оперативной памяти. Вы говорите, что у вас есть 20301 элементов в list
, Это кажется слишком маленьким, чтобы вызвать ошибку памяти для простых типов данных (например, int
), но если каждый элемент сам по себе является объектом, который занимает много памяти, у вас вполне может быть недостаточно памяти.
IndexError
Однако, вероятно, вызвано тем, что ваш ListTemp
имеет только 19767 элементов (с индексом от 0 до 19766), и вы пытаетесь получить доступ к последнему элементу.
Трудно сказать, что вы можете сделать, чтобы избежать ограничения, не зная точно, что вы пытаетесь сделать. С помощью numpy
может помочь. Похоже, вы храните огромное количество данных. Возможно, вам не нужно хранить все это на каждом этапе. Но это невозможно сказать, не зная.
Если вы хотите обойти эту проблему, вы также можете использовать полку. Затем вы создадите файлы, которые будут соответствовать размеру вашей машины, и будут помещать их в ОЗУ только при необходимости, в основном записывая на HD и собирая информацию по частям, чтобы вы могли обработать ее.
Создайте двоичный файл и проверьте, есть ли в нем информация, если да, создайте локальную переменную для ее хранения, а затем запишите данные, которые вы считаете необходимыми.
Data = shelve.open('File01')
for i in range(0,100):
Matrix_Shelve = 'Matrix' + str(i)
if Matrix_Shelve in Data:
Matrix_local = Data[Matrix_Shelve]
else:
Data[Matrix_Selve] = 'somenthingforlater'
Надеюсь, это не звучит слишком сложно.