WedX - журнал о программировании и компьютерных науках

Мне нужен произвольно большой буфер в Linux/C/C++

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

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

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

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

29.11.2011

  • Что не так с std::stack? 30.11.2011
  • Я бы посоветовал, если вам нужен произвольно большой стек, запрашивать это, а не спрашивать, как, по вашему мнению, вы хотите действовать. Или здесь есть какое-то другое ограничение? 30.11.2011

Ответы:


1

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

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

29.11.2011

2

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

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

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

29.11.2011
  • Так что, если я установлю vm_overcommit, а затем mmap() терабайт анонимного пространства, я смогу начать его использовать? Есть ли много накладных расходов в madvise (поскольку он заполняет страницы нулями)? 30.11.2011
  • @Chris: нулевое заполнение фактически выполняется при первом доступе к странице. Его можно отключить, но обычно это делается из соображений безопасности — чтобы убедиться, что память, освобожденная одним процессом (или ядром), не может быть прочитана другим. Имейте также в виду, что vm_overcommit не может помешать вам фактически исчерпать память (если у вас нет 1 ТБ ОЗУ/подкачки), и вы пытаетесь получить доступ ко всему этому, вероятным результатом будет SIGKILL. 30.11.2011
  • Потрясающе спасибо! Итак, я посмотрел на madvise() и не нашел способа сказать, что я закончил с этими страницами, поэтому удалите их следующими, если вам когда-нибудь понадобится место, не утруждайте себя копированием их для обмена местами. Похоже, это, вероятно, не поддерживается ... 01.12.2011
  • @Chris: Это то, что делает MADV_DONTNEED. Предполагая, что ядро ​​восстанавливает страницы (что произойдет, если есть какая-либо нехватка памяти или, может быть, даже если нет): если вы сопоставили фактический файл, в следующий раз, когда вы будете использовать страницы, файл будет перечитан; если вы сопоставили анонимное пространство (с MAP_ANONYMOUS), то в следующий раз, когда вы будете читать страницы, они будут заполнены нулями (чтобы избежать раскрытия предыдущего содержимого физической памяти, которая в последний раз могла использоваться другим приложением) 01.12.2011
  • Обратите внимание, что вы можете использовать флаг MAP_NORESERVE для mmap(), чтобы запросить поведение в стиле избыточной фиксации для определенного сопоставления, даже если избыточная фиксация отключена. 02.12.2011

  • 3

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

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

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

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

    29.11.2011
  • Это не так в 64-битном Linux. Предполагая, что у вас есть подкачка (или физическая память) для его поддержки, несколько ТБ непрерывного адресного пространства не проблема. 30.11.2011
  • То же самое я думал и о Windows, хотя у меня нет ничего, что могло бы это подтвердить. Разве это не одна из главных причин, по которой у нас есть виртуальная память? Я знаю, что раньше выделял 2 ГБ векторов на своей 32-битной машине с Windows. 30.11.2011
  • Возможно, я несколько раз сталкивался с bad_alloc при выделении пространства, намного меньшего, чем в Linux (подобной) установке, которую мы используем на работе. Я думаю, это больше зависит от платформы, чем я думал. 30.11.2011
  • Возможно, у вас установлены какие-то ограничения ресурсов, или, может быть, у вас отключен vm_overcommit и недостаточно свопа, чтобы включить его. Но найти несколько ТиБ в виртуальном адресном пространстве 256 ТиБ, которое есть у современных 64-битных процессоров, не должно быть сложно. 30.11.2011

  • 4

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

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

    Возможно, даже использование функции GCC __bultin_prefetch может оказаться полезным (но я уверен, что madvise более актуально).

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

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

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

    29.11.2011
  • Он нигде не говорит о стеке вызовов. Просто стек 30.11.2011
  • Новые материалы

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

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

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

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

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..


    Для любых предложений по сайту: [email protected]