Я хочу произвольно большой буфер в Linux / C / C ++ - PullRequest
6 голосов
/ 30 ноября 2011

В основном я хочу, чтобы стек был сколь угодно большим. Я знаю, что это невозможно, но могу ли я выделить для этого несколько терабайт моего виртуального адресного пространства? Я хотел бы иметь возможность начинать с самого начала и увеличивать буфер по мере необходимости, и Linux может по мере необходимости загружать страницы из физической памяти. Возможно ли что-то подобное? Будет ли он иметь такую ​​же производительность, как и просто размещение буфера? Будет ли какой-нибудь способ сообщить Linux, что вы закончили с памятью, как только вы извлечете стек?

РЕДАКТИРОВАТЬ: Я хочу этого, потому что я хочу оптимизировать рекурсивный / параллельный алгоритм, который выделяет много памяти при каждом вызове. Malloc слишком медленный для меня, и я не хочу, чтобы все потоки пересекались друг с другом внутри замков malloc. Таким образом, в основном это был бы мой собственный стек времени выполнения наряду с реальным (один для каждого потока).

На самом деле, пока стек времени выполнения достаточно велик, этого должно быть достаточно. Есть ли способ узнать / обеспечить размер стека? В 64-битном адресном пространстве достаточно места для нескольких потоков, чтобы выделить гигабайты данных в стеке. Это выполнимо?

Похоже, что pthread_attr_setstacksize может работать для новых потоков, но это мало поможет, если вас можно вызвать из любого потока ...

Ответы [ 5 ]

4 голосов
/ 30 ноября 2011

Ну, если вы хотите большой стек, вы всегда можете изменить ulimit -s. Он может быть очень большим, по крайней мере, на 64-битных платформах.

Если вы mmap анонимны, фактически вам не будут выделены физические страницы, пока вы не коснетесь его. Вам нужно будет либо установить vm_overcommit, либо иметь достаточно подкачки (если у вас не так много физической памяти). Конечно, mmap анонимное пространство - это именно то, что malloc делает, когда вы запрашиваете много памяти.

Вы можете сказать Linux, что вы сделали со страницами, используя madvise. Если вы позвоните по номеру MADV_DONTNEED, Linux удалит страницы , и они должны быть заполнены нулями при следующем обращении к ним.

2 голосов
/ 30 ноября 2011

Прежде всего, malloc память такого размера (или new ее или создание в стеке) почти наверняка приведут к ошибке std::bad_alloc, потому что вы пытаетесь создать все это непрерывнопамяти - и у вас определенно нет такого большого количества непрерывной непрерывной памяти из-за фрагментации.

Если вы используете контейнер std::, например, deque, или адаптер контейнера, например, stack (что угоднобез смежной памяти - т.е. не вектора), то он будет использовать кучу памяти в виде кусков, которые можно расширять.Это поможет вам обойти эту ошибку bad_alloc.

Итак, это возможно, но не пытайтесь сделать память непрерывной - и если вам разрешено использовать std:: контейнер / адаптер.

PS: если вам нужны большие объемы памяти, вы можете рассмотреть возможность использования списка динамически распределенных буферов (malloc ed указатели), размер которых достаточно велик, чтобы его можно было использовать, но достаточно мал, чтобы он не срабатывалbad_alloc исключение).

1 голос
/ 30 ноября 2011

Вы можете создать такое распределение, используя mmap() с флагами MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE. Если вы хотите вернуть его обратно в систему, используйте munmap().

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

1 голос
/ 30 ноября 2011

Не забывайте, что ресурсы всегда ограничены физическими ограничениями: число атомов во вселенной, вероятно, конечно ... Так что произвольно большие буферы не могут существовать в строгом смысле слова ...

Однако вы можете использовать системный вызов Linux mmap для просмотра части файла как сегмента виртуальной памяти. Если он очень большой (больше, чем RAM), у вас будут проблемы с производительностью. Попробуйте настроить его с помощью madvise (и, возможно, readahead) системных вызовов.

Может быть, даже использование GCC __ bultin_prefetch может быть полезно (но я уверен, что madvise более уместно).

Если у вас действительно стек размером в терабайты, настройка вашего приложения будет очень важной. Научитесь использовать oprofile . Я надеюсь, что у вас есть мощная машина!

И этого на самом деле недостаточно для стека вызовов (возможно, он ограничен, например, через setrlimit ...) См. Также sigaltstack (для стека, используемого для доставка сигнала).

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

0 голосов
/ 30 ноября 2011
Create stack using two queues in that way you can have variable length of stack, which will increase as you require.

implementing stack using two queues

initially q1 is full and q2 empty
1] tranfer elements from q1 to q2 till last element left in q1
2] loop till q2 is not empty
deque element from q2 and again push in q2 till last element is left in q2
transfer this last element in q1
reduce size of q2 by 1
3]finally q1 contains all elements in reverse order as in stack
eg

1]
q1 = 1 2 3 4
q2 =
2]
3 deques till last element left in q1
q1 = 4
q2 = 1 2 3
3]
deque and again queue q2 till last element left
q1 = 4
q2 = 3 1 2
4] deque q2 and queue q1
q1 = 4 3
q2 = 1 2
5] again
deque and queue q2 till last element left
q1= 4 3
q2= 2 1
6] queue q1
q1= 4 3 2
7] queue last element of q2 to q1
q1= 4 3 2 1 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...