Ошибка памяти Python 2.7 для большой сложности - PullRequest
1 голос
/ 26 января 2012

Я новичок в Python.Я запускаю следующий код, и он дает ошибку памяти с python2.7.Так как я использую opencv, поэтому я работаю с python2.7.Я прочитал предыдущие посты, но я не очень понимаю из них.Код пытается сохранить частоту красного, зеленого и синего компонентов.И для этого я инициализирую эти значения в ноль

Ответы [ 3 ]

5 голосов
/ 26 января 2012

Вещи 1: используйте itertools вместо построения всех списков range каждый раз вокруг цикла. xrange вернет объект итератора, такой как range, а product вернет итератор, выбирающий наборы элементов из заданной итерации.

Вещи 2: используйте numpy для больших данных. Это матричная реализация, разработанная для такого рода вещей.

>>> import numpy as np
>>> from itertools import product
>>> x=np.zeros((256,256,256))
>>> for i, j, k in product(xrange(256), repeat=3):
...     x[i,j,k]= i*j*k
... 

Займет у меня около пяти секунд и ожидаемый объем памяти.

$ cat /proc/27240/status 
Name:   python
State:  S (sleeping)
...
VmPeak:   420808 kB
VmSize:   289732 kB

Обратите внимание, что на самом деле вы можете столкнуться с ограничениями памяти в масштабе всей системы, если попытаетесь выделить три 256 * 256 * 256 массивов, поскольку каждый из них содержит около 17 миллионов записей. К счастью, numpy позволяет сохранять массивы на диск.

Сталкивались ли вы с PIL (Python Imaging Library) ? Вы можете найти это полезным.

1 голос
/ 26 января 2012

На самом деле вашей программе нужно как минимум (!) 300 * 300 * 300 * 4 * 3 байта исключительно для значений данных из dicts. Кроме того, ваши кортежи ключей занимают 300 * 300 * 300 * 3 * 3 * 4 байта.

Это всего 1296000000 байт или 1,2 ГиБ данных.

Этот расчет даже не включает накладные расходы на поддержание данных в диктовке.

Таким образом, это зависит от количества памяти, которое имеет ваша машина, если она выходит из строя или нет.

Вы могли бы сделать первый шаг и сделать

s = {}
ns = {}
ts = {}
for i in range(0, 300):
    for j in range(0, 300):
        for k in range(0, 300):
            index=(i, j, k)
            s[index]=j
            ns[index]=k
            ts[index]=i*j*k

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


Из того, что вы описываете (вам нужен простой подсчет), вам не нужно предварительно инициализировать полный диапазон комбинаций. Таким образом, вы можете опустить вашу инициализацию, показанную в вопросе, и вместо этого создать хранилище, где вы храните эти значения только там, где у вас действительно есть данные, которых, предположительно, гораздо меньше, чем возможно.

Вы можете либо использовать defaultdict(), либо подражать его поведению вручную, так как я думаю, что большинство комбинаций не используются в вашей цветовой «палитре».

from collections import defaultdict
make0 = lambda: 0
s = defaultdict(make0)
ns = defaultdict(make0)
# what is ts? do you need it?

Теперь у вас есть три dict -подобных объекта, которые могут быть записаны в случае необходимости. Затем для каждой комбинации цветов, которые у вас действительно есть, вы можете сделать s[index] += 1 соотв. ns[index] += 1.

Я не знаю о вашем ts - возможно, вы либо сможете рассчитать его, либо вам придется найти другое решение.

0 голосов
/ 26 января 2012

Даже если все ваши переменные используют один байт, этой программе потребуется 405 МБ ОЗУ.

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

Редактировать: если вы хотитечтобы создать гистограмму в Python, см. этот прекрасный пример использования библиотеки изображений Python (PIL) .Тяжелая работа сделана с этими 3 линиями:

import Image
img = Image.open(imagepath)
hist = img.histogram()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...