Russian Qt Forum

Компиляторы и платформы => Linux => Тема начата: QtCoder от Декабрь 02, 2011, 08:35



Название: Выделение памяти большими кусками
Отправлено: QtCoder от Декабрь 02, 2011, 08:35
Пытаюсь выделить 2 Gb — fail.
2 раза по 1 Gb — success.
Понятно, что виновата фрагментация памяти.
А как узнать максимально доступный непрерывный кусок? Из user-mode.
Смотрел /proc/self/maps — там о регионах ничего нет.
То есть, я оттуда могу получить информацию об общем числе незамапленных регионов, но увидеть непрерывный кусок не могу.

$cat /proc/self/maps
08048000-0804c000 r-xp 00000000 03:01 122897 /bin/cat
0804c000-0804d000 rwxp 00004000 03:01 122897 /bin/cat
0804d000-0806e000 rwxp 0804d000 00:00 0 [heap]
b7e6e000-b7ea0000 r-xp 00000000 03:01 165044 /usr/share/locale/KOI8-R/LC_CTYPE

В области 0806e000 — b7e6e000 размещаются выделяемые гигабайты. Общая сумма области порядка 3 Gb.
Ковыряние в /proc/self/mem может как-то помочь в поиске непрерывного региона?

Пример карты пямяти:

Address Kbytes Mode Offset Device Mapping
020e9000 97660 rwx-- 00000000020e9000 000:00000 [ anon ]
//skipped
09cca000 2832036 rwx-- 0000000009cca000 000:00000 [ anon ]
//skipped
b7f6e000 97660 rwx-- 00000000b7f6e000 000:00000 [ anon ]

Сначала я выделил 1+1+0.7 Gb. Оно разместилось по адресу 09cca000
Дальше я попытался выделить 200 Mb — фэйл.
Выделил 2 раза по 100 Mb. Они разместились по адресам 020e9000 и b7f6e000, т.е. в совершенно разных местах.

Мне нужно узнать — сколько я могу максимально выделить памяти за 1 раз? При наличии фрагментации.


Название: Re: Выделение памяти большими кусками
Отправлено: Bepec от Декабрь 02, 2011, 08:55
Кхм. максимально доступный непрерывный кусок? хз как узнать :)

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

Встает вопрос - оно вам надо? Что вы хотите сделать?


Название: Re: Выделение памяти большими кусками
Отправлено: QtCoder от Декабрь 02, 2011, 09:15
vmmap для Windows видели?
http://technet.microsoft.com/en-us/sysinternals/dd535533 (http://technet.microsoft.com/en-us/sysinternals/dd535533)

Он показывает в том числе и свободные непрерывные регионы.
Куски именно такого размера можно выделять .
Под win это делается с помощью VirtualQuery достаточно просто (благодаря Рихтеру).
Задача сделать под linux. Из юзер-мода. Модуль ядра не годится, хотя среди функций ядра есть функции типа find_vma.

Зачем, я хочу написать менеджер памяти способный управляться с фрагментированной памятью.


Название: Re: Выделение памяти большими кусками
Отправлено: BRE от Декабрь 02, 2011, 09:54
В malloc.h определена следующая структура и функция:
Код
C++ (Qt)
struct mallinfo
{
 int arena;    /* non-mmapped space allocated from system */
 int ordblks;  /* number of free chunks */
 int smblks;   /* number of fastbin blocks */
 int hblks;    /* number of mmapped regions */
 int hblkhd;   /* space in mmapped regions */
 int usmblks;  /* maximum total allocated space */
 int fsmblks;  /* space available in freed fastbin blocks */
 int uordblks; /* total allocated space */
 int fordblks; /* total free space */
 int keepcost; /* top-most, releasable (via malloc_trim) space */
};
 
/* Returns a copy of the updated current mallinfo. */
extern struct mallinfo mallinfo (void) __THROW;
 


Название: Re: Выделение памяти большими кусками
Отправлено: QtCoder от Декабрь 02, 2011, 10:32
В malloc.h определена следующая структура и функция:
Судя по
Цитировать
You can get information about dynamic memory allocation by calling the mallinfo function. This function and its associated data type are declared in malloc.h; they are an extension of the standard SVID/XPG version.

— Data Type: struct mallinfo

This structure type is used to return information about the dynamic memory allocator. It contains the following members:

int arena
This is the total size of memory allocated with sbrk by malloc, in bytes.

int ordblks
This is the number of chunks not in use. (The memory allocator internally gets chunks of memory from the operating system, and then carves them up to satisfy individual malloc requests; see Efficiency and Malloc.)

int smblks
This field is unused.

int hblks
This is the total number of chunks allocated with mmap.

int hblkhd
This is the total size of memory allocated with mmap, in bytes.

int usmblks
This field is unused.

int fsmblks
This field is unused.

int uordblks
This is the total size of memory occupied by chunks handed out by malloc.

int fordblks
This is the total size of memory occupied by free (not in use) chunks.

int keepcost
This is the size of the top-most releasable chunk that normally borders the end of the heap (i.e., the high end of the virtual address space's data segment).

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


Название: Re: Выделение памяти большими кусками
Отправлено: QtCoder от Декабрь 02, 2011, 10:34
В общем, говорят из user-space нельзя узнать.
http://stackoverflow.com/questions/4401912/linux-contiguous-physical-memory-from-userspace

Только из кернела


Название: Re: Выделение памяти большими кусками
Отправлено: Igors от Декабрь 02, 2011, 11:50
Узнать максимальный свободный регион отсюда нельзя.
Захватывать/узнавать максимальный свободный регион - (поза)вчерашний день. Мне пришлось избавляться от такой техники, т.к. она не только не ускоряет, но и наоборот, дает тормоза. А написать менеджер - дело хорошее, мне в одном проекте тоже приходится это делать  :)


Название: Re: Выделение памяти большими кусками
Отправлено: QtCoder от Декабрь 02, 2011, 12:00
Узнать максимальный свободный регион отсюда нельзя.
Захватывать/узнавать максимальный свободный регион - (поза)вчерашний день. Мне пришлось избавляться от такой техники, т.к. она не только не ускоряет, но и наоборот, дает тормоза. А написать менеджер - дело хорошее, мне в одном проекте тоже приходится это делать  :)

Не поделитесь секретом устаревшей техники?


Название: Re: Выделение памяти большими кусками
Отправлено: BRE от Декабрь 02, 2011, 12:53
В общем, говорят из user-space нельзя узнать.
http://stackoverflow.com/questions/4401912/linux-contiguous-physical-memory-from-userspace
Только из кернела
Здесь про физическую память говорят, а процессы живут в виртуальной памяти. Процесс может попросить ядро разместить нужное количество физических страниц для его кучи, какие это будут страницы и где они будут реально располагаться в физической памяти для процесса значения не имеет.

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

Для 64 битных систем размер непрерывного куска может быть ну очень большим и значительно превышать размер реальной памяти вместе со всеми свопами. :)


Название: Re: Выделение памяти большими кусками
Отправлено: Igors от Декабрь 02, 2011, 13:20
Не поделитесь секретом устаревшей техники?
Расскажу, хотя это вряд ли что Вы хотите. Были старые проекты, написаны еще на Mac classic. В них выделялся наибольший кусок и внутри него велась своя куча. Да, тогда это работало ощутимо быстрее по сравнению с обычным new/malloc. Но с переходом на OSX (POSIX) появились проблемы. Ф-ция MaxBlock (если я правильно помню) перестала существовать. Выяснилось что на попытку выделить > 1 Gb возвращается NULL (это может специфика конкретного OC). Возился долго, пробовал vmalloc, лазил в станицах, лочил и.т.п.  Это тоже было давненько и всех деталей я не помню, но смысл один: даже если удается все посадить "резидентно" - результат печальный по производительности  :'(

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



Название: Re: Выделение памяти большими кусками
Отправлено: QtCoder от Декабрь 02, 2011, 13:27
В общем, говорят из user-space нельзя узнать.
http://stackoverflow.com/questions/4401912/linux-contiguous-physical-memory-from-userspace
Только из кернела
Здесь про физическую память говорят, а процессы живут в виртуальной памяти. Процесс может попросить ядро разместить нужное количество физических страниц для его кучи, какие это будут страницы и где они будут реально располагаться в физической памяти для процесса значения не имеет.

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

Для 64 битных систем размер непрерывного куска может быть ну очень большим и значительно превышать размер реальной памяти вместе со всеми свопами. :)


Ядро может отказать в выделении памяти при отсутствии блока необходимого размера.
Цитировать
Связано это с тем, что первые 2ГБ виртуального адресного пространства процесса фрагментированы, разбиты на непрерывные области, и при попытке зарезервировать область памяти больше имеющейся приложение говорит, что недостаточно памяти.
http://forall.ru-board.com/egor23/online/FAQ/Virtual_Memory/Limits_Virtual_Memory.html (http://forall.ru-board.com/egor23/online/FAQ/Virtual_Memory/Limits_Virtual_Memory.html)
Там про винду, но думаю справедливо и для linux.

Задача такая - нужно работать с большими изображениями. Нужно знать - поместится ли оно в память. Если нет - что-то с этим делать. Что именно пока не знаю.
Либо пытаться дефрагментировать память, либо картинку распихивать по разным местам.

 


Название: Re: Выделение памяти большими кусками
Отправлено: QtCoder от Декабрь 02, 2011, 13:29
Не поделитесь секретом устаревшей техники?
Расскажу, хотя это вряд ли что Вы хотите. Были старые проекты, написаны еще на Mac classic. В них выделялся наибольший кусок и внутри него велась своя куча. Да, тогда это работало ощутимо быстрее по сравнению с обычным new/malloc. Но с переходом на OSX (POSIX) появились проблемы. Ф-ция MaxBlock (если я правильно помню) перестала существовать. Выяснилось что на попытку выделить > 1 Gb возвращается NULL (это может специфика конкретного OC). Возился долго, пробовал vmalloc, лазил в станицах, лочил и.т.п.  Это тоже было давненько и всех деталей я не помню, но смысл один: даже если удается все посадить "резидентно" - результат печальный по производительности  :'(

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


Хорошая функция MaxBlock  ;D
Раз Вы про Mac, я про Windows. Под Windows нет проблемы найти максимальный блок - есть функция VirtualQuery.
Но мы про Linux...


Название: Re: Выделение памяти большими кусками
Отправлено: Igors от Декабрь 02, 2011, 13:36
Задача такая - нужно работать с большими изображениями. Нужно знать - поместится ли оно в память. Если нет - что-то с этим делать. Что именно пока не знаю.
Либо пытаться дефрагментировать память, либо картинку распихивать по разным местам.
Ну здесь менеджер памяти ни при чем - надо делать подкачку страницами (своими). Кстати даже если оно якобы "поместится" - то часто лучше бы не помещалось - тормоза могут быть ужасны


Название: Re: Выделение памяти большими кусками
Отправлено: BRE от Декабрь 02, 2011, 13:51
Там про винду, но думаю справедливо и для linux.
Там про 32 системы, в которых максимальный адресуем размер ограничивается 4Gb.
В зависимости от платформы процессу остается доступно для linux - 3 Gb, для венды - 2 Gb. В эту память все и должно поместиться: код, статические данные, стек и куча.

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


Название: Re: Выделение памяти большими кусками
Отправлено: Bepec от Декабрь 02, 2011, 13:59
BRE меня опередил.

Работа с большими изображениями всегда осуществляется нарезкой и разбитием. Тут даже где то тема была про это. :)


Название: Re: Выделение памяти большими кусками
Отправлено: QtCoder от Декабрь 02, 2011, 14:01
BRE меня опередил.

Работа с большими изображениями всегда осуществляется нарезкой и разбитием. Тут даже где то тема была про это. :)

Нарезкой каким размером? Каким-то фиксированным или по размерам доступных блоков в памяти?


Название: Re: Выделение памяти большими кусками
Отправлено: BRE от Декабрь 02, 2011, 15:12
Нарезкой каким размером? Каким-то фиксированным или по размерам доступных блоков в памяти?
Тут тебе лучше знать. :)
Например, можно загружать кусок изображения равное размеру окна для его отображения (или чуть больше) или разделить изображение на тайлы скажем 100x100 точек (а может 1000x1000) и загружать нужные тайлы из которых составлять видимую часть изображения.
Что программа будет делать с этими изображениями?


Название: Re: Выделение памяти большими кусками
Отправлено: Bepec от Декабрь 02, 2011, 15:15
Зависит от твоего желания и того, что ты будешь делать. Если показывать, то нужно будет в размер видимой области + 8 полей в памяти боковых для быстрой подгрузки :)


Название: Re: Выделение памяти большими кусками
Отправлено: Igors от Декабрь 02, 2011, 15:23
Нарезкой каким размером? Каким-то фиксированным или по размерам доступных блоков в памяти?
В общем случае - размер блока кратен 4K, остальное зависит от задачи. Неплохо напр блок 64K. 32-битный имедж прекрасно "вписывается", для др могут оставаться неиспользуемые "хвостики", это нормально. Использование QCache значительно упрощает подгрузку. Конечно "заголовки" всех страниц сидят в памяти