Постоянная память (Persistent Memory, PMEM) – это быстрая память, обладающая возможностью хранить данные после отключения питания компьютера. Нередко её называют «Non-Volatile Random Access Memory» (NVRAM) – «энергонезависимой оперативной памятью», или просто «энергонезависимой памятью». Ещё одно наименование такой памяти – NVDIMM. Оно указывает на то, что в состав постоянной памяти входят модули традиционной оперативной памяти.
Иногда мы просто не знаем, какую картинку вставить до ката. И сегодня именно такой случай. Путь будет кот :)
Исторически сложилось так, что приложения организуют данные с использованием двух уровней памяти. Первый – быстрая оперативная память, второй – сравнительно медленные накопители информации. Появление PMEM означает возникновение третьего уровня памяти, занимающего место между первым и вторым.
Работать с новым видом памяти можно так же, как с ОЗУ, используя инструкции процессора по загрузке и сохранению данных.
Путь аппаратных решений, реализующих PMEM, только начинается. Однако, всё указывает на то, что они вполне могут получить широкое распространение. Новая разновидность памяти требует новых подходов к разработке программного обеспечения. Программы сами по себе не могут извлечь выгоду из PMEM, их нужно к этому подготовить.
Если вы – программист, который хочет, как можно раньше, ещё до широкого распространения аппаратных PMEM-решений, приступить к созданию приложений, умеющих работать с новой памятью, вы можете воспользоваться эмуляцией. Такой подход поможет и при обновлении существующих проектов.
Из этого материала вы узнаете о том, как настроить эмуляцию PMEM, используя обычную оперативную память. Выделенная под эмуляцию область ОЗУ будет видна операционной системе как область постоянной памяти. Надо отметить, что в нашем случае, так как эмуляция основана на обычной DRAM, данные из виртуальной PMEM теряются после выключения питания. Однако, скорость работы с эмулируемой памятью будет очень высокой.
Здесь мы будем пользоваться сервером с процессором Intel и ОС семейства Linux с ядром версии 4.3. или выше. Мы расскажем о конфигурировании аппаратного обеспечения, и о том, как настроить программную часть решения. После того, как эмуляция будет настроена, вы сможете испытать примеры PMEM-приложений, которые можно найти в библиотеке NVM на сайте pmem.io.
Аппаратные и программные компоненты
Вот характеристики аппаратного и программного обеспечения, которые использовались для экспериментов.
Компонент | Характеристики |
Процессор | Intel Xeon E5-2699 v4 (2.2 ГГц, 22 ядра, используется одно ядро). |
Чипсет | Intel C610 QS (степпинг B1), системная шина Intel QPI, 9.6 ГТ/с. |
Платформа | Intel Server System R2000WT (Wildcat Pass), 24 слота DIMM, 2 процессорных сокета, блок питания на 1100 Вт. BIOS – GRRFSDP1.86B.0271.R00.1510301446 ME:V03.01.03.0018.0 BMC:1.33.8932 |
Оперативная память | Micron MTA36ASF2G72PZ2GATESIG, 256 Гб (16х16 Гб) DDR4 2133P. |
Накопитель | Western Digital WD1002FAEX, 1 Тб. |
Операционная система | CentOS с ядром 4.5.3 |
Подготовка ядра Linux
В ходе работы использовалось ядро Linux версии 4.5.3. Поддержка устройств постоянной памяти и эмуляции имеется в ядре, начиная с версии 4.0, однако, для того, чтобы упростить настройку системы, рекомендуется пользоваться ядрами версии выше 4.2.
Эмуляция должна работать с любым дистрибутивом Linux, который способен поддерживать официальное ядро. Для того, чтобы установить нужные драйверы, запустите make nconfig.
На рисунках 1 — 5 показан процесс настройки поддержки NVDIMM в меню конфигурации ядра (Kernel Configuration).
$ make nconfig
-> Device Drivers -> NVDIMM Support ->
<M>PMEM; <M>BLK; <*>BTT

Рис. 1. Переход к настройке драйверов устройств

Рис. 2. Настройка поддержки NVDIMM

Рис. 3. Настройка файловой системы для поддержки технологии Direct Access

Рис. 4. Настройка поддержки Direct Access (DAX)

Рис. 5. Параметры поддержки NVDIMM
Ядро предложит области памяти для драйвера PMEM, их можно будет использовать для эмуляции постоянного хранилища. На рисунках 6 — 7 показана настройка параметров процессора и системы.
$ make nconfig
-> Processor type and features
<*>Support non-standard NVDIMMs and ADR protected memory

Рис. 6. Настройка процессора для поддержки NVDIMM

Рис. 7. Включение поддержки нестандартной памяти NVDIMM и памяти, защищённой ADR
Теперь всё готово к тому, чтобы собрать ядро, используя команду, показанную ниже.
$ make -jX
X – это число ядер процессора
Ускорение сборки ядра
Новое ядро можно собрать значительно быстрее, используя несколько потоков. Эксперименты с разным количеством потоков показали, что компиляцию можно ускорить примерно на 95% в многопоточном режиме. В результате настройка нового ядра проходит довольно быстро. На двух рисунках, приведённых ниже, показана загрузка процессора и график, иллюстрирующий воздействие на производительность использования нескольких потоков при сборке ядра.

Рис. 8. Компиляция исходного кода ядра

Рис. 9. Влияние многопоточности на производительность компиляции
Установка и настройка нового ядра
Для установки ядра воспользуйтесь такой командой:
# make modules_install install

Рис. 10. Установка ядра
Теперь зарезервируем область памяти, модифицировав загрузочные параметры ядра. В итоге выбранная область будет выглядеть для операционной системы как постоянная память. Здесь используется команда такого вида:
memmap=nn[KMG]!ss[KMG]
В результате её исполнения будет выделена область памяти в диапазоне от ss до ss+nn. «KMG» – это сокращение для единиц измерения: Kilo, Mega, Giga.
Например, команда вида memmap=4G!12G резервирует 4 Гб памяти между 12-тым и 16-тым гигабайтами. Настройка выполняется в GRUB и различается для разных дистрибутивов Linux. Вот пример конфигурации GRUB для CentOS 7.0.
# vi /etc/default/grub
GRUB_CMDLINE_LINUX="memmap=nn[KMG]!ss[KMG]"
On BIOS-based machines:
# grub2-mkconfig -o /boot/grub2/grub.cfg
На рисунке ниже показана инструкция, касающаяся PMEM, добавленная в GRUB-файл.

Рис. 11. Указание областей для PMEM в файле /etc/default/grub
А вот – процесс сборки конфигурации GRUB.

Рис. 12. Создание файла конфигурации загрузки на основе шаблона grub
После настройки GRUB и перезагрузки компьютера, если всё сделано правильно, можно будет увидеть эмулируемое устройство как /dev/pmem0…pmem3.
Попытка захватить зарезервированные области памяти под эмуляцию постоянной памяти приведёт к разорванным областям, относящимся к постоянной памяти (type 12).

Рис. 13. Области, выделенные под эмуляцию постоянной памяти маркированы как (type 12)
При настройке рекомендуется либо использовать память из диапазона, превышающего 4 Гб (memmap=nnG!4G), либо предварительно проверить карту памяти (через BIOS-e820) и выбрать подходящий диапазон.
Если нужного виртуального устройства в системе не видно, проверьте настройки memmap в файле grub, как показано на рис. 11, затем – проанализируйте состояние памяти с помощью dmesg, как показано на рисунке 13. Если всё настроено правильно, вы увидите зарезервированные области памяти. Здесь могут присутствовать и неперекрывающиеся области, зарезервированные как постоянная память. Если при настройке использовать несколько команд memmap, будут созданы несколько виртуальных устройств, предоставляемых ядром и видимых как /dev/pmem0, /dev/pmem1, /dev/pmem2 и так далее.
Расширения прямого доступа к файловой системе
Расширения прямого доступа (Direct Access, DAX) к файловой системе создают среду, в которой можно работать с PMEM. Некоторые дистрибутивы, такие, как Fedora 24 и её более поздние версии, уже имеют встроенные механизмы DAX/PMEM, там же доступна и библиотека NVM (NVML).
Вот быстрый способ проверить, встроены ли в ядро DAX и PMEM. Для этого можно обработать утилитой egrep конфигурационный файл ядра, который обычно находится в папке /boot дистрибутива:
# egrep ‘(DAX|PMEM)’ /boot/config-`uname –r`
В результате выполнения такой команды будет выведено примерно следующее:
CONFIG_X86_PMEM_LEGACY_DEVICE=y
CONFIG_X86_PMEM_LEGACY=y
CONFIG_BLK_DEV_RAM_DAX=y
CONFIG_BLK_DEV_PMEM=m
CONFIG_FS_DAX=y
CONFIG_FS_DAX_PMD=y
CONFIG_ARCH_HAS_PMEM_API=y
С помощью следующих команд можно установить файловую систему с DAX (сегодня это возможно для ext4 и xfs):
# mkdir /mnt/pmemdir
# mkfs.ext4 /dev/pmem3
# mount -o dax /dev/pmem3 /mnt/pmemdir
Теперь в только что смонтированном разделе можно создавать файлы и передавать в качестве входных данных NVML-пулам.

Рис. 14. Блоки постоянной памяти

Рис. 15. Сборка файловой системы
Стоить отметить, что эмулировать постоянную память можно и с помощью ramdisk (то есть, /dev/shm), или установив переменную окружения PMEM_IS_PMEM_FORCE=1. Это позволит избежать воздействия на производительность, вызванного msync.
Итоги
Теперь вы знаете, как настроить среду, в которой можно создавать приложения, работающие с PMEM, не имея соответствующего аппаратного обеспечения, а используя дополнительные потоки на серверах с архитектурой Intel, вы сможете быстро собрать новое ядро Linux, готовое к экспериментам с постоянной памятью.
Автор: Intel