До основного вмісту

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

Виділені сервери · · Оновлено · 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-топологія фізичного сервера прокидається у гостьові машини, розглядає стаття віртуалізація на виділеному сервері.

Чи була стаття корисною?
← Назад до бази знань Поставити питання підтримці