К основному содержимому

NUMA на двух процессорах: привязка процессов и память

Выделенные серверы · 29.09.2026 · 5 мин чтения
Иллюстрация к статье «NUMA на двух процессорах: привязка процессов и память»

Что такое NUMA и почему это важно на двух процессорах

NUMA (Non-Uniform Memory Access) — архитектура памяти двухпроцессорного сервера, где у каждого CPU есть "своя" память с быстрым доступом и "чужая" память другого сокета с доступом через межпроцессорную шину. Тема актуальна в первую очередь для серверов с двумя и более сокетами — то, как выбран процессор, напрямую определяет число узлов NUMA и их размер.

Если приложение не учитывает NUMA, планировщик ОС может разместить процесс на одном сокете, а память выделить на другом. Результат — просадка производительности без видимой причины в мониторинге CPU.

Как посмотреть топологию NUMA

lscpu | grep -i numa
numactl --hardware

Команда numactl --hardware покажет количество узлов, объём памяти на каждом и расстояния между узлами (node distances). Значение 10 — обращение к своему узлу, 20-21 — к соседнему: чем выше число, тем дороже промах.

Проблема: память "не своего" узла

Типичный сценарий: сервер на двух процессорах, 256 ГБ памяти, приложение запущено без привязки. Планировщик Linux переносит процесс между ядрами разных сокетов, а выделенная память остаётся на первом узле. Каждое обращение ко второму сокету идёт через межпроцессорный интерконнект, и задержка растёт.

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

Привязка процессов: numactl и cpuset

Явная привязка процесса к узлу решает проблему напрямую:

numactl --cpunodebind=0 --membind=0 /usr/bin/mysqld
numactl --interleave=all /usr/bin/myapp

Флаг --cpunodebind закрепляет процесс за ядрами узла 0, --membind — за памятью того же узла. Флаг --interleave=all распределяет память равномерно по всем узлам — полезно для приложений, которые сами не умеют работать с NUMA и не выигрывают от локальности.

ПараметрЧто делаетКогда использовать
--cpunodebindЗакрепляет ядра узлаСУБД, JVM с большой кучей
--membindЗакрепляет память узлаВместе с cpunodebind
--interleave=allЧередует память по узламNUMA-неосведомлённые приложения
--preferredПредпочитает узел, но не запрещает другиеГибкая нагрузка

NUMA в базах данных и виртуализации

PostgreSQL и MySQL рекомендуют запускать один инстанс на NUMA-узел при больших объёмах памяти либо явно привязывать процесс через numactl, если инстанс один на весь сервер. В виртуализации (KVM, Proxmox) стоит выделять виртуальной машине vCPU и память в пределах одного физического узла — иначе гипервизор столкнётся с той же проблемой межузлового трафика.

Перед изменением привязки измерьте эффект: прогоните тест до и после через sysbench с нагрузкой, близкой к реальной, а не синтетической однопоточной.

Чек-лист настройки NUMA

  • Проверьте topology через numactl --hardware до тюнинга, не после.
  • Привязывайте процесс к CPU и памяти вместе, а не по отдельности.
  • Для NUMA-неосведомлённых приложений используйте --interleave=all вместо ручной привязки.
  • Замеряйте задержки и throughput до и после — прирост не всегда очевиден на слабой нагрузке.

Частые ошибки при работе с NUMA

numactl: Warning: cpu binding outside of valid numa node cpuset

libnuma: Warning: node argument 4 is out of range

mbind: Cannot allocate memory

numactl: command not found
СообщениеПричинаРешение
cpu binding outside of valid numa node cpusetУказанные ядра не принадлежат тому узлу NUMA, для которого задан --membindСверить номера ядер узла через numactl --hardware перед составлением команды
node argument N is out of rangeВ команде указан номер узла, которого физически нет на сервере (например, узел 4 на двухпроцессорной машине с узлами 0 и 1)Проверить реальное число узлов: numactl --hardware | grep available
mbind: Cannot allocate memoryНа запрошенном узле NUMA физически не хватает свободной памяти под жёсткий --membindИспользовать --preferred вместо --membind, чтобы разрешить выделение на другом узле при нехватке
numactl: command not foundПакет numactl не установлен — он не входит в минимальный набор большинства дистрибутивовУстановить пакет: apt install numactl или dnf install numactl

Способы управления NUMA-привязкой: сравнение

СпособУровень примененияКогда использовать
numactl (для одного процесса)Один запускаемый процессБыстрая проверка гипотезы и ручной запуск СУБД или сервиса
cgroups cpusetГруппа процессов, systemd-юнит, контейнерПостоянная привязка сервиса, который перезапускается системой, а не вручную
BIOS Node InterleavingВся система целикомТолько временная диагностика — полностью отключает NUMA, не для продакшна

Когда привязка NUMA не даёт эффекта

  • Сервер однопроцессорный — топология NUMA вырождена в один узел, и numactl --hardware покажет node distance только 10, привязывать нечего
  • Рабочий набор данных приложения меньше памяти одного узла NUMA — планировщик и так почти всегда держит процесс и память рядом без ручного вмешательства
  • Нагрузка сильно многопоточная и равномерно использует все ядра сервера — жёсткая привязка к одному узлу в этом случае снижает параллелизм вместо того, чтобы его ускорить
  • Виртуальная машина уже мигрирует между узлами кластера (live migration) — статическая привязка vCPU к NUMA-узлу физического сервера теряет смысл при переезде на другую машину

Проверка результата

# Локальные и удалённые обращения к памяти по узлам
numastat -p $(pgrep -f mysqld)

# Задержка доступа к памяти до и после привязки
numactl --cpunodebind=0 --membind=0 -- perf stat -e task-clock,cycles ./benchmark

# Итоговое распределение памяти процесса по узлам
cat /proc/$(pgrep -f mysqld)/numa_maps | head -5
  1. Выполните numastat -p PID до и после привязки — доля numa_foreign и other_node должна заметно снизиться
  2. Замерьте целевую метрику нагрузки (запросы в секунду, время ответа) обоими способами — без привязки и с ней — на одинаковом профиле трафика
  3. Проверьте через /proc/PID/numa_maps, что основной объём страниц процесса действительно лежит на ожидаемом узле, а не распределён поровну
  4. Повторите замер через день работы под реальной нагрузкой — синтетический тест сразу после запуска не всегда показывает то же поведение, что установившийся прогрев кэшей

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

Статья помогла?
← Назад в базу знаний Задать вопрос поддержке