Как выделить "огромные" страницы для приложения С++ в Linux
У меня есть приложение С++ для Linux, которое очень чувствительно к задержкам. Мое использование памяти составляет около 2 ГБ, поэтому с 4kb-страницами и 64 записями TLB я собираюсь встретить пропуски TLB.
Я читал в руководствах разработчиков Intel, что "огромные" страницы размером 2 МБ (или 4 МБ?) уменьшают количество записей TLB наполовину, поэтому увеличение диапазона памяти компенсирует сокращение записей в TLB, и было бы лучше для производительности.
Как распределить память с помощью "огромных" страниц в приложении на С++? Есть ли компромиссы, о которых я должен знать?
Мой Linux - это дистрибутив Red Hat.
Ответы
Ответ 1
Я предполагаю, что вам нужны огромные страницы только для конкретного приложения, написанного на С++, иначе вы просто измените размер страницы своей системы. Ниже метод будет отлично работать для приложений, написанных на любом языке.
-
Чтобы использовать огромные страницы для конкретного приложения, вам нужно построить ядро для поддержки огромной поддержки страниц. вы должны создать ядро с параметрами CONFIG_HUGETLBFS
-
Укажите размер страницы, указав
hugepagesz=<size>
в командной строке загрузки
-
Чтобы узнать, как установить параметры загрузки: http://www.cyberciti.biz/tips/10-boot-time-parameters-you-should-know-about-the-linux-kernel.html
-
Чтобы установить no из огромных страниц, используйте
# echo 20 > /proc/sys/vm/nr_hugepages
-
Чтобы проверить огромные страницы (доступные, итоговые,...)
# cat /proc/meminfo
-
Когда все выше будет хорошо, теперь вам нужно работать с "как использовать эти страницы для конкретного приложения": монтировать файловую систему типа hugetlbfs
как
# mount -t hugetlbfs -o uid=<value>,gid=<value>,mode=<value>,pagesize=<value>,size=<value>,min_size=<value>,nr_inodes=<value> none /mnt/huge
разместите приложение на этом жестком диске /mnt/huge
теперь ваше приложение будет использовать размер страницы, заданный вами!
Подробнее см. https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
Достоинства/недостатки огромных страниц:
Эффективность : благодаря сокращению пропусков TLB, меньшим ошибкам страницы, уменьшению размера таблицы страниц и меньшему количеству переводов
demerits: больше внутренней фрагментации: потеря памяти, большая латентность при обмене (hugetlbfs
страницы не изменяются, их отображение постоянно)
для более подробной информации проверьте https://lwn.net/Articles/359158/
ИЗМЕНИТЬ
Существует также API, позволяющий выделять огромные страницы PLZ-check, возможно, помогает
https://github.com/libhugetlbfs/libhugetlbfs/blob/master/HOWTO
https://lwn.net/Articles/375096/
Ответ 2
Документация "hugetlb" из ядра должна здесь помочь.
Пользователи могут использовать огромную поддержку страниц в ядре Linux, используя либо системный вызов mmap, либо стандартные системные вызовы системной памяти SYSV (shmget, shmat).
и
Примеры
1) map_hugetlb: см. инструменты/тестирование/selftests/vm/map_hugetlb.c
2) greatpage-shm: см. инструменты/тестирование/selftests/vm/vastpage-shm.c
3) largepage-mmap: см. инструменты/тестирование/selftests/vm/vastpage-mmap.c
4) Библиотека libhugetlbfs (https://github.com/libhugetlbfs/libhugetlbfs) предоставляет широкий спектр средств пользовательского пространства, чтобы помочь с огромной страницей > удобство использования, настройки среды и управления.
(Эти пути относятся к дереву источника Linux).
Итак, это в основном сводится к:
- использовать
mmap
с флагом MAP_HUGETLB
- или, сопоставьте файл из установленной файловой системы hugetlb, если он существует
Ответ 3
Вы также можете попытаться использовать прозрачную огромную поддержку страниц, которая доступна на любом ядре за последние несколько лет (по крайней мере, что-либо в 3.x и 4.x, а также различные ядра 2.6.x).
Основное преимущество заключается в том, что вам не нужно создавать какие-либо специальные "hugetlbfs", они "просто работают". Недостатком является то, что он гарантирован: ядро может удовлетворить ваши распределения огромными страницами, если выполняются некоторые условия, а некоторые доступны. В отличие от hugetlbfs
, который резервирует фиксированное количество огромных страниц при запуске, которые доступны только через определенные вызовы, прозрачные огромные страницы вырезают огромные страницы из общего пула памяти. Для этого требуются смежные 2 МБ блоки физической памяти, которые со временем могут стать редкими из-за фрагментации физической памяти.
Furhtermore, существуют различные настройки ядра, которые влияют на получение огромной страницы или нет, наиболее важным из которых является /sys/kernel/mm/transparent_hugepage/enabled
.
Лучше всего выделить блоки на границе 2 МБ с помощью posix_memalign
, а затем сделать madvise(MADV_HUGEPAGE)
в выделенной области до, касаясь ее в первый раз, Он также работает с такими вариантами, как aligned_alloc
. По моему опыту, в системах с /sys/kernel/mm/transparent_hugepage/enabled
, установленными на always
, это обычно приводит к огромной странице. Тем не менее, я в основном использую системы со значительной свободной памятью и не слишком долгое время.
Если вы используете 2 ГБ памяти, вы, возможно, получите значительную выгоду от огромных страниц. Если вы выделите это все в маленьких блоках, например. через malloc
существует высокая вероятность того, что прозрачные огромные страницы не будут вбиты, поэтому вы также можете рассмотреть возможность выделения в THP-значении способа, использующего основную часть вашей памяти (часто это один тип объекта).
Я также написал библиотеку, чтобы определить, действительно ли вы получили огромные страницы из любого заданного распределения. Вероятно, это не полезно в производственном приложении, но это может быть полезной диагностикой, если вы идете по пути использования THP, поскольку по крайней мере вы можете определить, получили ли вы их или нет.