Чому ігри хочуть один CPU, а рендеринг — інший

Було корисно?

Ви купуєте «монстроподібний» процесор із героїчною кількістю ядер, запускаєте улюблену гру, і… графік FPS нагадує сейсмограф.
Тим часом ваш колега з меншою кількістю ядер та вищою частотою Boost летить. Потім ви переключаєтеся на рендер-джоб і ситуація раптом змінюється:
ваш багатоядерник мчить уперед, а ігровий фаворит колеги задихається.

Це не маркетинговий фокус. Це фізика навантажень: ігри — тирани затримки; офлайн-рендеринг — ненажерливий на пропускну здатність.
Якщо ви керуєте продакшн-системами, ви бачили ту саму кінострічку в іншому залі: одна служба потребує низької хвостової затримки на короткому критичному шляху,
інша потребує агрегованої пропускної здатності по флоту працівників. Процесори не виняток. Оберіть неправильний — і заплатите за силікон, яким не зможете скористатися.

Два навантаження, дві культури: затримка проти пропускної здатності

Ігри й офлайн-рендеринг обидва «використовують CPU», але вимагають від нього різних контрактів.
Ігри піклуються про послідовність часу кадру: час між дією гравця й появою пікселів на екрані.
Рендеринг піклується про час завершення: скільки сэмплів, плиток або фреймів ви опрацюєте за годину.

У термінах SRE: ігри хочуть низької p99 затримки на короткому шляху запиту; рендери прагнуть максимальної кількості запитів за секунду через багато воркерів.
Процесор, що чудово підходить для одного, не автоматично підходить для іншого, бо обмежувальні ресурси різні.

Реальність часу кадру: один запізнілий кадр псує все

Ваш монітор оновлюється з постійним ритмом. Гра має встигнути надати завершений кадр (симуляція + відсіювання + подача на рендер + робота GPU) до дедлайну.
Промах — і гравець бачить підвисання, навіть якщо «середній FPS» виглядає нормально.
Тому ігри цінують:

  • Високу продуктивність на одному потоці для головного потоку (і іноді для одного–двох інших «гарячих» потоків).
  • Швидкі кеші й передбачувану затримку пам’яті.
  • Короткочасні сплески boost-частоти без теплового троттлінгу.
  • Поводження планувальника, що тримає критичний потік на швидкому ядрі й не мігрує його постійно.

Реальність рендерингу: одна повільна плитка — не катастрофа

Більшість офлайн-рендеринг-пайплайнів (CPU ray tracing, кодування, baking, симуляції) можна розбити на шматки.
Плитка, що завершується за секунду пізніше, дратує, але не спричиняє «підвисання». KPI — це пропускна здатність:

  • Багато ядер (часто із SMT), які можуть бути зайняті годинами.
  • Висока стійка частота за всі ядра (не лише героїчний 1‑ядерний boost на 20 мс).
  • Пропускна здатність пам’яті для великих сцен і наборів даних.
  • Топологія NUMA, яка не перетворює вашу RAM на полювання по крос‑сокетних доступах.

Жарт №1: Купувати 64‑ядерний CPU для кіберспорту — це як привезти навантажувач, щоб занести один пакет із продуктами: ефектно, але ви все одно розіллєте молоко.

Що насправді потрібно іграм від CPU

Головний потік усе ще є «шиварою»

Сучасні двигуни значно паралельніші, ніж десять років тому, але більшість усе ще мають «головний потік» (або невелику групу потоків), що контролює прогрес:
логіка геймплею, оновлення сутностей, обходи сцени, подача draw‑викликів, синхронізація та координація.
Якщо цей потік пропускає дедлайн кадру, GPU може простоювати, інші ядра можуть бути зайняті, і все одно буде підвисання.

Слово, яке вам треба — послідовність. Ігри повні цього:
обробка вводу повинна передувати симуляції; симуляція — відсіву видимості; відсів — подачі draw‑викликів.
Так, існують job‑системи та графи задач. Ні, це не робить усе ембаррасинглі паралельним.

Бюджети затримки: 16,67 ms — не рекомендація

На 60 Гц у вас 16,67 мс на кадр. На 120 Гц — 8,33 мс. На 240 Гц ви працюєте на еспресо й жалю.
Цей бюджет ділиться між CPU і GPU, і частка CPU часто становить кілька мілісекунд. Одна кеш‑промах, що призводить до довгого обходу DRAM,
сама по собі не фатальна, але кілька таких разом із міграцією планувальника та фоновим перериванням? Ось і сплеск.

Чому одноядерна продуктивність — це не лише «частота»

Люди коротко називають геймерські CPU «висіклоковими». Частота важлива, але практична формула:
IPC × стійкий boost × поведінка кешу × затримка пам’яті × передбачення переходів × стабільність планувальника.
Ігри стрибають між кодовими шляхами, часто гілкуються, працюють із вказівниками й торкаються великих робочих наборів (стан світу, анімація, broadphase фізики).
Вам потрібно ядро, швидке для «неохайної» роботи, не лише для пікової арифметики.

Кеш: тихий творець відчуття

Багато ігрової продуктивності залежить від питання «залишилися ми в кеші?». Не все, але досить, щоб процесори з більшими або розумнішими кешами
могли показувати помітно кращі часи кадру навіть при схожих частотах.
Великий L3 кеш може:

  • Зменшити звертання в DRAM для даних сутностей/компонентів і систем движка.
  • Поглинати міжпотокову взаємодію (наприклад структури подачі рендеру) з меншими витратами на когерентність.
  • Згладжувати сплески, коли робочий набір тимчасово зростає (вибухи, натовпи, переходи стрімінгу).

Підвисання часто — це історія I/O у вовняній шкурі CPU

Стрімінг текстур, компіляція шейдерів, завантаження активів і декомпресія можуть навантажувати CPU, але тригер часто — це сховище або
фолти сторінок ОС. CPU потім виглядає «завантаженим», але він зайнятий очікуванням, копіюванням, декомпресією або обробкою фолтів.
Якщо ви коли‑небудь гналися за «вузьким місцем CPU», що виявився затримкою сховища — ласкаво просимо у доросле життя.

Що насправді потрібно рендерингу від CPU

Рендеринг любить паралелізм, бо математика чемна

Офлайн-рендеринг (CPU ray tracing, path tracing, офлайн‑GI baking) зазвичай має одиниці роботи, що можуть виконуватися незалежно:
пікселі, плитки, сэмпли, промені, бакети. Залежності є, але внутрішній цикл повторюваний і передбачуваний.
Це «хороший» тип обчислень: CPU може годувати багато ядер, а ОС планувати їх без крихкої потреби в низькій затримці.

Пропускна здатність — це про стійку поведінку, не про маркетингові boost‑частоти

Рендер‑джоби не переймаються тим, чи може ваш CPU досягти 6 ГГц на 50 мс; їх цікавить, що він робить за 50 хвилин.
Це створює тиск на:

  • Стійку всіядну частоту під обмеженнями потужності (PL1/PL2 на деяких платформах).
  • Охолодження, бо теплове дроселювання — це просто «регрес продуктивності з фанатським саундтреком».
  • Пропускну здатність пам’яті для великих сцен, текстур і структур прискорення геометрії.
  • NUMA‑локальність на багатосокетних системах і в дизайні на чіплетах.

Рендерери масштабуються — поки не досягнуть межі

Багато рендерерів добре масштабується до великої кількості ядер, але не нескінченно. Часті фактори, що вбивають масштабування:

  • Конкуренція за замки в аллокаторах пам’яті.
  • Спільні збірки структур прискорення, що серіалізуються.
  • NUMA‑пінг‑понг, коли потоки гуляють між доменами пам’яті.
  • Диск та мережеве I/O: завантаження масивних сцен із шарів може зупиняти воркерів.

Кластерний погляд: ферми рендерингу роблять «правильний CPU» очевидним

На фермі рендерингу ви фактично купуєте пропускну здатність у формфакторі датацентру: ватти, юніти в стійці й ліцензування.
Найкращий CPU часто той, що дає найбільше завершених кадрів за долар за ват, залишаючись стабільним.
Ігрово‑оптимізований CPU, який виграє в одній робочій станції, може програти в стійці, коли реальні обмеження потужності й охолодження враховані.

Жарт №2: Рендеринг — єдина робота, де ви можете підпалити комп’ютер і назвати це «термальною оптимізацією».

Факти й історичний контекст, що досі важливі

Кілька коротких історичних пунктів пояснюють, чому цей розрив існує і чому він тримається:

  1. Звички епохи одноядерних CPU лишилися. У 1990‑х та на початку 2000‑х ігри були здебільшого однопоточними; архітектура рухунків досі несе цей ДНК.
  2. Консолі змусили паралелізувати — але на фіксованому залізі. Розробники оптимізували під відомі числа ядер і поведінку пам’яті, а не під кожну ПК‑топологію.
  3. Епоха DirectX 11 була відомо CPU‑зв’язана. Наклад подачі draw‑викликів робив «швидкий головний потік» головним метриком роками.
  4. Сучасні API зменшили частину накладу, але не видалили координації. Нижчі рівні API перемістили роботу, але не прибрали залежності.
  5. Чіплети зробили затримку топологічною проблемою. Коли ядра розкидані по чіплетах, шаблони доступу до кешу/пам’яті можуть стати помітно нерівномірними.
  6. Гібридні ядра (Big.LITTLE) змінили ставки планування. Змішування швидких і енергоефективних ядер робить розміщення потоків першим за значущістю фактором продуктивності.
  7. SMT став інструментом для пропускної здатності більше, ніж для затримки. Для рендерерів SMT часто дає «майже безкоштовну» пропускну здатність; для ігор іноді погіршує гірший випадок кадру.
  8. Поширення SSD змістило вузьке місце з сирого читання на декомпресію й CPU‑роботу. Завантаження стало швидшим; обробка завантажених даних вийшла на поверхню.
  9. Міри безпеки мали реальні побічні ефекти. Витрати на перехід корінь/користувач і міри проти спекулятивного виконання впливали на деякі навантаження більше, особливо на старіші двигуни.

Мікроархітектура: негламурні причини цього явища

IPC і передбачення переходів: ігри хаотичні, рендерери — повторювані

Ігри виконують різноманітні системи в кожному кадрі: рішення ШІ, контакти фізики, змішування анімацій, скрипти, мережа, стрімінг, UI, аудіо.
Багато гілок. Багато роботи з вказівниками. Багато структур даних.
Це означає, що CPU витрачає час на вгадування подальших дій (branch prediction) і очікує на дані (cache misses).

Рендерери часто мають більш вузький гарячий цикл: перетин променів, шейдинг, сэмплування, акумуляція. Все ще складно, але регулярніше.
Це полегшує роботу CPU, дозволяє краще насичувати конвеєри і компілятор оптимізувати чеґко.

Ієрархія кешу й форма «робочого набору»

Історія кешу відрізняється для навантаження:

  • Ігри: середні‑до‑великих робочих набори з частим повторним використанням у межах кадру; чутливість до затримки; спільний стан движка між потоками.
  • Рендеринг: великі робочі набори (геометрія, текстури), але патерни доступу можуть бути більш стримінговими; вища терпимість до затримки, якщо є багато потоків.

Більший L3 кеш може допомогти обом, але ігри зазвичай відчувають поліпшення «в руці», бо головний потік завжди на один поганий DRAM‑доступ від пропуску кадру.

Затримка пам’яті vs пропускна здатність пам’яті

Ігри зазвичай чутливіші до затримки (скільки часу до першого байта). Рендерери й симуляції можуть бути чутливішими до
пропускної здатності (скільки байт за секунду можна підтримувати), особливо коли багато ядер одночасно «луплять» по пам’яті.

CPU з меншою кількістю ядер, але з нижчою латентністю може виграти в іграх. CPU з більшою кількістю ядер і більшою кількістю каналів пам’яті може виграти в рендері.
Саме тому робочі платформи з додатковими каналами пам’яті блищать у рендер-джобах, навіть якщо «одноядровий» показник на папері схожий.

Обмеження потужності й стійкі частоти: прихований податок

Ігри — імпульсні. Рендеринг — сталі. CPU мають турбо‑поведінку, налаштовану під електричні й теплові ліміти.
Чип, що рекламує дуже високий boost, може тримати його недовго на одному‑двох ядрах.
Це нормально для ігор (якщо головний потік там і не переривається).
Для рендерингу CPU часто падає до нижчої стабільної всіядної частоти, яка керується обмеженнями потужності й охолодженням.

NUMA і чіплети: топологія — це продуктивність

NUMA означає «неоднорідний доступ до пам’яті». Переклад: частина RAM ближча до певних ядер.
На багатосокетних серверах це помітно. На десктопних CPU з чіплетами — тонко, але реально.

Ігри не люблять NUMA‑сюрпризів. Міграція головного потоку між ядрами з різною локальністю кешу може створити сплески часу кадру.
Рендерери можуть терпіти більше топологічних дивностей, бо тримають достатньо потоків у роботі, але вони теж втрачають значну пропускну здатність при невірному розміщенні пам’яті.

SMT (Hyper‑Threading): інструмент пропускної здатності, іноді — ризик для затримки

SMT дозволяє одному ядру запускати два потоки, що ділять ресурси виконання. Це підвищує завантаження й пропускну здатність, коли один потік чекає.
Рендеринг часто виграє. Ігри іноді теж, але ризик у тому, що головний потік конкуруватиме зі своїм «сиблінгом» за ресурси, підвищуючи гіршу затримку.
Якщо вам важливі стабільні часи кадру, протестуйте SMT увімкнено/вимкнено, а не сперечайтесь у мережі.

Гібридні ядра: добра ідея, залежить від планувальника

CPU з продуктивними й енергоефективними ядрами можуть бути чудовими. Але ігри потребують, щоб їхній критичний потік стабільно сидів на швидкому ядрі.
Планувальник ОС має правильно класифікувати навантаження, а гра — поводитися так, як очікує ОС.
Коли це не відбувається, ви отримуєте класичний симптом: «середній FPS нормальний, але гра відчувається не так».

Планувальники, налаштування ОС і чому «той самий CPU» поводиться інакше

Міграція потоків: смерть від тисячі контекстних переключень

Для критичного потоку гри міграція між ядрами може бути дорогою: втрачені теплі кеші, витрати на когерентність і дрібні джиттери від іншої активності.
Планувальник мігрує потоки за балансом навантаження й енергетичними причинами. Це розумно для загального використання.
Але це може бути грубим для навантажень, що залежать від часу кадру.

Переривання і DPC: фоновий шум, що перетворюється на підвисання

Ігри чутливі до випадкової затримки. Шторми переривань, проблеми з драйверами або «шумний» пристрій можуть відбирати час у найневдаліший момент.
У продакшн‑системах ми називаємо це «шумний сусід». На ігровому ПК це «чому він підвисає кожні 12 секунд».

Енергоменеджмент: P‑стани, C‑стани і «чому мій CPU заснув»

Функції енергозбереження корисні, поки латентність пробудження не конкурує з бюджетом кадру. Деякі системи агресивно знижують частоту,
потім потребують часу на підйом. Для рендерингу час розгону не має значення; навантаження постійне і швидко виходить на steady‑state.
Для ігор швидкі переходи можуть створювати джиттер, якщо політика надто консервативна.

Цитата, якою живуть люди з операцій

«Надія — не стратегія.» — генерал Гордон Р. Салліван

Якщо ви обираєте CPU за відчуттями замість профілювання й обмежень, ви буквально розгортаєте на продакшн надію.
Не робіть цього.

Швидкий план діагностики

Мета — не написати дисертацію. Мета — швидко вирішити, де насправді вузьке місце.
Виконуйте це в порядку і зупиняйтеся, коли знайдете «димлячий пістолет».

Перше: вирішіть, чи ви CPU‑зв’язані, GPU‑зв’язані або I/O‑зв’язані

  1. Дивіться часи кадрів, а не FPS. Середні FPS брешуть; сплески часу кадру говорять правду.
  2. Перевірте завантаження і частоти GPU. Якщо GPU завантажено повністю, CPU, мабуть, не ваш ліміт (хіба він погано годує GPU).
  3. Перегляньте завантаження по ядрах CPU. Одне ядро на 100% при інших вільних? Це головний потік гри або драйверний потік.
  4. Перевірте затримки сховища під час підвисань. Хитання стрімінгу часто корелює зі стрибками затримки читання, фолтами сторінок або сплесками декомпресії.

Друге: ідентифікуйте тип обмеження CPU

  1. Обмеження одноядерністю: одне ядро в максимумі, частота висока, але часи кадру все ще стрибають → потрібна краща одноядерна швидкодія, кеш або менше роботи на головному потоці.
  2. Проблема планування / гібридні ядра: навантаження стрибає між ядрами, частота коливається, періодичні підвисання → потрібна стабільність планувальника, афінність або зміни політики енергії.
  3. Обмеження затримкою пам’яті: CPU не повністю завантажений, але лічильники perf показують стагнації, багато LLC‑місів → мають значення кеш/пам’ять і топологія.
  4. Обмеження синхронізацією: багато активних потоків, але низький IPC, багато очікувань → налаштування движка, воркерів, SMT і боротьба з контенцією.

Третє: для рендерингу перевірте масштабування й локальність

  1. Всі ядра зайняті? Якщо ні, вузьке місце — I/O, серіальна фаза або обмеження на кількість потоків у рендері.
  2. Падає частота CPU? Якщо так — проблема потужності/тепла.
  3. Навантаження пам’яті досягає ліміту? Якщо так — додаткові ядра не допоможуть; потрібні додаткові канали.
  4. NUMA: якщо мультисокет або багато чіплетів — перевірте локальність і пінування для рендерера.

Практичні завдання: команди, виводи й рішення

Це реальні завдання, які можна виконати на Linux‑станції або рендер‑ноді. Вони не вирішать усе, але припинять вгадування.
Кожне завдання включає: команду, приклад виводу, що це значить і яке рішення прийняти.

1) Визначте топологію CPU (ядра, потоки, NUMA)

cr0x@server:~$ lscpu
Architecture:                         x86_64
CPU(s):                               32
Thread(s) per core:                   2
Core(s) per socket:                   8
Socket(s):                            2
NUMA node(s):                         2
NUMA node0 CPU(s):                    0-15
NUMA node1 CPU(s):                    16-31
L3 cache:                             64 MiB

Значення: Два сокети, два NUMA‑домену. Крос‑нодовий доступ до пам’яті буде повільніший.

Рішення: Для рендеру: закріпіть воркерів по NUMA‑нодах або запустіть два процеси рендерера, по одному на ноду. Для ігрової машини: уникайте мультисокетних систем; топологія — не ваш друг.

2) Перевірте поточну поведінку частот CPU (чи дійсно ви boost‑уєте?)

cr0x@server:~$ cat /proc/cpuinfo | awk -F': ' '/cpu MHz/ {sum+=$2; n++} END{print "avg_mhz="sum/n}'
avg_mhz=3675.42

Значення: Середня частота по логічних CPU зараз.

Рішення: Якщо гра підвисає й середній MHz низький при спіковому навантаженні, перевірте governor і налаштування енергії. Для рендеру порівняйте середній MHz під повним навантаженням із очікуваним all‑core.

3) Перевірте governor CPU (енергетична політика)

cr0x@server:~$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
powersave

Значення: «powersave» може повільно піднімати частоту залежно від платформи й ядра.

Рішення: Для чутливої до затримки гри або інтерактивної роботи, розгляньте «performance» (або налаштований governor). Для рендер‑нодів «performance» — звично, бо постійне навантаження робить енергозбереження зайвим.

4) Встановити governor на performance (тимчасово, потребує прав)

cr0x@server:~$ sudo sh -c 'for g in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do echo performance > "$g"; done'

Значення: Примушує підтримувати високі частоти, де це підтримується.

Рішення: Якщо сплески часу кадру зменшаться, проблема була в розгоні та політиці енергії. Якщо пропускна здатність рендера покращиться — залишайте на рендер‑нодах і задокументуйте зміну.

5) Спостерігайте завантаження по ядрах і міграції під час підвисання

cr0x@server:~$ mpstat -P ALL 1 5
Linux 6.8.0 (server) 	01/10/2026 	_x86_64_	(32 CPU)

12:00:01 PM  CPU   %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
12:00:02 PM  all   32.1  0.0   4.2   0.1    0.0  0.6    0.0    0.0    0.0   63.0
12:00:02 PM   3    98.0  0.0   1.0   0.0    0.0  1.0    0.0    0.0    0.0    0.0
12:00:02 PM  10    12.0  0.0  10.0   0.0    0.0  0.0    0.0    0.0    0.0   78.0

Значення: CPU3 завантажено, інші — ні. Класичне «головний потік»‑вузьке місце.

Рішення: Не купуйте більше ядер, очікуючи вищого FPS. Купуйте кращу одноядерну продуктивність/кеш або зменшіть налаштування, що важко навантажують CPU (натовпи, відстань симуляції), або налаштуйте обмеження потоків у грі, якщо це можливо.

6) Перевірте I/O‑wait‑сплески (підозра на стрімінг)

cr0x@server:~$ iostat -x 1 3
Linux 6.8.0 (server) 	01/10/2026 	_x86_64_	(32 CPU)

avg-cpu:  %user %nice %system %iowait  %steal   %idle
          18.12  0.00    3.98    0.04    0.00   77.86

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s w_await  aqu-sz  %util
nvme0n1         120.0   64000.0     0.0   0.00    0.78   533.33     8.0    2048.0   1.10    0.09   12.4

Значення: Низький await і %util; сховище не є вузьким місцем у цьому прикладі.

Рішення: Якщо під час підвисань r_await/w_await стрибають у десятки мс — досліджуйте сховище, файлову систему і сторінкову пам’ять — а не «більше CPU».

7) Перевірте тиск пам’яті й великі фолти сторінок

cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0      0 412000  88000 912000    0    0    12    20 4200 9800 28  4 68  0  0
 3  0      0  98000  88000 915000    0    0  8200    40 6500 14000 40  6 53  1  0

Значення: «free» різко впало і «bi» (blocks in) стрибнув: можлива підвантаження пам’яті чи стрімінг.

Рішення: Для ігор: переконайтеся в достатності ОЗП, зменшіть фонові додатки і перевірте, чи гра встановлена на швидкому локальному сховищі. Для рендеру: переконайтеся, що сцени локальні або кешовані; уникайте swap.

8) Визначте найвищих споживачів CPU (і чи це ядро/драйвер)

cr0x@server:~$ top -b -n 1 | head -n 15
top - 12:01:10 up 10 days,  3:22,  2 users,  load average: 6.12, 5.88, 5.70
Tasks: 312 total,   2 running, 310 sleeping,   0 stopped,   0 zombie
%Cpu(s): 31.5 us,  4.2 sy,  0.0 ni, 63.7 id,  0.1 wa,  0.0 hi,  0.5 si,  0.0 st
MiB Mem :  64000.0 total,   1100.0 free,  21000.0 used,  41900.0 buff/cache
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 8421 cr0x      20   0 9123456 2.1g  220m R  185.0   3.4   5:12.33 game-main
 9002 cr0x      20   0 3210000 1.2g  140m S   40.0   1.9   1:01.08 shadercache

Значення: «game-main» використовує ~2 ядра (185% у Linux означає по потоках), але, ймовірно, один потік найгарячіший.

Рішення: Якщо «shadercache» корелює з підвисаннями — розгляньте попередню компіляцію шейдерів і збереження кешу; для рендер‑нодів ізолюйте такі завдання від рендер‑воркерів.

9) Виміряйте троттлінг CPU й теплові ліміти (Intel/AMD по-різному; використовуйте turbostat)

cr0x@server:~$ sudo turbostat --quiet --Summary --interval 2 --num_iterations 2
Summary: 2.00 sec
Avg_MHz   Busy%   Bzy_MHz   PkgTmp  PkgWatt
4120      78.30   5263      92      210.4
Summary: 2.00 sec
Avg_MHz   Busy%   Bzy_MHz   PkgTmp  PkgWatt
3605      96.10   3750      99      165.2

Значення: Температура піднялася до 99°C і частота впала під тривалим навантаженням: троттлінг.

Рішення: Рендер‑ноди потребують кращого охолодження або налаштувань потужності; ігрові машини потребують тонкого налаштування охолодження, якщо boost колапсує під час ігрових сплесків (особливо у CPU‑важких тайтлах).

10) Перевірте NUMA‑локальність і розміщення пам’яті (перевірка рендер‑ноду)

cr0x@server:~$ numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
node 0 size: 32198 MB
node 0 free: 18002 MB
node 1 cpus: 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
node 1 size: 32206 MB
node 1 free: 30110 MB

Значення: Пам’ять розподілена нерівномірно; node0 більше завантажена.

Рішення: Для рендеру розгляньте запуск двох процесів, закріплених по нодах, щоб тримати пам’ять локально. Для інтерактивних навантажень — бажано одиночний сокет.

11) Закріпіть рендер‑джоб до NUMA‑ноди й порівняйте пропускну здатність

cr0x@server:~$ numactl --cpunodebind=0 --membind=0 ./renderer --threads 16 --scene big_scene.json
render: samples/sec=128.4 time=00:10:00

Значення: Цей прогін обмежений node0. Повторіть для node1 і порівняйте.

Рішення: Якщо закріплений прогін краще за незакріплений, ваша ферма потребує NUMA‑усвідомленого планування. Інтегруйте це у runner замість «надії на щастя».

12) Виявлення конкуренції за замки (режим відмови масштабування)

cr0x@server:~$ perf top -p $(pidof renderer) --sort comm,dso,symbol
Samples:  4K of event 'cycles', Event count (approx.): 2560000000
  22.13%  renderer  libc.so.6        [.] pthread_mutex_lock
  14.45%  renderer  renderer         [.] FrameBuffer::AddSample
   9.90%  renderer  renderer         [.] BVH::Intersect

Значення: Багато циклів витрачається на взяття mutex. Це межа масштабування.

Рішення: Збільшіть розмір плитки, використайте буфери на потік або оновіть версію/налаштування рендерера. Купівля додаткових ядер не вирішить проблему з mutex.

13) Перевірте переключення контекстів і шурхіт планування

cr0x@server:~$ pidstat -w -p $(pidof game-main) 1 3
Linux 6.8.0 (server) 	01/10/2026 	_x86_64_	(32 CPU)

12:03:01 PM   UID       PID   cswch/s nvcswch/s  Command
12:03:02 PM  1000      8421   1200.00    450.00  game-main
12:03:03 PM  1000      8421   1305.00    480.00  game-main

Значення: Високі добровільні та недобровільні переключення контекстів можуть вказувати на контенцію, таймерну активність або відскоки планувальника.

Рішення: Зменшіть фонові процеси, перевірте накладки (overlays) і розгляньте ізоляцію ядер (просунута дія). Для рендеру це може свідчити про надто багато потоків або «шумних сусідів» на спільних хостах.

14) Перевірте місце на диску й ризик фрагментації файлової системи (бо кеші рендеру ростуть)

cr0x@server:~$ df -h /mnt/render-cache
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p2  1.8T  1.6T  120G  94% /mnt/render-cache

Значення: 94% заповнений кешовий том. Ви в одному великому сцені від «таємничих збоїв».

Рішення: Впровадьте очищення кешу, розширіть сховище або перенесіть кеш на більший том. Заповнення диска викликає затримки, що виглядають як проблеми CPU.

15) Виміряйте затримку сховища напряму (підозра NFS/SMB у фермі)

cr0x@server:~$ sudo fio --name=readlat --filename=/mnt/render-cache/lat.test --size=1G --rw=randread --bs=4k --iodepth=1 --numjobs=1 --direct=1 --runtime=10 --time_based
readlat: (groupid=0, jobs=1): err= 0: pid=22010: Fri Jan 10 12:05:00 2026
  read: IOPS=12.8k, BW=50.0MiB/s (52.4MB/s)(500MiB/10000msec)
    lat (usec): min=48, max=9210, avg=72.11, stdev=110.32

Значення: Середня латентність нормальна, але max — 9.2 мс. Для ігор такий максимум може бути помітним як підвисання під час стрімінгу; для рендеру це може блокувати багато потоків.

Рішення: Якщо максимальні латентності корелюють зі сповільненнями задач, перемістіть «гарячі» активи на локальний NVMe або додайте шар кешування; не звинувачуйте CPU у чеканні на сховище.

16) Перевірте hugepages і transparent hugepages (поведінка пам’яті для рендеру)

cr0x@server:~$ cat /sys/kernel/mm/transparent_hugepage/enabled
[always] madvise never

Значення: THP увімкнено. Це може допомагати або шкодити залежно від поведінки аллокатора і навантаження.

Рішення: Для рендеру з великими алокаціями THP може допомогти; для інтерактивних навантажень воно може викликати паузи під час дефраг/компакції на деяких системах. Бенчмаркуйте перед зміною.

Три корпоративні історії з польових робіт

Інцидент: хибне припущення («більше ядер вирішить підвисання»)

Студія, з якою я працював, мала внутрішній сервіс «playable build»: кожен коміт створював завантажуваний билд з автоматизованими smoke‑тестами.
Художники скаржились, що билд «жахливо підвисає» на інакше потужних робочих станціях. Керівництво побачило графіки CPU і вирішило, що все просто:
«Потрібно більше ядер.» Закупили партію багатоядерних CPU, орієнтованих на контент‑креацію.

Підвисання не зникло. Воно навіть трохи погіршилося. Кількість тикетів зросла, тепер із додатковим припасом «але це нова дорога машина».
Ми профілювали гру і знайшли головний потік, що був завантажений майже на 100% під час сцен з інтенсивними обходами. Але вбивцею виявилися не сира обчислювальна потреба, а періодичні хіки
від компіляції шейдерів і стрімінгу активів. Ці завдання запускалися опортунистично і стикалися з дедлайнами кадру.

Помилка припущення була класичною: трактували завантаження CPU як доказ «не вистачає ядер», замість того, щоб запитати «який потік не встиг і чому».
Багатоядерні CPU мали нижчий per‑core boost і вищу латентність до деяких шляхів кешу/пам’яті через топологію. Чудово для збірок, але не для цієї гри.

Виправлення було неефектним, але дієвим: ми винесли компіляцію шейдерів у фоновий процес з явним бюджетуванням, закріпили його подалі від пріоритетних ядер головного потоку,
і попередньо скомпілювали гарячі шейдери для тестових мап. Також покращили пакування активів, щоб зменшити випадкові читання.
Після цього нові машини стали прийнятними — бо ми перестали змушувати CPU робити неправильну роботу в неправильний час.

Урок: якщо симптом — підвисання, перше питання: «хто не вклався в дедлайн», а не «скільки у нас ядер».

Оптимізація, що відвернулася: «максимізувати воркер‑потоки» (поки mutex не з’їв ферму)

Постпродакшн‑команда запускала CPU‑рендеринг на невеликій on‑prem фермі. Вони оновили платформи до значно більшої кількості ядер на ноду.
Хтось увімкнув у рендері «AUTO» і гордо виставив worker‑threads на «всі логічні CPU». Пропускна здатність мала підскочити.
Натомість час рендеру майже не покращився, а іноді став гіршим.

Ми подивилися системні метрики. Завантаження CPU було високим, але IPC низький і кількість контекстних переключень через дах. Ферма також почала
повідомляти про періодичні «зависання», що насправді були просто повільними кадрами.
Профілі показали сильну контенцію в спільному шляху акумуляції framebuffer і гарячу точку аллокатора пам’яті.

Провал був передбачуваний: більше потоків підвищило контенцію й трафік когерентності кешів. Рендерер витрачав більше часу на координацію, ніж на обчислення.
Додатково, кількість потоків підвищила навантаження на пам’ять, і усіядна частота впала через безперервні обмеження потужності.

Виправлення було контрінтуїтивним: ми зменшили кількість потоків на процес, збільшили розміри плиток і запустили два незалежні процеси рендерера на ноду, щоб зменшити спільний стан.
Продуктивність покращилася одразу, і дисперсія впала. Потім задокументували «відомо‑хорошу» конфігурацію потоків і плиток для кожного класу CPU.

Урок: «використовувати всі потоки» не є стратегією; це дефолт. Дефолти — місце для відпочинку продуктивності.

Нудна, але правильна практика, що врятувала день: планування з урахуванням топології і нотатки про ємність

VFX‑команда мала мішанину робочих станцій і маленьку ферму. Ферма містила вузли з різними поколіннями CPU і двома різними NUMA‑топологіями.
Нудна практика була у вигляді spreadsheet (так) та невеликого шматка коду в диспетчері задач:
кожен вузол повідомляв свою NUMA‑розкладку, канали пам’яті і «безпечну конкурентність», відбенчмарчену заздалегідь.

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

Через те, що диспетчер був усвідомлений до топології, він уникав розміщення пам’ятево‑важких задач на вузлах, які відомо сатурують пропускну здатність раніше.
Також він закріплював процеси рендерера по NUMA‑доменах на двосокетних вузлах, що тримало пам’ять локально і прогнозовано.
Коли масив сховища мав поганий день і латентність стрибнула, система деградувала плавно: менше задач затрималося одночасно завдяки консервативним лімітам конкурентності.

Нічого героїчного не сталося. У цьому і суть. Вони вклали проєкт вчасно, бо система поводилася як система, а не як набір надій.

Урок: запишіть вашу топологію і відбенчмарчену конкурентність. Це нудно, це правильно, і це рятує від «таємничих уповільнень» у майбутньому.

Типові помилки: симптом → корінь → виправлення

1) Симптом: високий середній FPS, але гра здається підвисаючою

Корінь: сплески часу кадру від затримок головного потоку, компіляції шейдерів, переривань драйверів або стрімінгу I/O.

Виправлення: захопіть графіки часу кадру; попередньо компілюйте шейдери, де можливо; перемістіть гру на швидкий локальний SSD; зменшіть фонові задачі; протестуйте SMT вкл/викл; перевірте стабільний boost і правильний governor.

2) Симптом: завантаження CPU лише 30–40%, але ви «CPU‑зв’язані»

Корінь: один гарячий потік гальмує кадр; інші потоки чекають на бар’єрах.

Виправлення: дивіться завантаження по ядрах; ідентифікуйте гарячий потік; зменшіть CPU‑важкі налаштування; обирайте CPU з кращою одноядерною швидкодією і кешем, а не більше ядер.

3) Симптом: рендер‑джоб не масштабується понад N ядер

Корінь: контенція за замки, аллокатор, серіальні фази (BVH build) або насичення пропускної здатності пам’яті.

Виправлення: профілюйте mutex‑гарячі точки; налагодьте розміри плиток/бакетів; спробуйте менше потоків на процес; запускайте кілька процесів; забезпечте використання всіх каналів пам’яті й NUMA‑локальність.

4) Симптом: рендер повільніший на «більшому» CPU в стоці

Корінь: обмеження потужності/тепла в реальному шасі, нижчі стійкі all‑core частоти або гірша пропускна здатність пам’яті на ядро.

Виправлення: виміряйте стійкі частоти (turbostat); перевірте охолодження; встановіть реалістичні обмеження потужності; бенчмаркуйте в реальному шасі, а не на відкритому стенді.

5) Симптом: продуктивність сильно варіюється між прогоном

Корінь: джиттер планувальника, фонові сервіси, осциляція частот, варіації кеш‑хітів диску або випадкова NUMA‑розсадка пам’яті.

Виправлення: закріпіть критичні навантаження; стандартизуйте governor; ізолюйте рендер‑ноди від інтерактивних задач; стабільно прогрівайте кеші; робіть політику NUMA явною (numactl або конфіг планувальника).

6) Симптом: апгрейд GPU мало покращив FPS

Корінь: вузьке місце в головному потоці CPU або накладність draw‑викликів/драйверів, що обмежує підживлення GPU.

Виправлення: зменшіть CPU‑важкі налаштування; оновіть CPU для одноядерної продуктивності й кешу; використовуйте графічні налаштування, що переводять навантаження на GPU (вища роздільна здатність, складніший AA) тільки якщо GPU і справді є обмежувачем.

7) Симптом: рендер‑ноди «зайняті», але пропускна здатність ферми низька

Корінь: надто висока конкурентність на вузол призводить до контенції і троттлінгу; шумні сусіди; затримки сховища.

Виправлення: обмежте конкурентність до відбенчмарчених безпечних значень; закріплюйте процеси по NUMA‑доменах; забезпечте локальний кеш; тримайте вузли «чистими» й одноцільовими.

Чеклисти / покроковий план

Вибір CPU для ігор (щоб не шкодувати)

  1. Пріоритет — сильна одноядерна продуктивність і поведінка кешу замість екстремальної кількості ядер.
  2. Перевіряйте реальні бенчмарки часу кадру в CPU‑обмежених сценаріях (не лише середній FPS при 4K).
  3. Віддавайте перевагу платформам зі стабільним boost у ваших реальних умовах охолодження, а не маркетинговим графікам.
  4. Перевірте політику енергії ОС: уникайте агресивного зниження частоти, якщо це викликає джиттер.
  5. Тестуйте SMT вкл/викл для конкретних ігор; тримайте налаштування, що мінімізує p99 часу кадру.
  6. Тримайте фоновий софт мінімальним: overlays, інструменти захоплення й «помічники» додають шум планувальника.
  7. Якщо ви багато стрімите активи, розглядайте сховище й декомпресію як частину вибору CPU.

Вибір CPU для рендерингу / створення контенту

  1. Почніть з масштабування рендерера: чи справді він використовує 32/64/96 потоків ефективно?
  2. Купуйте для стійкої all‑core частоти під реалістичні обмеження потужності й охолодження.
  3. Віддавайте перевагу більшій кількості каналів пам’яті і пропускній здатності для важких сцен і симуляцій.
  4. Плануйте NUMA: закріплюйте процеси по нодах, уникайте крос‑нодової «свальби» пам’яті.
  5. Бенчмаркуйте з продакшн‑сценами, а не з демо від вендора.
  6. Бюджетуйте сховище: локальний NVMe‑кеш для активів і проміжних результатів запобігає «голоду CPU».
  7. Стандартизуйовані конфігурації вузлів (governor, microcode, kernel) зменшують варіації та час на дебаг.

Гібридний план: одна робоча станція для ігор і рендерингу

  1. Вирішіть, яке навантаження пріоритетне. «Обидва однаково» — шлях до двічі незадоволених.
  2. Обирайте CPU з гарною одноядерною продуктивністю й пристойною кількістю ядер; уникайте екстремальної топологічної складності, якщо вона не потрібна.
  3. Інвестуйте в охолодження й живлення, щоб стійкий рендер не троттлився і boost для ігор був стабільним.
  4. Майте окремі профілі: одна політика ОС для ігор/інтерактиву, інша — для рендеру.
  5. Використовуйте локальний швидкий scratch/cache для рендер‑активів і ігрових інсталяцій.
  6. Документуйте «відомо‑хорошу» кількість потоків для рендеру і дотримуйтеся її.

Поширені запитання

1) Якщо ігри «тепер багатопоточні», чому вони досі піклуються про одноядерність?

Тому що координація все ще серіалізована. Ви можете паралелізувати задачі, але критичний шлях усе одно визначає, коли кадр готовий.
Цей критичний шлях часто проходить через головний потік або невелику групу потоків з інтенсивною синхронізацією.

2) Чи дійсно більше L3 кешу допомагає іграм?

Часто так — особливо для мінімального FPS і консистентності часу кадру. Великі кеші зменшують штрафи для коду з великою кількістю вказівників і спільного стану.
Але залежить від робочого набору гри й поведінки пам’яті. Кеш не виправить погану шейдерну логіку.

3) Чому процесори з великою кількістю ядер іноді гірші для ігор?

Бо вони можуть мати нижчі boost‑частоти на ядро, більш складну топологію (чіплети/NUMA) та вищу латентність у деяких шляхах.
Ігри помічають затримку й джиттер планувальника більше, ніж вигоду від зайвих ядер, які вони не можуть тримати завантаженими.

4) Для рендерингу завжди слід максимально навантажувати потоки?

Ні. Багато рендерерів досягають контенції або ліміту пропускної здатності. Після точки насичення більше потоків створюють лише тепло, троттлінг і битви за mutex.
Бенчмаркуйте і обирайте кількість потоків, що дає найкращу пропускну здатність на ват і стабільний час завершення.

5) SMT допомагає чи шкодить?

Для рендерингу SMT часто допомагає, підвищуючи завантаження. Для ігор результати змішані: може покращити середній FPS, але погіршити p99 часу кадру у деяких тайтлах.
Тестуйте на вашому конкретному наборі ігор і фоновому навантаженні.

6) Чому мій рендер‑нода стає повільнішою через годину?

Зазвичай через термальні або потужні обмеження. Тривалі навантаження на всі ядра приводять CPU у steady‑state: нижчі частоти, вищі температури.
Перевірте троттлінг (turbostat), почистіть фільтри від пилу та підтвердіть, що прошивка не встановила надто консервативні ліміти потужності.

7) Що важливіше: швидкість RAM для ігор чи рендеру?

Ігри частіше залежать від затримки пам’яті й поведінки кешу; налаштування RAM можуть допомогти мінімальному FPS у деяких випадках.
Рендеринг частіше залежить від пропускної здатності й ємності, особливо з багатьма ядрами й великими сценами. Платформи з більшою кількістю каналів можуть бути важливішими, ніж швидкість DIMM.

8) Чи може сховище справді виглядати як вузьке місце CPU у іграх?

Так. Стрімінг активів може викликати фолти сторінок, декомпресію та компіляцію шейдерів. CPU стає зайнятим опрацюванням наслідків I/O‑латентності.
Виміряйте затримки сховища й фолти сторінок перед тим, як звинувачувати CPU.

9) А GPU для рендерингу — чи має вибір CPU значення?

Для GPU‑рендерерів CPU все ще важливий для підготовки сцени, зборок BVH, передач даних і підживлення GPU.
Слабкий CPU може змусити дорогий GPU простоювати. «Правильний» CPU для цього зазвичай має більше ядер і пропускної здатності, ніж типовий ігровий вибір.

10) Яке найкоротше «в одне речення» правило для вибору CPU?

Якщо пропускання дедлайнів болюче (ігри, інтерактив), купуйте за латентністю; якщо важливі швидкіший час завершення (рендеринг), купуйте за пропускною здатністю і стійкими частотами.

Наступні кроки, які можна зробити цього тижня

  1. Перестаньте використовувати середній FPS як головний метрик. Відстежуйте часи кадрів (p95/p99) для ігор і час‑до‑завершення для рендеру.
  2. Профілюйте перед покупкою. На поточній машині ідентифікуйте, чи ви одноядерно‑зв’язані, обмежені контенцією, пам’яттю або I/O.
  3. Для ігор: віддавайте перевагу CPU з сильною одноядерною і кешовою поведінкою; забезпечте стабільний boost при належному охолодженні; приборкайте фоновий шум.
  4. Для рендерингу: бенчмаркуйте масштабування, перевірте стійкі частоти у штатному шасі і зробіть політику NUMA явною.
  5. Операціоналізуйте: запишіть відомо‑хороші кількості потоків, налаштування потужності й нотатки про топологію. Майбутній ви буде вдячний.

Якщо ви запам’ятаєте одну річ: ігри винагороджують CPU, який швидкий прямо зараз; рендеринг — CPU, який швидкий увесь день.
Купуйте відповідно і вимірюйте наполегливо.

← Попередня
Доступні стани фокусу, які не виглядають як сміття
Наступна →
Події OOM-killer у Proxmox: чому він вбиває процеси і як задати розумні ліміти

Залишити коментар