LINUX.ORG.RU

Узнать доступный для malloc'а объем памяти


0

1

Подскажите, можно ли как-нибудь, кроме выделения большего объема памяти, чем нужно, и контроля возвращенного malloc'ом на не-NULL, узнать, сколько памяти я смогу выделить.

// хочу распараллелить одну штуку, хорошо кушающую память, но для этого до вызова N потоков надо выяснить допустимый объем памяти и как минимум мегабайт 50 оставить, а остальной объем W разделить на N1 буферов размером S и отдать каждый буфер в свой поток (один из N1)

☆☆☆☆☆

Ответ на: комментарий от unsigned

Фигню там какую-то пишут, например, сейчас:

MemFree:          141488 kB
однако, когда я запускаю свою программулину, отжирающую при сложных преобразованиях двести с лишним мегабайт, ничего страшного не происходит.

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

/proc/meminfo не прокатит. Узнать то, что вы хотите практически очень сложно, т.к. ядро использует для этого определенные алгоритмы, учитывающие объем памяти, дисковых кэшей, свопа и т.п. Погугли overcommit_memory.

no-such-file ★★★★★
()
Ответ на: комментарий от Eddy_Em

Насколько я понимаю, Buffers и Cached - тоже доступная память.

unsigned ★★★★
()

Если оверкоммит включен, то ядро считает память бесконечной.

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

Фигню там какую-то пишут

Смотри на CommitLimit и Committed_AS.

geekless ★★
()

Помню, тоже хотел такую фичу, но так и не нашел решение.

buddhist ★★★★★
()

geekless, no-such-file, спасибо.

Т.е. выходит, что наверняка знать, что произойдет при выделении очередной малюсенькой порции в полгигабайта оперативки не получится?

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

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

такие действия могут привести к краху системы?

В теории: при нехватке памяти ядро убьет наиболее «невыгодный» процесс. Если твоя программа использует большие объемы ОЗУ, её и прибьёт.

На практике: иногда система уходит в бесконечный своппинг. (Даже при отсутствии свопа, да.)

Если для твоей программы критично, чтобы можно было в явном виде обработать ошибку а ля «память не выделилась, сделаем что-нибудь разумное на имеющейся памяти и завершим работу», то пускай её с выключенным оверкоммитом. (В этом случае программа получит NULL из malloc, а не внезапный SIGKILL.)

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

что произойдет при выделении очередной малюсенькой порции в полгигабайта оперативки не получится?

Тут, в общем случае вообще нет гарантий, т.к.:

1.Вы проверяете любым способом объем доступной памяти.
2.Другая программа выделяет себе 1Гб
3.Вы пытаетесь выделить себе объем, который узнали в п.1
4.FAIL

no-such-file ★★★★★
()
Ответ на: комментарий от geekless

В теории: при нехватке памяти ядро убьет наиболее «невыгодный» процесс

Знаю, только oom-killer, похоже, убивает все подряд, а не самый проблемный процесс (я с таким уже часто сталкивался, но чаще всего сначала убивались никого не трогающие иксы).

пускай её с выключенным оверкоммитом

А как это программно реализовать?

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от no-such-file

В принципе, да. Но возможна и другая ситуация: я выделил гигабайт, потом освободил полгигабайта и работаю с оставшимися 512МБ (но мне в процессе еще понадобятся мегабайт 50..100), однако, как только я в очередной раз захочу выделить следующую порцию в пару-тройку килобайт, памяти «вдруг» не хватит, т.к. кто-то другой ее уже сожрал...

Да уж, даже не знаю, как более-менее прилично решить эту проблему.

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

Знаю, только oom-killer, похоже, убивает все подряд, а не самый проблемный процесс (я с таким уже часто сталкивался, но чаще всего сначала убивались никого не трогающие иксы).

oom-killer подкручивать можно, в тч запретить убивать определенный процесс

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

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

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

Да уж, даже не знаю, как более-менее прилично решить эту проблему

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

no-such-file ★★★★★
()

Я конечно не разработчик, но как админ выскажусь У процесса виртуальное адресное пространство (размер зависит от архитектуры). В его пределах и выбирается свободный кусок. Как ядро мапит его на адресные страницы и где они находятся ( в памяти или свопе ) программе пофиг. Как уже сказали, при vm.overcommit=0 ядро будет позволять программе выделять память, пока есть свободное ОЗУ + своп. Потом начнёт работать OOM Killer.

Насколько я понимаю, для программисту нужно либо

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

2) предложить пользователю ввести размер памяти , которую захавает приложение. Ну или админу в конфиге, если это демон

router ★★★★★
()

В линуксе malloc всегда возвратит не-NULL.

By default, Linux follows an optimistic memory allocation strategy. This means that when malloc() returns non-NULL there is no guarantee that the memory really is available. This is a really bad bug. (c) man malloc

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

oom-killer подкручивать можно, в тч запретить убивать определенный процесс

С этого места по-подробнее, пожалуйста.

anonymous
()
Ответ на: комментарий от no-such-file

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

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от anonymous

Если хип фрагментирован, он может вернуть NULL. Виртуальная память не бесконечна.

anonymous
()

malloc всегда возвращает какой-то указатель, но память реально не выделаяет. Когда процесс к ней обращается проихсодит сегфолт, но ядро знает, что процесс этот адрес затребовал раньше, поэтому не снимает процесс, а выделяет ему страницу из доступных свободных страниц. Дальше делает маппинг и возвращает управление процессу. Если процесс память не выделял перед сегфолтом - то ядро посылает процессу sigsegv. Выделенную malloc() память ядро не считает, а считает только реально выделенные процессам страницы. Поэтому невозможно точно сказать, сколько там у тебя памяти свободно. Но на сколько я знаю оомкиллер в линуксе вообще можно отключить, тогда всё будет работать кропаль медленее, и можно узнать сколько malloc() затребовал всего. Но опять таки, ситация, что после того как процесс узнал, сколько свободно памяти другой процесс её всю «забил», никто не отменял. Я бы даже сказал, что отключать оомкиллер не нужно. Короче, нехватка памяти програмистов в линуксе волновать не обязана, это проблема юзера или администратора. Но именно по-этому программист для линукса должен быть весьма адекватным и объективно мыслящим человеком, но я смотрю в последнее время это не так.

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

Для твоих целей тебе надо сложить MemFree, Buffers и Cached. Тебе будет счастье, лору спокойствие.

anonymous
()

а ты проверил - есть ли выигрыш работы твоей программы от большого количества потоков ?
не ограничится ли количеством ядер проца * 2 ?
может сабж решать и незачем

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

Простое применение openMP увеличивает скорость для тестового изображения с 1.25с до 0.75с. Если грамотно распараллелить, вполне возможно, что еще быстрее можно сделать.

Хотя, конечно, это не десятки секунд...

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от nanoolinux

Выделенную malloc() память ядро не считает, а считает только реально выделенные процессам страницы

А реально выделенные страницы, это какие? Кроме того, если следовать вашей логике, что будет если в системе с 1.2Гб памяти:

1.Один процесс выделил себе 1Гб, но не использует его.
2.Другой процесс выделил себе 1Гб и использовал.
3.Первый процесс хочет использовать свой законно полученный гигабайт.
4.FAIL

Вы, как мне кажется, не вполне понимаете механизм пейджинга.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Всё именно так как вы описали, только конец истории другой.

3. Первый процесс хочет использовать свой законно полученный гигабайт, но свободных страниц нет, поэтому ядро запускает оомкиллер, который начинает прибивать разные процессы (жертвы выбираются хитрым алгоритмом;), до тех пор пока не получит требуемое количество свободных страниц. Если оомкиллер уже всех поубивал, кроме этих двух процессов, то тогда и только тогда fail.

nanoolinux ★★★★
()
Ответ на: комментарий от no-such-file

/proc/meminfo не прокатит. Узнать то, что вы хотите практически очень сложно, т.к. ядро использует для этого определенные алгоритмы, учитывающие объем памяти, дисковых кэшей, свопа и т.п. Погугли overcommit_memory.

Ну так ядро не знает и не может знать, сколько памяти может выделить malloc.

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

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

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

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

Ядро это знает, но это мало соотносится с тем, что вернет malloc.

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

«в glibc на линуксе malloc всегда возвратит не-NULL»

4.2

насколько я знаю, при выделение большого куска, аллокатор glibc напрямую вызывает mmap.

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

mmap может не выделить память. Адресное пространство не бесконечно.

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

Этот дефолт зависит не от маллока, а от [кривых] рук дистроклепателя/админа.

Я знаю.

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

Один раз во время загрузки системы? Если я всё правильно понял, то это не защитит от той ситуации, когда я попытаюсь выделить 2 Gb, malloc() вернёт указатель != NULL, но при попытке использовать эту пямять через 10 секунд от момента malloc()-a программа упадёт, т.к. ядро не распределяло реально эту память, и её увёл кто-то более хитрый.

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

От такой ситуации защищает только полная вырубка оверкоммита.

LamerOk ★★★★★
()

Насчет своего вопроса сообщаю: тестирование алгоритма при распараллеливании показало очень маленький прирост производительности, поэтому вопрос пока отпал.

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

Eddy_Em ☆☆☆☆☆
() автор топика
Ответ на: комментарий от anonymous

И действительно, так быстрее будет.

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