LINUX.ORG.RU

В какой момент освобождается память?

 


0

1

Использую python для решения всяких вычислительных задач по работе. Опыта пока не много.

Иногда возникает ситуация, когда не хватает 4 гига оперативной памяти, в связи с этим возникает следующий вопрос: очень часто в процессе работы программы используются временные переменные, которые изменяются в теле цикла и могут содержать много данных, а после цикла уже не нужны совсем. Собственно вопрос: когда они уничтожаются gc? Сразу по окончанию цикла (если их имя не упоминается дальше в коде)? Или только в конце выполнения (обычно всё выполение занимает несколько минут)? Нужно ли им делать del вручную?

★★★★★

Последнее исправление: vitruss (всего исправлений: 1)

Иногда возникает ситуация, когда не хватает 4 гига оперативой памяти

4Г? Странная цифра.

когда они уничтожаются gc?

Когда исчезает последняя ссылка. Когда именно это происходит - вопрос тонкий. Проще перейти на 64-битовую систему (даже если у тебя всего 4Г ОП).

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)

Собственно вопрос: когда они уничтожаются gc?

ответ: хрен его знает. Как карта ляжет.

Нужно ли им делать del вручную?

помнится в одном кривом проекте на пхп я делал unset(). Помогало.

emulek
()

Если большие объемы данных и 4 гб озу не хватает, то лучше перейти на более «низкий» язык, где ты сможешь сам управлять памятью.

Lilly
()
Ответ на: комментарий от NeverLoved

Проще перейти на 64-битовую систему (даже если у тебя всего 4Г ОП).

Зачем, если не секрет?

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

tailgunner ★★★★★
()
Ответ на: комментарий от Lilly

Если большие объемы данных и 4 гб озу не хватает, то лучше перейти на более «низкий» язык

В нем float волшебным образом занимает не 4 байта, а 1? %)

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

В нём можно не молиться на GC и его славную волю. Правда, само ручное управление сложное, неудобное и требует определенных навыков, конечно, тут не поспорю.

Но советовать ТС-у поставить 64 бита и докупить памяти это как-то... Какой-то экстенсивный подход, что-ли.

Lilly
()
Ответ на: комментарий от Lilly

В нём можно не молиться на GC и его славную волю.

А ты не подумал, что у ТС может быть просто много данных, и даже виртуозное ручное управление памятью ничего не даст?

Но советовать ТС-у поставить 64 бита

Смешно слышать это от человека, который предлагает переписать программу с Python на Си. «Поставить 64 бита» - это поставить 64-бит ядро (в любом приличном дистре есть готовое) и установить 64-бит систему в chroot, контейнер или VM.

и докупить памяти

Где ты увидел совет докупить памяти?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

А ты не подумал, что у ТС может быть просто много данных, и даже виртуозное ручное управление памятью ничего не даст?

Если у него *такое* количество данных, то ему нужна рабочая станция для расчетов в крайнем случае.

Хотя, исходный вопрос ТС совсем-совсем о другом.

Lilly
()
Ответ на: комментарий от Lilly

Если у него *такое* количество данных, то ему нужна рабочая станция для расчетов в крайнем случае.

Какая еще станция, 2014 год на дворе. У меня в ноуте 16G. Перемолоть 5-6G можно и в 4G физической памяти.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

В нем float волшебным образом занимает не 4 байта, а 1? %)

в нём float занимает не более 4х байт, а не волшебным образом в разы больше. Но не обязательно для этого спускаться именно на другой яп, в каком-нибудь numpy мб есть более оптимальные типы.

mashina ★★★★★
()
Ответ на: комментарий от mashina

в нём float занимает не более 4х байт, а не волшебным образом в разы больше

А где он занимает больше?

Python 2.7.3 (default, Mar 14 2014, 11:57:14) 
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> M=1024*1024
>>> a=[12.34]*(500*M)

в результате выделено 2G памяти

numpy

А что, кто-то пишет вычисления на Python _без_ numpy? Никогда не встречал.

tailgunner ★★★★★
()

Нужно ли им делать del вручную?

Всегда можно провести эксперимент. Можно делать del, записывать None или выносить код, который использует эти временные данные, в отдельную ф-ю. Просто однажды заюзанная переменная в ф-ии может не освобождаться до выхода из её области видимости. Питон в общем случае не может понять, что объект дальше не будет использоваться и его можно уничтожить раньше. Т.е. если код не побит на ф-ии и все временные объекты создаются в общем скопе, то жить будут до конца работы программы.

mashina ★★★★★
()
Ответ на: комментарий от tailgunner

А где он занимает больше?

Очевидно, 4 байта у тебя занимает ссылка (т.е. один void* на машине) на 1 питоно-float объект. У тебя там нет 500M разных float объектов. Нужно проверять как-то так

a = [ float(x) for x in xrange(500 * 2**20)]
у меня получается около 24 байт на float объект.

mashina ★★★★★
()
Последнее исправление: mashina (всего исправлений: 1)
Ответ на: комментарий от mashina

Очевидно, 4 байта у тебя занимает ссылка (т.е. один void* на машине) на 1 питоно-float объект

Да, я был неправ. Но расчеты на встроенных списках Python не пишут еще по многим причинам.

tailgunner ★★★★★
()

Неужели у тебя одни только переменные столько занимают?

djambeyshik ★★★★★
()
Ответ на: комментарий от tailgunner

Где ты увидел совет докупить памяти?

На 64битной ОС оверхед на каждый питоно объект увеличится ещё в раза полтора. Если действительно использует много данных в виде мн-ва мелких объектов, то на 64битной платформе ему будет уже не хватать 6Гб

mashina ★★★★★
()
Ответ на: комментарий от tailgunner

См. выше.

Что туда смотреть? Один numpy все подобные проблемы не решает. «Вычисления» это не только ~FLOPы.

mashina ★★★★★
()
Ответ на: комментарий от mashina

Что туда смотреть?

Туда смотреть насчет оверхеда по памяти на 64-бит системе.

Один numpy все подобные проблемы не решает

Назови «все подобные проблемы» поименно. Или хотя бы Топ5.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Назови «все подобные проблемы» поименно. Или хотя бы Топ5.

Проблема здесь всего одна - питон не умеет эффективно и правильно хранить в памяти ни один из типов объектов. Соответственно начинать оптимизацию нужно с поиска оптимальных конейнеров (или делать такие своими силами) Для некоторых классов задач подходит numpy, но далеко не для всех.

mashina ★★★★★
()
Ответ на: комментарий от mashina

Проблема здесь всего одна

А я уж подумал, что их хотя бы две.

питон не умеет эффективно и правильно хранить в памяти ни один из типов объектов.

Python вполне эффективно хранит свои объекты, numpy полне эффективно хранит свои. В чем _конкретно_ претензия к неэффективности хранения float в numpy? Тебе нужен какой-то особый порядок элементов, не Си и не Fortran?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Python вполне эффективно хранит свои объекты, numpy полне эффективно хранит свои. В чем _конкретно_ претензия к неэффективности хранения float в numpy? Тебе нужен какой-то особый порядок элементов, не Си и не Fortran?

Когда-нибудь избавишься от привычки стнавоится дурачком к концу треда?

mashina ★★★★★
()
Ответ на: комментарий от mashina

В чем _конкретно_ претензия к неэффективности хранения float в numpy? Тебе нужен какой-то особый порядок элементов, не Си и не Fortran?

Когда-нибудь избавишься от привычки стнавоится дурачком к концу треда?

Ты на вопрос ответь.

tailgunner ★★★★★
()
Ответ на: комментарий от NeverLoved

Зачем, если не секрет?

там говноgc лучше работает. Его сама страничная организация x86 поддерживает. Ну т.е. можно выделить Over9000Mb памяти, и положить с прибором на её освобождение.

emulek
()
Ответ на: комментарий от tailgunner

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

а это, кстати, уже от рук зависит.

emulek
()
Ответ на: комментарий от tailgunner

В нем float волшебным образом занимает не 4 байта, а 1?

не, 0. Когда он не нужен, его можно отдать обратно системе.

emulek
()
Ответ на: комментарий от emulek

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

а это, кстати, уже от рук зависит.

Ну да, ну да... виртуальную память придумали безрукие.

Когда он не нужен, его можно отдать обратно системе.

Вау. Почти как в Python.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от mashina

На 64битной ОС оверхед на каждый питоно объект увеличится ещё в раза полтора.

кстати, это теория, или ты реально проверял?

emulek
()
Ответ на: комментарий от tailgunner

Ну да, ну да... виртуальную память придумали безрукие.

её придумали _для_ безруких. Нет, серьёзно, конечно ручное управление памятью это Ъ, но вот времени и сил оно занимает _очень_ много. И в 95% это всё ради экономии жалких 1000 байт в куче.

emulek
()
Ответ на: комментарий от emulek

виртуальную память придумали безрукие.

её придумали _для_ безруких

Бетти, если будешь часто притворяться тупым - станешь реально тупым. Или уже стал.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Это ясно, просто я это батти читал, а Бетти - вполне себе имя

esandmann
()
Ответ на: комментарий от emulek

кстати, это теория, или ты реально проверял?

Каждый объект это минимум (size_t, void*, data) в CPython - счётчик ссылок, указатель на объект типа и сами данные. Можешь сам оценить увеличение памяти для простых объектов, data для которых 4-8 байт. Всякие списки это массивы из void*. В общем, весь оверхед обычно состоит из size_t и void* типов размер которых зависит от разрядности. И таки да, с фактическими значениями это совпадает.

mashina ★★★★★
()
Ответ на: комментарий от tailgunner

Ты на вопрос ответь.

Попробуй сначала его задать как-то осмысленно и желательно контексто связанно со всем остальным.

mashina ★★★★★
()
Ответ на: комментарий от mashina

Всякие списки это массивы из void*.

вот это спорно: если я в пайтоне сделал простой массив int32_t, то почему интерпретатор не может использовать действительно массив int32_t, и индексировать его тем же int32_t?

ЗЫЖ я не в курсе, просто интересно, почему такая оптимизация невозможна/не применяется?

ЗЗЫЖ float'ы кстати и в африке, и в amd64 4х байтные. Смысл им навешивать void* в 8 байт?

emulek
()
Ответ на: комментарий от emulek

вот это спорно: если я в пайтоне сделал простой массив int32_t, то почему интерпретатор не может использовать действительно массив int32_t, и индексировать его тем же int32_t?

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

Итого, при желании можно хранить компактно некоторые простые типы, но нельзя делать на них «компактные» ссылки. Ссылка на элемент в таком массиве будет фактически чиселкой, которая в питоне представляется как отдельный объект со всеми оверхедами.

Т.е. если нужно будет харнить много и ссылаться мало (т.е. на весь массив сразу или на диапазон), то иногда закостылить можно. Но если и ссылаться нужно много (~ все int32_t разбросаны по разным объектам и ествественным образом массива не образуют), то уже ничего в рамках питона не сделать.

float'ы кстати и в африке, и в amd64 4х байтные

float это всего лишь символьная строчка за которой кроется некоторое многозначное понятие. В частности, это может быть IEEE754 float, а может быть и какая-то другая реализация FP типа.

Смысл им навешивать void* в 8 байт?

В питоне всё завёрнуто в объекты, с float'ом из кода можно работать только через объект.

mashina ★★★★★
()
Ответ на: комментарий от mashina

спасибо за консультацию по пайтону.

float это всего лишь символьная строчка за которой кроется некоторое многозначное понятие. В частности, это может быть IEEE754 float, а может быть и какая-то другая реализация FP типа.

ну в общем случае — да. Хотя сейчас везде IEEE754 AFAIK.

emulek
()
Ответ на: комментарий от crowbar

Спасибо за наглядные примеры!

vitruss ★★★★★
() автор топика

Всем спасибо за разьяснения :) прочитал много всего интересного. Надеюсь поможет оптимизировать рассчёт.

vitruss ★★★★★
() автор топика
Ответ на: комментарий от mashina

Так вся суть numpy что там сишные массивы. Поверх них уже собственные numpy-аналоги memoryview которые позволяют с ними работать напрямую из питона.

true_admin ★★★★★
()

Сделай подкласс от ndarray. Или класс, который включает ndarray. Переопредели __del__, вставь в него print, и всё. Ты будешь видеть, когда именно он уничтожается, соответственно освобождается память. :)

yvv ★★☆
()
Ответ на: комментарий от yvv

Ну да, я уже подумал, что по аналогии с примерами выше можно отслеживать что удалилось, а что нет.

vitruss ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.