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

16 хв читання - 16 червня 2026 р.

hero section cover
Зміст
  • Розуміння NUMA та прив'язка процесора для виділених серверів
  • Як працює NUMA на багатопроцесорних серверах
  • Перевірка топології NUMA в Linux
  • Прив'язка до процесора та політики пам'яті
  • Вибір стратегії залежно від навантаження
  • Налаштування BIOS та ядра, які слід перевірити
Поділитися

Як перевірити топологію NUMA та розподілити робочі навантаження Linux між відповідними ядрами та пам'яттю. Охоплює numactl, taskset, systemd, налаштування BIOS та стратегії, специфічні для робочих навантажень.

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

На будь-якому багатопроцесорному сервері місце виконання процесу та місце розташування його пам'яті — це два різних питання, і розсинхронізація між ними — один із найпростіших способів втратити продуктивність. Розуміння NUMA та прив'язка процесора — це два важелі, які вирішують цю проблему. У цій публікації розглядається, як працює NUMA, як перевірити її в Linux та як правильно прив'язати робочі навантаження для баз даних, навчання штучного інтелекту та сервісів, чутливих до затримок.

Як працює NUMA на багатопроцесорних серверах

Вузол NUMA (Non-Uniform Memory Access) — це група ядер процесора, пов’язаних із локальним блоком оперативної пам’яті через спеціальний контролер пам’яті. На двопроцесорному сервері зазвичай є два вузли. Будь-яке ядро може зчитувати будь-яку адресу, але час локального доступу становить приблизно 80 нс, тоді як перехід між сокетами через Intel UPI або AMD Infinity Fabric — близько 130–150 нс. У більших системах з більшою кількістю сокетів найгірший вузол може перевищувати 250 нс.

Пропускна здатність підпорядковується тій самій закономірності. Двосокетна система Sapphire Rapids може підтримувати близько 600 ГБ/с, коли ядра звертаються до локальної пам'яті, але міжсокетний канал становить лише частку від цього, тому трафік, що проходить через нього, швидко створює вузьке місце. Процесори з великою кількістю ядер роблять це більш деталізованим: Sub-NUMA Clustering (SNC) від Intel та Nodes Per Socket (NPS) від AMD розділяють кожен сокет на кілька доменів NUMA, тому «двосокетна» система може легко представити Linux чотири або вісім вузлів.

Без підтримки NUMA планувальник Linux без проблем переміщатиме потік між сокетами, тоді як його робочий набір залишатиметься на початковому вузлі. Кожен наступний доступ стане віддаленим. Видимим симптомом є високе завантаження процесора при низькій фактичній пропускній здатності, оскільки ядра витрачають час на очікування пам'яті. Пристрої вводу-виводу погіршують ситуацію. Графічний процесор або мережева карта підключені до конкретного кореневого PCIe, який належить одному вузлу NUMA. Якщо процес, що їх живить, працює на іншому сокеті, кожен DMA-передача проходить через міжз'єднання.

Перевірка топології NUMA в Linux

Чотири інструменти охоплюють майже все, що вам потрібно:

  • lscpu для швидкого огляду сокетів та вузлів.
  • numactl --hardware для загальних обсягів пам'яті вузлів та матриці відстаней між вузлами.
  • numastat для лічильників влучень/промахів за процесом.
  • lstopohwloc) для ієрархії кешу та локальності пристроїв PCIe.

Почніть з numactl --hardware. Тут перелічено кожен вузол, ядра та пам'ять, що належать до нього, а також матрицю відстаней. Значення 10 означає локальність, 20+ — віддаленість. Якщо ви бачите один вузол на багатопроцесорній системі, у вашому BIOS увімкнено Node Interleaving, що приховує топологію; спочатку виправте це (див. нижче).

Для конкретного процесу numastat -p <PID> розбиває, де фактично розміщена його пам'ять. Важливі чотири лічильники:

  • numa_hit: пам'ять, виділена на призначеному вузлі. Бажано, щоб це значення було високим.
  • numa_miss: призначений вузол був заповнений, виділення розлилося в інше місце.
  • numa_foreign: інший вузол намагався виділити пам'ять локально, але не зміг, що вказує на навантаження на пам'ять.
  • other_node: сторінки, виділені на вузлі, відмінному від того, де виконується процес. Високі значення тут є класичною ознакою поганого прив'язування.

Для робочих навантажень GPU або NIC запустіть lstopo-no-graphics і подивіться, до якого вузла NUMA підключено кожне пристрій PCIe. Якщо ядра, що керують пристроєм, знаходяться на іншому вузлі, це перше, що потрібно виправити.

Прив'язка до процесора та політики пам'яті

Прив'язка процесора (або афінність процесора) прив'язує процес до конкретних ядер, щоб планувальник не міг його перемістити. Самого цього недостатньо, оскільки Linux за замовчуванням використовує політику пам'яті «first-touch»: сторінки виділяються на тому вузлі, який першим записує на них дані. Якщо потік запускається на неправильному вузлі до того, як його прив’яжуть, його пам’ять залишається там. Потрібно контролювати як розміщення, так і виділення разом.

Три інструменти охоплюють типові випадки:

ІнструментКонтрольВикористовується для
tasksetТільки ядра ЦПШвидке одноразове прив'язування існуючого процесу
numactlЯдра ЦП та пам'ятьЗапуск робочих навантажень із суворою локальністю
systemdЯдра ЦП та пам'ять, постійніСлужби, які потребують фіксації між перезавантаженнями

numactl підтримує чотири політики пам'яті:

  • --membind=N: виділяти тільки на вузлі N, у разі переповнення — відмову.
  • --preferred=N: надавати перевагу вузлу N, у разі потреби використовувати інші.
  • --interleave=all: циклічний розподіл між вузлами для рівномірного розподілу пропускної здатності.
  • --localalloc: виділяти на тому вузлі, на якому працює процесор.

Прив'язка робочого навантаження до одного вузла

Спочатку визначте, які ядра належать до вашого цільового вузла:

numactl --hardware

Потім запустіть додаток, прив'язаний до цього вузла як для ядер, так і для пам'яті:

numactl --cpunodebind=0 --membind=0 ./your_application

Для процесу, що вже працює, налаштуйте прив'язку до процесора за допомогою taskset:

taskset -cp 0-7 <PID>

Щоб зберегти налаштування після перезавантаження, вкажіть їх у модулі systemd:

[Service]
CPUAffinity=0-7
NUMAPolicy=bind
NUMAMask=0

Перезавантажте та перезапустіть:

sudo systemctl daemon-reload && sudo systemctl restart <service>

Коли ви прив'язуєте вручну, вимкніть автобалансувальник ядра, щоб він не перешкоджав вашому розміщенню:

sysctl -w kernel.numa_balancing=0

Додайте це до /etc/sysctl.conf для збереження налаштувань. Потім перевірте за допомогою numastat -p <PID> протягом декількох хвилин реального навантаження. Якщо other_node залишається близьким до нуля, фіксація працює.

Вибір стратегії залежно від навантаження

Правильна політика залежить від того, чи для вашого робочого навантаження важливіше низька затримка, чи сумарна пропускна здатність по всіх вузлах.

НавантаженняПолітикаЧому
Бази даних (PostgreSQL, MySQL, SQL Server)--cpunodebind + --membindВеликі спільні буфери, шляхи запитів, чутливі до затримки
Кеш в пам'яті (Redis, Memcached)Прив'язка до одного вузлаВсе відбувається через доступ до оперативної пам'яті, затримка при віддаленому доступі проявляється миттєво
Навчання та інференція AI/MLПрив'язка до вузла NUMA графічного процесораУникнення передачі тензорів через кореневі канали PCIe
Аналітика (Spark, Elasticsearch)--interleave=allВеликий робочий набір потребує пропускної здатності на всіх вузлах
API, чутливі до затримки, торгівляСувора прив'язка до виводів + IRQПередбачуваність важливіша за пікову пропускну здатність
Високе навантаження на мережу (RoCEv2, InfiniBand)Прив'язка до NUMA-вузла мережевої карти, виділення ядер для IRQЗберігає обробку переривань локально та поза межами потоків додатків

Саме для робочих навантажень на графічний процесор запустіть lstopo щоб визначити, на якому вузлі NUMA розташований GPU, а потім запускайте процес навчання або інференції з numactl --cpunodebind=N --membind=N для того самого N. Це один із найпростіших способів отримати виграш на багатопроцесорному сервері з GPU, оскільки розміщення за замовчуванням у планувальнику часто є неправильним.

Для робочих навантажень HPC та MPI, що охоплюють обидва сокети, прив’яжіть кожен ранг до одного вузла за допомогою localalloc , а не переплітаючи все. Кожен ранг отримує локальну пам'ять, і паралелізм відбувається на рівні рангу.

Одне практичне зауваження: якщо ви прив’язуєте до одного вузла, залиште на ньому 2–4 ГБ вільного місця. Вузол, що працює майже на повну потужність, запускає процес звільнення пам’яті, що коштує вам затримки, яку ви намагалися заощадити.

Налаштування BIOS та ядра, які слід перевірити

Точність результатів інструменту залежить від топології, яку надає прошивка. Кілька налаштувань, які слід перевірити:

  • Node Interleaving: вимкніть цю опцію. Коли вона увімкнена, BIOS представляє всю пам'ять як єдиний плоский пул і повністю приховує NUMA від ОС. numactl --hardware У цьому випадку на багатопроцесорному комп'ютері буде показано один вузол.
  • Sub-NUMA Clustering (Intel) або Nodes Per Socket (AMD): увімкніть на процесорах з великою кількістю ядер, якщо вам потрібна більш точна локалізація. Підтверджується lscpu після перезавантаження.
  • vm.zone_reclaim_mode: для більшості виробничих серверів встановіть значення 0. Значення, відмінне від нуля, агресивно звільняє локальну пам'ять замість віддаленого виділення, що може витіснити корисний кеш сторінок.
  • kernel.numa_balancing: залиште увімкненим для робочих навантажень загального призначення, вимкніть, коли ви вручну фіксуєте. Автобалансувальник буде мігрувати сторінки та потоки у спосіб, що суперечить вашій політиці.

Якщо ви виконуєте налаштування NUMA на «голій залізі», де ви контролюєте BIOS, параметри ядра та афінітет IRQ, ви можете застосувати все вищезазначене, не обходячи абстракції гіпервізора. Це головна причина, чому така робота простіша на виділеному апаратному забезпеченні, ніж у хмарних віртуальних машинах.

Щодо багатопроцесорних виділених серверів із повним доступом до root, дивіться виділені сервери FDC.

Блог

На цьому тижні

Більше статей
Налаштовані профілі для оптимізації навантаження на сервер Linux

Налаштовані профілі для оптимізації навантаження на сервер Linux

Як вибирати, застосовувати та налаштовувати налаштовані профілі для графічних процесорів, баз даних та високошвидкісних серверів Linux, з прикладами та порадами щодо розгортання Ansible.

16 хв читання - 9 червня 2026 р.

Налаштування Linux OOM Killer для VPS: практичний посібник

12 хв читання - 8 червня 2026 р.

Більше статей
background image

Маєте запитання або потребуєте індивідуального рішення?

icon

Гнучкі варіанти

icon

Глобальне охоплення

icon

Миттєве розгортання

icon

Гнучкі варіанти

icon

Глобальне охоплення

icon

Миттєве розгортання