FinCodeCow · Обзор AI-инфраструктуры

Настройка ОС, Docker и Kubernetes для GPU-окружений

Обзор третьей главы книги Chris Fregly «AI Systems Performance Engineering» (O'Reilly, 2026) — с изложением содержания, проверкой прогнозов и систематизацией ключевых положений
Об источнике

Настоящий материал представляет собой обзор третьей главы книги Chris Fregly, «AI Systems Performance Engineering: Optimizing Model Training and Inference Workloads with GPUs, CUDA, and PyTorch», O'Reilly Media, 2026 (Copyright © 2026 Flux Capacitor, LLC).

Прямые цитаты из книги выделены отдельными блоками с пометкой «Цитата из книги». Остальной текст — систематизированное изложение содержания главы, сопоставление с актуальными данными, проверка прогнозов и дополнительные замечания, выходящие за пределы текста главы. Цитаты приводятся в ограниченном объёме в целях обзора и критического анализа.

§Контекст главы

Третья глава книги Fregly посвящена системному окружению, в котором работают GPU-ускорители. Даже идеально оптимизированный GPU-код может упереться в потолок, созданный операционной системой, драйверами или контейнерной средой. Быстрый графический процессор полезен ровно настолько, насколько быстро окружение способно подводить к нему данные и инструкции. Глава последовательно разбирает все уровни этого окружения — от параметров ядра Linux до оркестрации Kubernetes.

Цитата из книги · Глава 3

«Даже с высокооптимизированным GPU-кодом и библиотеками системные узкие места могут ограничивать производительность крупномасштабного AI-обучения. Самый быстрый GPU хорош ровно настолько, насколько хороша среда, подающая ему данные и инструкции».

Изложение содержания

В главе подчёркивается, что системные оптимизации часто остаются в тени алгоритмических, но могут давать двузначные процентные улучшения. На масштабе большого AI-проекта это выливается в десятки и сотни тысяч долларов сэкономленного времени вычислений.

Глава построена как последовательный разбор уровней: ОС → драйвер → CUDA Toolkit → библиотеки → фреймворк → CPU-конфигурация → GPU-настройки → контейнеры → оркестрация. Каждый уровень может стать узким местом. Задача инженера — обеспечить, чтобы ни один из них не блокировал работу GPU.

• • •
Блок 01 · Фундамент

Операционная система

Цитата из книги · Глава 3

«ОС — это фундамент, на котором работает всё остальное. GPU-серверы обычно используют Linux-дистрибутивы вроде Ubuntu Server LTS или Red Hat с обновлённым ядром, поддерживающим свежее GPU-железо. Драйвер NVIDIA устанавливает модули ядра, создающие файлы устройств: /dev/nvidia0, /dev/nvidia1 и так далее — по одному на каждый GPU».

Изложение содержания

В главе ОС описывается как слой, который должен быть настроен так, чтобы не мешать GPU-задачам. Ключевые требования: отключённый свопинг, высокая пропускная способность памяти, минимум прерываний. GPU-узлы не должны заниматься посторонними задачами — всё, что может создать джиттер, должно быть изолировано.

Отдельно упоминаются демоны, которые должны работать на GPU-сервере: NVIDIA Persistence Daemon (держит драйвер загруженным), Fabric Manager (управляет топологией NVSwitch) и NVIDIA Data Center GPU Manager (мониторинг здоровья GPU).

Практическое следствие: свопинг свести к минимуму. Глава предлагает vm.swappiness = 0; на современных ядрах чаще рекомендуют 1–10 — ноль не отключает своп полностью и увеличивает риск жёсткого OOM (см. уточнение в «Проверке прогнозов»). Суть неизменна: если память процесса уйдёт на диск, задержки вырастут на порядки, и GPU будет простаивать.

Итоги блока 01
Ключевое положение главы

ОС — фундамент производительности. Неправильные настройки ядра (свопинг, энергосбережение, миграция потоков) обесценивают оптимизации на всех верхних уровнях.

Практическое следствие

vm.swappiness — настройка с оговоркой: 1–10 на современных ядрах; ноль не отключает своп полностью и повышает риск жёсткого OOM. Отключение глубоких C-состояний, изоляция системных демонов. GPU-сервер должен быть настроен как HPC-узел.

• • •
Блок 02 · Стек

Программный стек NVIDIA

Цитата из книги · Глава 3

«Запуск многопетафлопсного GPU-кластера — это больше, чем просто написание кода на PyTorch, TensorFlow или JAX. Под всем этим лежит целый программный стек, и каждый его уровень может влиять на производительность».

Изложение содержания

В главе стек описывается как многоуровневая система: PyTorch/TensorFlow/JAX → cuDNN/cuBLAS/CUTLASS/NCCL → nvcc/PTX/CUDA Runtime → Triton/CUDA Python/cuTile → драйвер GPU → железо. Каждый уровень добавляет свои накладные расходы и свои возможности оптимизации.

Ключевая идея: проблема на нижнем уровне (устаревший драйвер, неверный PTX) обесценивает оптимизации на верхнем. Инженер по производительности должен одинаково уверенно работать на всех уровнях стека.

Рисунок 3-1. Программный стек NVIDIA

От фреймворков до кремния: шесть уровней абстракции

PyTorch / TensorFlow / JAX
High-level AI frameworks
cuDNN · cuBLAS · CUTLASS · NCCL
Optimized CUDA libraries
nvcc · PTX · CUDA Runtime
Compiler & runtime API
Triton · CUDA Python · cuTile
Python-native GPU kernels
NVIDIA GPU Driver
Hardware interface layer
GPU Hardware (Blackwell / Hopper)
SMs · Tensor Cores · HBM
Описание: Каждый уровень стека влияет на производительность. Проблема на нижнем слое (например, устаревший драйвер или неверный PTX) обесценивает оптимизации на верхнем. Инженер по производительности должен одинаково уверенно работать на всех шести уровнях.
Итоги блока 02
Ключевое положение главы

Производительность — результат работы всего стека, а не только верхнего уровня. Оптимизация PyTorch-кода не поможет, если драйвер устарел или PTX неверен.

Практическое следствие

Инженер должен уметь диагностировать проблемы на каждом уровне. Nsight Systems для верхнего уровня, Nsight Compute для ядер, nvidia-smi для драйвера, логи CUDA для PTX.

• • •
Блок 03 · Драйвер

Драйвер GPU

Цитата из книги · Глава 3

«В основании стека — драйвер NVIDIA, который связывает Linux и GPU. Драйвер управляет низкоуровневыми операциями: выделением памяти на устройстве, планированием задач на GPU и разделением GPU между арендаторами. Важно держать драйвер в актуальном состоянии: новые релизы часто открывают улучшения производительности и поддержку свежих архитектур».

Изложение содержания

В главе драйвер описывается как интерфейс между ОС и железом. Он транслирует команды CUDA Runtime в команды GPU и управляет памятью устройства. Утилита nvidia-smi идёт в комплекте и позволяет следить за температурой, загрузкой, статусом ECC и включать режимы вроде persistence mode.

Ключевой момент: драйвер должен соответствовать версии CUDA внутри контейнера. Для CUDA 13.x минимальная версия драйвера — R580, для CUDA 12.x — R525. Несоответствие версий приводит к ошибкам инициализации CUDA.

Практическое следствие: на всех узлах кластера должны быть одинаковые версии драйвера и CUDA. Разнобой приводит к тому, что одни узлы работают, а другие — нет, и диагностика занимает часы.

Итоги блока 03
Ключевое положение главы

Драйвер — интерфейс между ОС и GPU. Его версия должна соответствовать версии CUDA в контейнере.

Практическое следствие

Одинаковые версии драйвера на всех узлах. Проверка соответствия версий через nvidia-smi и nvcc --version. При обновлении драйвера — тестирование на staging-кластере.

• • •
Блок 04 · Runtime

CUDA Toolkit и среда исполнения

Цитата из книги · Глава 3

«Поверх драйвера расположены CUDA Runtime и библиотеки — CUDA Toolkit. В него входит компилятор nvcc для CUDA C++ ядер. Скомпилированные программы линкуются с CUDA runtime (cudart), который напрямую общается с драйвером NVIDIA для запуска работы и выделения памяти на GPU. CUDA Toolkit также предоставляет множество оптимизированных библиотек: cuDNN для нейросетевых примитивов, cuBLAS для линейной алгебры, NCCL для много-GPU коммуникаций».

Изложение содержания

В главе CUDA Toolkit описывается как набор библиотек и компиляторов, которые транслируют высокоуровневые операции в команды GPU. nvcc компилирует CUDA C++ в PTX и SASS, cuDNN и cuBLAS реализуют оптимизированные примитивы, NCCL обеспечивает коллективные операции между GPU.

Практическое следствие: использование последней версии CUDA Toolkit, поддерживающей вашу вычислительную способность, даёт доступ к новым оптимизациям компилятора и библиотек. Например, cuBLAS в новых версиях может использовать Tensor Cores более эффективно или поддерживать новые форматы данных.

Отдельно упоминается, что скомпилированный код содержит как PTX (виртуальный промежуточный код), так и CUBIN (SASS для конкретной архитектуры). PTX позволяет JIT-компилировать код под будущие архитектуры, CUBIN — исполняться напрямую на известных.

Рисунок 3-2. Компиляция nvcc → PTX → цели GPU

Виртуальный промежуточный код и физические бинарники

CUDA Program (.cu)
Virtual / Source
nvcc Compiler
Front-end
PTX (Intermediate IR)
Forward-compatible
sm_90 (Hopper)
sm_100 (Blackwell)
future GPU
Описание: PTX — виртуальный промежуточный код, совместимый вперёд: драйвер может JIT-компилировать его под будущие архитектуры. CUBIN — уже скомпилированный SASS для конкретной архитектуры, быстрее, но не совместим вперёд. Fatbinary объединяет оба варианта.
Итоги блока 04
Ключевое положение главы

CUDA Toolkit — набор оптимизированных библиотек, которые транслируют высокоуровневые операции в команды GPU. Версия Toolkit должна соответствовать вычислительной способности GPU.

Практическое следствие

Обновление CUDA Toolkit даёт доступ к новым оптимизациям. PTX обеспечивает совместимость вперёд, CUBIN — максимальную производительность на известных архитектурах.

• • •
Блок 05 · Совместимость

Совместимость CUDA между поколениями GPU

Цитата из книги · Глава 3

«Важная особенность модели программирования NVIDIA — совместимость между поколениями железа. При компиляции CUDA-кода бинарник содержит как виртуальный промежуточный код PTX, так и физический код устройства. Это достигается через модель fatbinary, содержащую PTX для совместимости вперёд и CUBIN — архитектурно-специфичные бинарники CUDA для известных архитектур».

Изложение содержания

В главе модель fatbinary описывается как механизм, обеспечивающий одновременно обратную и прямую совместимость. PTX — это виртуальный промежуточный код, который драйвер может JIT-компилировать под конкретную архитектуру во время выполнения. CUBIN — это уже скомпилированный SASS, который исполняется напрямую, но только на определённой архитектуре.

Практическое следствие: если вы поставляете только CUBIN для конкретной архитектуры (например, sm_90 для Hopper или sm_100 для Blackwell) без PTX, бинарник не будет работать на будущих архитектурах. Если вы поставляете PTX, драйвер сможет его скомпилировать, но с небольшими накладными расходами на JIT-компиляцию.

Рекомендация главы: включать в бинарник и CUBIN, и PTX. Это даёт максимальную производительность на известных архитектурах и совместимость с будущими.

Уточнение по актуальным данным

Начиная с CUDA 12.x, NVIDIA ввела понятие «family-specific» целей: sm_100f для Blackwell. Это позволяет компилировать код, который использует специфичные для семейства возможности, но остаётся совместимым внутри семейства. Для максимальной переносимости рекомендуется компилировать с generic-целями и явно включать PTX.

Итоги блока 05
Ключевое положение главы

Fatbinary с PTX + CUBIN обеспечивает одновременно производительность и совместимость. Без PTX бинарник не будет работать на будущих GPU.

Практическое следствие

Компилировать с generic-целями и включать PTX для будущей совместимости. Использовать family-specific цели только при необходимости в специфичных оптимизациях.

• • •
Блок 06 · Библиотеки

Библиотеки CUDA для C++ и Python

Цитата из книги · Глава 3

«Хотя большинство библиотек CUDA Toolkit написаны на C++, текущие Python-ориентированные решения NVIDIA включают CUDA Python, cuPyNumeric, CuTe DSL, cuTile и CuPy для работы с массивами, а также NVIDIA Warp для написания GPU-ядер на Python. CUTLASS — это C++ шаблонная библиотека, используемая под капотом cuBLAS, а не Python-библиотека».

Изложение содержания

В главе описываются Python-ориентированные библиотеки NVIDIA, которые снижают барьер входа для разработчиков. cuTile упрощает работу с большими матрицами через тайлинг. cuPyNumeric заменяет numpy. Triton (от OpenAI) позволяет писать GPU-ядра на Python.

Практическое следствие: для исследователей и разработчиков, не знакомых с CUDA C++, эти библиотеки дают возможность писать высокопроизводительный GPU-код. Под капотом они всё равно компилируются в PTX и SASS, но программист работает с Python-абстракциями.

Итоги блока 06
Ключевое положение главы

Python-ориентированные библиотеки (cuTile, cuPyNumeric, Triton) снижают барьер входа для разработчиков, не знакомых с CUDA C++.

Практическое следствие

Для новых проектов можно использовать Python-абстракции. Для максимального контроля — CUDA C++ и CUTLASS.

• • •
Блок 07 · Фреймворки

PyTorch и высокоуровневые фреймворки

Цитата из книги · Глава 3

«Когда вы выполняете операции над тензорами PyTorch на GPU, они перемещаются с CPU на GPU, что выглядит как один вызов Python. Однако этот единственный вызов транслируется в серию обращений к CUDA runtime с использованием различных библиотек CUDA».

Изложение содержания

В главе прослеживается цепочка от Python-кода до GPU: PyTorch Python API → PyBind11 → ATen Dispatcher → CUDA Runtime API → GPU Kernel Execution. Каждый переход добавляет накладные расходы, но PyTorch абстрагирует их, позволяя писать интуитивный Python-код.

Практическое следствие: понимание этой цепочки помогает диагностировать, где теряется производительность. Например, если операция слишком мелкая, накладные расходы на переход между уровнями могут превысить выигрыш от вычислений.

Рисунок 3-3. PyTorch код → GPU-устройство

Один вызов Python → множество обращений к CUDA runtime

PyTorch
Python API
torch.Tensor op
→
PyBind11
binding to C++
→
ATen
Dispatcher
C++ backend
→
CUDA Runtime API
cudaMemcpy / cudaLaunchKernel
→
GPU Kernel
Execution
on-device
Описание: Тонкая прослойка между высокоуровневым API PyTorch и железом. Каждый переход добавляет свои накладные расходы; знание этой цепочки помогает точно определять, где теряется производительность.
Итоги блока 07
Ключевое положение главы

PyTorch абстрагирует сложность CUDA, но каждый уровень цепочки добавляет накладные расходы.

Практическое следствие

Для мелких операций накладные расходы на переход между уровнями могут превысить выигрыш. Использование torch.compile и CUDA Graphs снижает эти расходы.

• • •
Блок 08 · NUMA

NUMA-топология и привязка CPU

Цитата из книги · Глава 3

«Современные серверные CPU имеют десятки ядер и часто разделены на несколько NUMA-узлов. NUMA-узел — это логическая группа CPU, GPU, сетевых карт и памяти, физически близких друг к другу. Доступ к ресурсам внутри одного NUMA-узла быстрее, чем к ресурсам в других узлах».

Изложение содержания

В главе NUMA-топология описывается как один из главных источников скрытых задержек. Когда процесс на CPU в одном NUMA-узле обращается к GPU в другом, данные идут через межузловую шину с повышенной задержкой. В одном эксперименте задержка доступа к локальному NUMA-узлу составила ~80 нс против ~139 нс для удалённого — рост примерно на 75%.

Практическое следствие: привязка процесса к CPU на том же NUMA-узле, что и его GPU, устраняет этот трафик. На практике это даёт +5–10% пропускной способности обучения и снижает джиттер. Инструменты: numactl --cpunodebind и taskset.

Отдельно оговаривается, что на системах с CPU-GPU superchip (Grace Blackwell) CPU и GPU связаны NVLink-C2C с когерентным доступом к памяти. Это снижает остроту проблемы, но Linux по-прежнему моделирует CPU DRAM и GPU HBM как отдельные пулы, и привязка к локальному NUMA-узлу остаётся полезной.

Рисунок 3-4. NUMA-топология: 8 GPU на 2 NUMA-узла

CPU pinning и локальность памяти

NUMA node 0

CPU 0-7
GPU 0 GPU 1 GPU 2 GPU 3
DRAM 0
Interconnect
Remote access: ~75% медленнее

NUMA node 1

CPU 8-15
GPU 4 GPU 5 GPU 6 GPU 7
DRAM 1
Описание: Привязка процесса к CPU, расположенному на том же NUMA-узле, что и GPU, устраняет меж-NUMA-трафик. На практике это даёт +5–10% пропускной способности обучения и снижает джиттер.
Итоги блока 08
Ключевое положение главы

NUMA-топология — источник скрытых задержек. Удалённый доступ к памяти на ~75% медленнее локального.

Практическое следствие

Привязка процессов к CPU на том же NUMA-узле, что и GPU, через numactl --cpunodebind. Это даёт +5–10% пропускной способности и снижает джиттер.

• • •
Блок 09 · Память

NUMA-дружественная память и закрепление

Цитата из книги · Глава 3

«По умолчанию процесс выделяет память из NUMA-узла того CPU, на котором он сейчас выполняется. Опция numactl --membind заставляет выделять память из конкретного NUMA-узла. Pinned-память (page-locked или nonpageable) критична для эффективного прямого доступа к GPU. Копирование данных из закреплённой памяти хоста на GPU может быть в 2–3 раза быстрее, чем из обычной страничной памяти».

Изложение содержания

В главе pinned-память описывается как ключевой элемент для быстрой передачи данных CPU → GPU. Обычная страничная память может быть выгружена на диск, поэтому GPU/NIC не может выполнять DMA напрямую. Pinned-память закреплена в RAM, и DMA выполняется напрямую.

Практическое следствие: в PyTorch DataLoader флаг pin_memory=True включает pinned-память. Это даёт 2–3× ускорение H2D-копий. Однако у pinned-памяти есть лимит, который контролируется через ulimit -l. Если лимит слишком мал, аллокация может упасть, и система перейдёт на обычную память.

Рекомендация: устанавливать ulimit -l unlimited для больших AI-нагрузок.

Рисунок 3-5. Pinned (Page-Locked) vs Pageable Memory

Прямой DMA против страничной памяти

Pageable Memory
Disk ↔ RAM swapping enabled
→
Pinned Memory
Page-locked · DMA ready
→
GPU
Описание: Pinned-память нельзя выгрузить на диск, поэтому GPU/NIC выполняет DMA напрямую. Это даёт 2–3× ускорение H2D-копий. В PyTorch включается флагом pin_memory=True в DataLoader.
Итоги блока 09
Ключевое положение главы

Pinned-память — ключ к быстрой передаче данных CPU → GPU. DMA напрямую даёт 2–3× ускорение.

Практическое следствие

pin_memory=True в DataLoader, ulimit -l unlimited для больших аллокаций. Для NUMA-локальности — numactl --membind.

• • •
Блок 10 · Страницы и планировщик

Огромные страницы, планировщик и IRQ affinity

Цитата из книги · Глава 3

«Огромные страницы — 2 МБ или даже 1 ГБ — могут снизить накладные расходы управления виртуальной памятью. Основные преимущества: меньше страничных отказов и меньше давления на буфер трансляции адресов (TLB). Обычно THP дают умеренный выигрыш — часто порядка 3–5% пропускной способности. Аппаратные прерывания каждого устройства следует привязывать к ядрам на том же NUMA-узле».

Изложение содержания

В главе прозрачные огромные страницы (THP) описываются как простой способ снизить накладные расходы на управление памятью. 2 МБ страницы вместо 4 КБ уменьшают количество записей в TLB и страничных отказов. Выигрыш умеренный, но стабильный.

Однако для latency-sensitive inference рекомендуется отключать THP. Фоновая компактификация может вносить непредсказуемые паузы. Это классический trade-off: throughput vs latency.

IRQ affinity — ещё один аспект. Если прерывания от GPU или NIC обрабатываются на ядре в другом NUMA-узле, это добавляет задержку и вызывает трафик когерентности. Привязка прерываний к локальным ядрам устраняет эту проблему.

Итоги блока 10
Ключевое положение главы

THP дают +3–5% пропускной способности, но могут вносить паузы. Для inference рекомендуется отключать.

Практическое следствие

Привязка IRQ к локальным NUMA-ядрам. Отключение irqbalance или настройка правил. Для latency-critical workloads — transparent_hugepage=never.

• • •
Блок 11 · Виртуальная память и частота

Виртуальная память, свопинг и частота CPU

Цитата из книги · Глава 3

«Всегда старайтесь избегать свопинга памяти. Если любая часть памяти вашего процесса будет выгружена на диск, вы увидите катастрофическое замедление на порядки. Установите vm.swappiness = 0. Для максимальной и стабильной производительности AI-системы часто настраивают governor частоты CPU в режим "performance"».

Изложение содержания

В главе свопинг описывается как катастрофа для GPU-нагрузок. Если память процесса выгружена на диск, GPU будет ждать, пока данные вернутся в RAM. Это замедление на порядки. Решение из главы — vm.swappiness = 0 и достаточный объём RAM. На современных ядрах стоит оговорка: ноль не отключает своп полностью и повышает риск жёсткого OOM, поэтому чаще рекомендуют значения 1–10 (подробнее — в «Проверке прогнозов»).

Частота CPU и C-состояния — второй аспект. В режиме энергосбережения CPU может уходить в глубокий сон, а пробуждение занимает микросекунды. Для GPU-нагрузок, где важна предсказуемость, рекомендуется режим performance и отключение глубоких C-состояний.

Практическое следствие: на GPU-серверах CPU governor должен быть в режиме performance, а C-состояния — ограничены. Это увеличивает энергопотребление, но обеспечивает стабильность.

Итоги блока 11
Ключевое положение главы

Свопинг — катастрофа для GPU-нагрузок. vm.swappiness = 0 — рекомендация главы; на современных ядрах чаще 1–10.

Практическое следствие

CPU governor в режиме performance, глубокие C-состояния отключены. Это trade-off: больше энергии, но стабильнее latency.

• • •
Блок 12 · Аллокатор

Настройка аллокатора памяти CPU

Цитата из книги · Глава 3

«Настраивая аллокатор памяти хоста (jemalloc или tcmalloc), можно устранить непредсказуемые паузы в подготовке данных. С jemalloc можно шардировать выделения по per-CPU аренам, включить background_thread для очистки вне критического пути и увеличить dirty_decay_ms/muzzy_decay_ms».

Изложение содержания

В главе аллокатор памяти описывается как источник непредсказуемых пауз. Стандартный malloc может блокировать потоки при выделении памяти, создавая джиттер. jemalloc и tcmalloc решают эту проблему через per-CPU арены и фоновую очистку.

Практическое следствие: для CPU-bound data pipeline (загрузка данных, tokenization, augmentation) настройка аллокатора может дать заметный выигрыш в стабильности. Это не увеличивает среднюю производительность, но снижает хвостовые задержки.

Рекомендация главы: использовать MALLOC_CONF с narenas:8, dirty_decay_ms:10000, muzzy_decay_ms:10000, background_thread:true.

Итоги блока 12
Ключевое положение главы

Аллокатор памяти — источник непредсказуемых пауз. jemalloc/tcmalloc сглаживают джиттер.

Практическое следствие

Настройка MALLOC_CONF для per-CPU арен и фоновой очистки. Это снижает хвостовые задержки в data pipeline.

• • •
Блок 13 · Режим постоянства

Режим постоянства GPU

Цитата из книги · Глава 3

«По умолчанию, если никакое приложение не использует GPU, драйвер может перевести GPU в состояние низкого энергопотребления и выгрузить часть контекста драйвера. Инициализация может занять секунду-две. Режим постоянства включается запуском демона nvidia-persistenced и держит драйвер GPU загруженным и железо в готовом состоянии».

Изложение содержания

В главе режим постоянства описывается как способ избежать задержки запуска задачи. Без него первый вызов CUDA после простоя может занять секунду-две. С ним GPU всегда готов.

Практическое следствие: на AI-кластерах режим постоянства включается на всех GPU при загрузке сервера. Это не ускоряет вычисления, но срезает задержку запуска. Особенно важно при использовании MIG, где без persistence конфигурация сбрасывается при каждом запуске.

Рекомендация: systemctl enable nvidia-persistenced.

Итоги блока 13
Ключевое положение главы

Режим постоянства срезает задержку запуска задачи. GPU всегда готов к работе.

Практическое следствие

systemctl enable nvidia-persistenced на всех GPU-серверах. Особенно важно при использовании MIG.

• • •
Блок 14 · MPS и MIG

MPS и MIG

Цитата из книги · Глава 3

«Обычно, когда несколько процессов совместно используют один GPU, планировщик GPU разделяет время между ними. MPS от NVIDIA создаёт своего рода зонтик, под которым несколько процессов могут работать на GPU одновременно, если ресурсы GPU доступны. MIG позволяет нарезать GPU на целых семь меньших логических GPU — каждый со своей выделенной частью памяти и вычислительных блоков».

Изложение содержания

В главе MPS и MIG описываются как инструменты повышения утилизации. MPS позволяет нескольким процессам делить GPU без time-slicing, что повышает утилизацию. MIG даёт аппаратную изоляцию с выделенными SM, L2 и HBM.

Практическое следствие: MPS подходит для inference-нагрузок, где отдельные задачи не загружают GPU целиком. MIG — для мультитенантности и изоляции. Однако для tightly-coupled training-нагрузок, где все GPU должны работать синхронно, MIG не подходит из-за отключения P2P.

Важное ограничение: на момент написания главы P2P между экземплярами MIG отключён. Это делает MIG непригодным для распределённого обучения, но полезным для inference.

Рисунок 3-6. GPU без MPS — Time-Slicing с idle-гэпами

Последовательное переключение между процессами

t₀t₁t₂t₃t₄t₅t₆t₇
Process A
A
idle
A
idle
A
idle
A
idle
Process B
idle
B
idle
B
idle
B
idle
B
Process A kernels Process B kernels Idle gap
⚠ GPU ≈ 50% idle из-за ping-pong переключений

Рисунок 3-7. GPU с MPS — параллельное перекрытие

Совместное выполнение ядер разных процессов

t₀t₁t₂t₃t₄t₅
Process A
A
A
A
A
A
A
Process B
B
B
B
B
B
B
GPU (SM)
A+B
A+B
A+B
A+B
A+B
A+B
Process A kernels Process B kernels Совместное выполнение
✓ Idle-гэпы устранены, GPU utilization ↑ 80–90%

Рисунок 3-8. Семь MIG-слайсов на одном GPU

Аппаратная изоляция SM, L2 и HBM

PHYSICAL GPU USER 0 1g.23gb USER 1 2g.45gb USER 2 3g.90gb USER 3 4g.90gb USER 4 5g.112gb USER 5 6g.135gb USER 6 7g.180gb

MIG — аппаратная изоляция: выделенные SM, L2-слайсы и HBM. До 7 изолированных GPU-инстансов на одной плате.

Описание: Сильная изоляция для многопользовательских inference-сценариев. Однако на момент написания P2P между экземплярами MIG отключён — включая NVLink и PCIe. Для крупномасштабного распределённого обучения MIG не подходит.
Итоги блока 14
Ключевое положение главы

MPS — для повышения утилизации через параллельное выполнение. MIG — для аппаратной изоляции и мультитенантности.

Ограничение

P2P между MIG-инстансами отключён. MIG не подходит для tightly-coupled training-нагрузок. Для inference — да, для обучения — нет.

Практическое следствие

MPS — для inference-кластеров. MIG — для мультитенантных inference-серверов. Не использовать MIG для распределённого обучения.

• • •
Блок 15 · Контейнеры

Оптимизация контейнеров для GPU

Цитата из книги · Глава 3

«Контейнер на узле разделяет ядро хост-ОС, так что операции CPU и памяти выполняются почти на нативной скорости. С NVIDIA Container Toolkit доступ к GPU из контейнера Docker прямой. Современные бенчмарки (MLPerf Inference v5.0) демонстрируют, что правильно настроенные контейнеры дают разницу < 2% от голого железа. Используйте официальные базовые образы NVIDIA из NGC».

Изложение содержания

В главе контейнеры описываются как способ обеспечить воспроизводимость окружения без потери производительности. NVIDIA Container Toolkit позволяет контейнеру напрямую обращаться к GPU. Разница с голым железом — менее 2%.

Практическое следствие: версия драйвера на хосте должна быть не старше минимальной, требуемой версией CUDA внутри контейнера. Для CUDA 13.x — R580+, для CUDA 12.x — R525+. Несоответствие приводит к ошибкам инициализации.

Отдельно оговаривается проблема OverlayFS: copy-on-write добавляет накладные расходы на I/O. Для интенсивного обучения монтируйте каталоги хоста в контейнер через bind mounts — они обходят overlay.

Итоги блока 15
Ключевое положение главы

Контейнеры с NVIDIA Container Toolkit дают производительность в пределах 2% от голого железа при правильной настройке.

Практическое следствие

Версии драйвера и CUDA должны соответствовать. Bind mounts для I/O-интенсивных нагрузок. Официальные образы NGC как база.

• • •
Блок 16 · Оркестрация

Kubernetes для топологически-осознанной оркестрации

Цитата из книги · Глава 3

«Kubernetes (K8s) — популярный оркестратор для AI-нагрузок. NVIDIA device plugin для Kubernetes объявляет аппаратное обеспечение GPU планировщику. NVIDIA Kubernetes GPU Operator автоматизирует установку и жизненный цикл всего ПО NVIDIA, включая DCGM-мониторинг. Kubernetes Topology Manager может предоставить топологическую информацию».

Изложение содержания

В главе Kubernetes описывается как оркестратор, который может учитывать топологию GPU. NVIDIA device plugin делает GPU видимыми для планировщика, GPU Operator автоматизирует управление ПО, Topology Manager обеспечивает топологическую осведомлённость.

Практическое следствие: для много-GPU задач важно использовать топологически-осознанное планирование. Политики best-effort, restricted или single-numa-node помогают размещать поды на GPU, связанных NVLink, и избегать меж-NUMA трафика.

Отдельно оговаривается проблема MIG: планировщик не может разделить запрос между GPU или узлами. Если ни один узел не имеет нужного количества свободных срезов, под останется в Pending.

Итоги блока 16
Ключевое положение главы

Kubernetes с NVIDIA device plugin и Topology Manager обеспечивает топологически-осознанное размещение GPU.

Практическое следствие

Политики Topology Manager для минимизации меж-NUMA трафика. Host networking для RDMA. MIG-поды требуют целых срезов на одном узле.

• • •
Блок 17 · Проверка прогнозов

Проверка прогнозов и актуальные данные

Книга Fregly писалась в 2025 году. С тех пор многое изменилось. Ниже представлено сопоставление прогнозов главы с открытыми данными и уточнение цифр.

Подтверждено Прогноз 1: системные оптимизации дают двузначные процентные улучшения

«Системные оптимизации часто остаются в тени алгоритмических, но могут давать двузначные процентные улучшения».

Подтверждено. На практике привязка к NUMA даёт +5–10%, pinned-память — 2–3× на H2D, режим постоянства срезает секунды задержки запуска. В сочетании на масштабе кластера это даёт миллионы долларов экономии.

Подтверждено Прогноз 2: MIG и MPS станут стандартом для мультитенантности

«MPS и MIG — инструменты повышения утилизации».

Подтверждено. В 2025–2026 годах MIG и MPS стали стандартом для inference-кластеров. Kubernetes device plugin и GPU Operator поддерживают автоматическое управление MIG-профилями. NVIDIA Dynamo использует MIG для мультитенантного inference.

Подтверждено Прогноз 3: контейнеры не будут стоить производительности

«Современные бенчмарки демонстрируют, что правильно настроенные контейнеры дают разницу < 2% от голого железа».

Подтверждено — с уточнением источника. MLPerf Inference v5.0 — это бенчмарк производительности inference-систем, а не сравнение контейнеров с «голым железом»: сам по себе он накладные расходы контейнеризации не измеряет. Цифра «менее 2%» — это оценка NVIDIA Container Toolkit, подкрепляемая практикой: официальные NGC-образы и Container Toolkit используются в подавляющем большинстве MLPerf-сабмитов, то есть бенчмарки прогоняются на контейнерном стеке без заметной потери результата. Сами выводы верны: Red Hat OpenShift и Kubernetes работают в production-развёртываниях повсеместно.

Уточнение vm.swappiness = 0 требует оговорки

«Установите vm.swappiness = 0».

Совет верен по мотивации, но устарел по исполнению. В современных ядрах Linux значение 0 не отключает своп полностью: под давлением памяти анонимные страницы всё же выгружаются, а узел быстрее падает в жёсткий OOM вместо плавной деградации. Для ML-узлов обычно рекомендуют низкие значения 1–10 и достаточный объём RAM, а полный отказ от swap-раздела — осознанное решение для кластеров с жёстким контролем размещения памяти. Формулировка из книги отражает традиционную HPC-практику; на актуальных ядрах безопаснее vm.swappiness = 1 при установленном swap.

Частично подтверждено Прогноз 4: P2P между MIG-инстансами отключён

«На момент написания P2P между экземплярами MIG отключён — включая NVLink и PCIe».

Частично подтверждено. Ограничение сохраняется в большинстве конфигураций. Однако NVIDIA работает над улучшением изоляции MIG и, возможно, в будущих поколениях P2P будет доступен. Пока для распределённого обучения MIG не рекомендуется.

Дополнение Kubernetes Topology Manager и DRA

В главе описывается Topology Manager, но не упоминается Dynamic Resource Allocation (DRA). В 2025 году DRA стал ключевым механизмом для гибкого выделения GPU-ресурсов в Kubernetes. DRA позволяет описывать GPU-ресурсы декларативно и управлять ими через API, что даёт большую гибкость, чем статический device plugin.

Дополнение NVIDIA Dynamo и disaggregated inference

Глава фокусируется на Kubernetes как оркестраторе, но не упоминает NVIDIA Dynamo — фреймворк для disaggregated inference, который использует NIXL для передачи KV-кэша и интегрируется с Kubernetes. Dynamo стал стандартом для production-развёртываний disaggregated prefill/decode в 2025–2026 годах.

• • •
Блок 18 · Пропущенные аспекты

Что не упомянуто в главе

Глава описывает архитектуру и принципы, но оставляет за скобками несколько аспектов, которые проявились в реальной эксплуатации.

Дополнительные замечания

DRA (Dynamic Resource Allocation) — в 2025 году Kubernetes представил DRA как замену статическому device plugin. DRA позволяет декларативно описывать GPU-ресурсы, включая MIG-профили, и динамически выделять их. Это даёт большую гибкость для мультитенантных кластеров.

NVIDIA Dynamo — фреймворк для disaggregated inference, который интегрируется с Kubernetes и использует NIXL для передачи KV-кэша. Dynamo стал стандартом для production-развёртываний в 2025–2026 годах.

GPU Operator и MIG Manager — GPU Operator автоматизирует управление MIG, включая пересоздание профилей после перезагрузки. Это решает проблему сброса MIG-конфигурации при перезапуске.

Container Device Interface (CDI) — стандарт для описания GPU-устройств в контейнерах. CDI упрощает передачу GPU в контейнеры и используется в современных версиях NVIDIA Container Toolkit.

• • •
Блок 19 · Итоги

Ключевые выводы

  1. Локальность данных и вычислений критична. Используйте локальные NVMe SSD-кэши и минимизируйте сетевой I/O.
  2. Внедряйте NUMA-осознанную конфигурацию и CPU affinity. numactl и taskset предотвращают меж-NUMA-трафик.
  3. Максимизируйте эффективность драйвера. Включайте режим постоянства; для многопользовательских сред — MPS или MIG.
  4. Предзагружайте и группируйте данные. Используйте prefetch_factor и pin_memory=True в DataLoader.
  5. Оптимизируйте передачу памяти. Pinned-память и огромные страницы ускоряют H2D.
  6. Перекрывайте коммуникацию с вычислениями. DDP с bucket size ~25 МиБ — стандарт.
  7. Настраивайте сетевой стек. RDMA, jumbo frames, IRQ affinity.
  8. Контейнеры не должны стоить производительности. Используйте NVIDIA Container Toolkit и bind mounts.
  9. Топологически-осознанное планирование. Kubernetes Topology Manager и device plugin от NVIDIA.
  10. DRA и Dynamo — новые стандарты. Dynamic Resource Allocation для гибкого выделения GPU, Dynamo для disaggregated inference.
Итог обзора

Третья глава книги Fregly — систематический разбор системного окружения GPU. Ключевая идея: производительность — результат работы всего стека, от ОС до Kubernetes. Инженер должен одинаково уверенно работать на всех уровнях. Проверка прогнозов показывает: книга оказалась точной в своих предсказаниях. MIG и MPS стали стандартом, контейнеры не стоят производительности, NUMA-оптимизации дают двузначные проценты. Главный вывод: системные оптимизации — не «мягкая» часть, а обязательный элемент производительности.

Источники: Chris Fregly, «AI Systems Performance Engineering» (O'Reilly, 2026), Глава 3 — цитаты приводятся в ограниченном объёме в целях обзора и критического анализа. Документация NVIDIA Container Toolkit; NVIDIA Kubernetes GPU Operator; MLPerf Inference v5.0; Uptime Institute; Dell'Oro Group.

FinCodeCow · AI Infrastructure Review

Configuring OS, Docker, and Kubernetes for GPU Environments

A review of Chapter 3 of Chris Fregly's «AI Systems Performance Engineering» (O'Reilly, 2026) — with exposition of content, forecast verification, and systematization of key points
About the source

This material is a review of Chapter 3 of Chris Fregly, «AI Systems Performance Engineering: Optimizing Model Training and Inference Workloads with GPUs, CUDA, and PyTorch», O'Reilly Media, 2026 (Copyright © 2026 Flux Capacitor, LLC).

Direct quotes from the book are marked with separate blocks labeled «Quote from the book». The rest of the text is a systematized exposition of the chapter's content, a comparison with current data, forecast verification, and additional observations that go beyond the chapter's text. Quotes are provided in limited volume for review and critical analysis purposes.

§Chapter Context

Chapter 3 of Fregly's book is dedicated to the system environment in which GPU accelerators operate. Even perfectly optimized GPU code can hit a ceiling imposed by the operating system, drivers, or the container environment. A fast GPU is only as useful as the environment is quick to feed it data and instructions. The chapter systematically examines all levels of this environment — from Linux kernel parameters to Kubernetes orchestration.

Quote from the book · Chapter 3

«Even with highly optimized GPU code and libraries, system-level bottlenecks can limit performance in large-scale AI training. The fastest GPU is only as good as the environment feeding it data and instructions».

Exposition of content

The chapter emphasizes that system-level optimizations often remain in the shadow of algorithmic ones, but can yield double-digit percentage improvements. At the scale of a large AI project, this translates into tens and hundreds of thousands of dollars in saved compute time.

The chapter is structured as a sequential examination of levels: OS → driver → CUDA Toolkit → libraries → framework → CPU configuration → GPU settings → containers → orchestration. Each level can become a bottleneck. The engineer's task is to ensure that none of them blocks GPU operation.

• • •
Block 01 · Foundation

Operating System

Quote from the book · Chapter 3

«The OS is the foundation for everything else. GPU servers typically use Linux distributions such as Ubuntu Server LTS or Red Hat with an updated kernel supporting recent GPU hardware. The NVIDIA driver installs kernel modules that create device files: /dev/nvidia0, /dev/nvidia1, and so on — one per GPU».

Exposition of content

In the chapter, the OS is described as a layer that must be configured so as not to interfere with GPU tasks. Key requirements: disabled swapping, high memory bandwidth, minimal interrupts. GPU nodes should not engage in extraneous tasks — anything that can create jitter should be isolated.

The chapter separately mentions daemons that should run on a GPU server: NVIDIA Persistence Daemon (keeps the driver loaded), Fabric Manager (manages NVSwitch topology), and NVIDIA Data Center GPU Manager (GPU health monitoring).

Practical consequence: minimize swapping. The book's recommendation is vm.swappiness = 0; on modern kernels values of 1–10 are common, as 0 does not fully disable swapping and increases the risk of a hard OOM (see the clarification in "Forecast Verification"). The essence is unchanged: if process memory goes to disk, latencies grow by orders of magnitude and the GPU idles.

Block 01 Summary
Key point of the chapter

The OS is the foundation of performance. Incorrect kernel settings (swapping, power saving, thread migration) invalidate optimizations at all higher levels.

Practical consequence

vm.swappiness is a setting with a caveat: 1–10 on modern kernels; 0 does not fully disable swapping and increases the risk of a hard OOM. Disable deep C-states, isolate system daemons. A GPU server should be configured as an HPC node.

• • •
Block 02 · Stack

NVIDIA Software Stack

Quote from the book · Chapter 3

«Running a multi-petaflop GPU cluster involves more than just writing high-level PyTorch, TensorFlow, or JAX code. There is a whole software stack underpinning GPU operations, and each layer can affect performance».

Exposition of content

The chapter describes the stack as a multi-level system: PyTorch/TensorFlow/JAX → cuDNN/cuBLAS/CUTLASS/NCCL → nvcc/PTX/CUDA Runtime → Triton/CUDA Python/cuTile → GPU driver → hardware. Each level adds its own overhead and its own optimization opportunities.

The key idea: a problem at a lower level (outdated driver, incorrect PTX) invalidates optimizations at higher levels. A performance engineer must be equally comfortable at all levels of the stack.

Figure 3-1. NVIDIA Software Stack

From frameworks to silicon: six layers of abstraction

PyTorch / TensorFlow / JAX
High-level AI frameworks
cuDNN · cuBLAS · CUTLASS · NCCL
Optimized CUDA libraries
nvcc · PTX · CUDA Runtime
Compiler & runtime API
Triton · CUDA Python · cuTile
Python-native GPU kernels
NVIDIA GPU Driver
Hardware interface layer
GPU Hardware (Blackwell / Hopper)
SMs · Tensor Cores · HBM
Description: Every layer affects performance. A problem at the bottom (outdated driver, wrong PTX) invalidates optimizations at the top. A performance engineer must be equally comfortable at all six levels.
Block 02 Summary
Key point of the chapter

Performance is the result of the entire stack, not just the top level. Optimizing PyTorch code won't help if the driver is outdated or PTX is incorrect.

Practical consequence

An engineer must be able to diagnose problems at every level. Nsight Systems for the top level, Nsight Compute for kernels, nvidia-smi for the driver, CUDA logs for PTX.

• • •
Block 03 · Driver

GPU Driver

Quote from the book · Chapter 3

«At the base is the NVIDIA GPU driver, which interfaces between the Linux OS and the GPU hardware. The driver manages low-level GPU operations, including memory allocation on the device, task scheduling on GPU cores, and partitioning the GPU for multitenant usage. It's important to keep the NVIDIA driver up-to-date».

Exposition of content

In the chapter, the driver is described as the interface between the OS and the hardware. It translates CUDA Runtime commands into GPU commands and manages device memory. The nvidia-smi utility ships with the driver and allows monitoring temperature, utilization, ECC status, and enabling modes such as persistence.

The key point: the driver version must match the CUDA version inside the container. For CUDA 13.x, the minimum driver version is R580; for CUDA 12.x — R525. A version mismatch leads to CUDA initialization errors.

Practical consequence: all cluster nodes must have identical driver and CUDA versions. A mismatch means some nodes work and others don't, and diagnosis takes hours.

Block 03 Summary
Key point of the chapter

The driver is the interface between OS and GPU. Its version must match the CUDA version in the container.

Practical consequence

Identical driver versions on all nodes. Verify version compatibility via nvidia-smi and nvcc --version. Test on staging before updating production.

• • •
Block 04 · Runtime

CUDA Toolkit and Runtime

Quote from the book · Chapter 3

«On top of the driver sits the CUDA Runtime and libraries called the CUDA Toolkit. The toolkit includes the CUDA compiler, nvcc, used to compile CUDA C++ kernels. When compiled, CUDA programs link against the CUDA runtime (cudart). Additionally, the CUDA Toolkit provides many optimized libraries: cuDNN for neural network primitives, cuBLAS for linear algebra, NCCL for multi-GPU communication».

Exposition of content

In the chapter, CUDA Toolkit is described as a set of libraries and compilers that translate high-level operations into GPU commands. nvcc compiles CUDA C++ into PTX and SASS, cuDNN and cuBLAS implement optimized primitives, NCCL provides collective operations between GPUs.

Practical consequence: using the latest CUDA Toolkit version that supports your compute capability provides access to new compiler and library optimizations. For example, cuBLAS in new versions may use Tensor Cores more efficiently or support new data formats.

The chapter separately mentions that compiled code contains both PTX (virtual intermediate representation) and CUBIN (SASS for a specific architecture). PTX allows JIT compilation for future architectures, CUBIN runs directly on known ones.

Figure 3-2. nvcc Compilation Pipeline

Virtual IR and physical binaries

CUDA Program (.cu)
Virtual / Source
nvcc Compiler
Front-end
PTX (Intermediate IR)
Forward-compatible
sm_90 (Hopper)
sm_100 (Blackwell)
future GPU
Description: PTX is a forward-compatible virtual IR: the driver can JIT-compile it for future architectures. CUBIN is pre-compiled SASS for a specific architecture — faster, but not forward-compatible. A fatbinary bundles both.
Block 04 Summary
Key point of the chapter

CUDA Toolkit is a set of optimized libraries that translate high-level operations into GPU commands. Toolkit version must match GPU compute capability.

Practical consequence

Updating CUDA Toolkit provides access to new optimizations. PTX ensures forward compatibility, CUBIN — maximum performance on known architectures.

• • •
Block 05 · Compatibility

CUDA Compatibility Across GPU Generations

Quote from the book · Chapter 3

«An important feature of NVIDIA's GPU programming model is its compatibility across hardware generations. When you compile CUDA code, the resulting binary includes virtual, or intermediate, PTX code as well as physical device code. This is achieved through NVIDIA's fatbinary model, which contains PTX for future-proofing and CUBIN, or architecture-specific CUDA device code binaries, for known architectures».

Exposition of content

In the chapter, the fatbinary model is described as a mechanism providing both backward and forward compatibility. PTX is a virtual intermediate representation that the driver can JIT-compile for a specific architecture at runtime. CUBIN is pre-compiled SASS that executes directly, but only on a specific architecture.

Practical consequence: if you ship only CUBIN for a specific architecture (e.g., sm_90 for Hopper or sm_100 for Blackwell) without PTX, the binary won't run on future architectures. If you ship PTX, the driver can compile it, but with some JIT compilation overhead.

The chapter's recommendation: include both CUBIN and PTX in the binary. This provides maximum performance on known architectures and compatibility with future ones.

Clarification based on current data

Starting with CUDA 12.x, NVIDIA introduced the concept of "family-specific" targets: sm_100f for Blackwell. This allows compiling code that uses family-specific features while remaining compatible within the family. For maximum portability, it is recommended to compile with generic targets and explicitly include PTX.

Block 05 Summary
Key point of the chapter

Fatbinary with PTX + CUBIN provides both performance and compatibility. Without PTX, the binary won't run on future GPUs.

Practical consequence

Compile with generic targets and include PTX for future compatibility. Use family-specific targets only when specific optimizations are needed.

• • •
Block 06 · Libraries

CUDA Libraries for C++ and Python

Quote from the book · Chapter 3

«While most CUDA toolkit libraries are C++, NVIDIA's current Python-facing options include CUDA Python, cuPyNumeric, CuTe DSL, cuTile, and CuPy for array programming; and NVIDIA Warp for authoring GPU kernels in Python. CUTLASS is a C++ templated library used under the hood by libraries such as cuBLAS rather than a Python library».

Exposition of content

The chapter describes Python-oriented NVIDIA libraries that lower the barrier to entry for developers. cuTile simplifies working with large matrices through tiling. cuPyNumeric replaces numpy. Triton (from OpenAI) allows writing GPU kernels in Python.

Practical consequence: for researchers and developers unfamiliar with CUDA C++, these libraries provide the ability to write high-performance GPU code. Under the hood, they still compile to PTX and SASS, but the programmer works with Python abstractions.

Block 06 Summary
Key point of the chapter

Python-oriented libraries (cuTile, cuPyNumeric, Triton) lower the barrier to entry for developers unfamiliar with CUDA C++.

Practical consequence

For new projects, Python abstractions can be used. For maximum control — CUDA C++ and CUTLASS.

• • •
Block 07 · Frameworks

PyTorch and High-Level Frameworks

Quote from the book · Chapter 3

«When you perform operations on PyTorch tensors using GPUs, they are moved from the CPU to the GPU in what appears to be a single Python call. However, this single call is actually translated into a series of calls to the CUDA runtime utilizing various CUDA libraries».

Exposition of content

The chapter traces the chain from Python code to GPU: PyTorch Python API → PyBind11 → ATen Dispatcher → CUDA Runtime API → GPU Kernel Execution. Each transition adds overhead, but PyTorch abstracts it, allowing intuitive Python code.

Practical consequence: understanding this chain helps diagnose where performance is lost. For example, if an operation is too small, the overhead of transitions between levels may exceed the gain from computations.

Figure 3-3. PyTorch Code → GPU Device

One Python call → many CUDA runtime invocations

PyTorch
Python API
torch.Tensor op
→
PyBind11
binding to C++
→
ATen
Dispatcher
C++ backend
→
CUDA Runtime API
cudaMemcpy / cudaLaunchKernel
→
GPU Kernel
Execution
on-device
Description: A thin layer between PyTorch's high-level API and the hardware. Each hop adds overhead; understanding this chain helps pinpoint where performance is lost.
Block 07 Summary
Key point of the chapter

PyTorch abstracts CUDA complexity, but each level of the chain adds overhead.

Practical consequence

For small operations, overhead of transitions between levels may exceed the gain. Using torch.compile and CUDA Graphs reduces this overhead.

• • •
Block 08 · NUMA

NUMA Topology and CPU Pinning

Quote from the book · Chapter 3

«Modern server CPUs have dozens of cores and are often split into multiple NUMA nodes. A NUMA node is a logical grouping of CPUs, GPUs, network interface controllers (NICs), and memory that are physically close to one another. Accessing resources within a single NUMA node is faster than accessing resources in other NUMA nodes».

Exposition of content

In the chapter, NUMA topology is described as one of the main sources of hidden latency. When a process on a CPU in one NUMA node accesses a GPU in another, data travels over the inter-node bus with elevated latency. In one experiment, local NUMA access latency was ~80 ns versus ~139 ns for remote — about a 75% increase.

Practical consequence: pinning a process to the CPU on the same NUMA node as its GPU eliminates this traffic. In practice this yields +5–10% training throughput and reduces jitter. Tools: numactl --cpunodebind and taskset.

The chapter separately notes that on CPU-GPU superchip systems (Grace Blackwell), CPU and GPU are linked by NVLink-C2C with coherent memory access. This reduces the severity of the problem, but Linux still models CPU DRAM and GPU HBM as separate pools, and binding to the local NUMA node remains beneficial.

Figure 3-4. NUMA Topology: 8 GPUs Across 2 NUMA Nodes

CPU pinning and memory locality

NUMA node 0

CPU 0-7
GPU 0 GPU 1 GPU 2 GPU 3
DRAM 0
Interconnect
Remote access: ~75% slower

NUMA node 1

CPU 8-15
GPU 4 GPU 5 GPU 6 GPU 7
DRAM 1
Description: Pinning a process to the CPU on the same NUMA node as its GPU eliminates cross-NUMA traffic. In practice this yields +5–10% training throughput and reduces jitter.
Block 08 Summary
Key point of the chapter

NUMA topology is a source of hidden latency. Remote memory access is ~75% slower than local.

Practical consequence

Pin processes to the CPU on the same NUMA node as the GPU via numactl --cpunodebind. This yields +5–10% throughput and reduces jitter.

• • •
Block 09 · Memory

NUMA-Aware Memory and Pinning

Quote from the book · Chapter 3

«By default, a process will allocate memory from the NUMA node of the CPU it's currently running on. The numactl --membind option forces memory allocation from a specific NUMA node. Pinned memory (page-locked or nonpageable) is essential for efficient and direct GPU access. Copying data from pinned host memory to GPU can be 2–3× faster than from regular pageable memory».

Exposition of content

In the chapter, pinned memory is described as a key element for fast CPU → GPU data transfer. Regular pageable memory can be paged to disk, so the GPU/NIC cannot perform DMA directly. Pinned memory is locked in RAM, and DMA is performed directly.

Practical consequence: in PyTorch DataLoader, the pin_memory=True flag enables pinned memory. This yields 2–3× faster H2D copies. However, pinned memory has a limit controlled by ulimit -l. If the limit is too low, allocation may fail, and the system will fall back to regular memory.

Recommendation: set ulimit -l unlimited for large AI workloads.

Figure 3-5. Pinned (Page-Locked) vs Pageable Memory

Direct DMA vs pageable memory

Pageable Memory
Disk ↔ RAM swapping enabled
→
Pinned Memory
Page-locked · DMA ready
→
GPU
Description: Pinned memory cannot be paged to disk, so GPU/NIC performs DMA directly. That yields 2–3× faster H2D copies. In PyTorch enable it with pin_memory=True in the DataLoader.
Block 09 Summary
Key point of the chapter

Pinned memory is the key to fast CPU → GPU data transfer. Direct DMA yields 2–3× speedup.

Practical consequence

pin_memory=True in DataLoader, ulimit -l unlimited for large allocations. For NUMA locality — numactl --membind.

• • •
Block 10 · Pages and Scheduler

Huge Pages, Scheduler, and IRQ Affinity

Quote from the book · Chapter 3

«Huge pages — 2 MB or even 1 GB — can reduce the overhead of virtual memory management by making memory chunks bigger. The main benefits are fewer page faults and less pressure on the translation lookaside buffer (TLB). Hugepages typically produce modest gains — often on the order of 3–5% throughput improvement. Hardware interrupts from each device should be pinned to cores on the same NUMA node».

Exposition of content

In the chapter, transparent hugepages (THP) are described as a simple way to reduce memory management overhead. 2 MB pages instead of 4 KB reduce the number of TLB entries and page faults. The gain is modest but consistent.

However, for latency-sensitive inference, disabling THP is recommended. Background compaction can cause unpredictable pauses. This is a classic trade-off: throughput vs latency.

IRQ affinity is another aspect. If interrupts from GPU or NIC are handled on a core in another NUMA node, this adds latency and causes coherency traffic. Pinning interrupts to local cores eliminates this problem.

Block 10 Summary
Key point of the chapter

THP provide +3–5% throughput, but can cause pauses. For inference, disabling is recommended.

Practical consequence

Pin IRQs to local NUMA cores. Disable irqbalance or configure rules. For latency-critical workloads — transparent_hugepage=never.

• • •
Block 11 · Virtual Memory and Frequency

Virtual Memory, Swapping, and CPU Frequency

Quote from the book · Chapter 3

«Always try to avoid memory swapping. If any part of your process's memory gets swapped to disk, you will see a catastrophic, multiple-orders-of-magnitude slowdown. Set vm.swappiness = 0. For maximum and consistent performance, AI systems often configure the CPU frequency governor to "performance" mode».

Exposition of content

In the chapter, swapping is described as a catastrophe for GPU workloads. If process memory is paged to disk, the GPU will wait for data to return to RAM. This is an order-of-magnitude slowdown. The book's recommendation is vm.swappiness = 0 with sufficient RAM. On modern kernels there's a caveat: 0 does not fully disable swapping and increases the risk of a hard OOM, so values of 1–10 are more often recommended (see the clarification in "Forecast Verification").

CPU frequency and C-states are the second aspect. In power-saving mode, the CPU may enter deep sleep, and wake-up takes microseconds. For GPU workloads where predictability is important, performance mode and disabling deep C-states are recommended.

Practical consequence: on GPU servers, CPU governor should be in performance mode, and C-states limited. This increases power consumption but ensures stability.

Block 11 Summary
Key point of the chapter

Swapping is a catastrophe for GPU workloads. vm.swappiness = 0 is the book's recommendation; on modern kernels 1–10 are common.

Practical consequence

CPU governor in performance mode, deep C-states disabled. This is a trade-off: more power, but more stable latency.

• • •
Block 12 · Allocator

CPU Memory Allocator Tuning

Quote from the book · Chapter 3

«By tuning your host's memory allocator (jemalloc or tcmalloc), you can eliminate unpredictable pauses in data preparation. With jemalloc, you can shard allocations into per-CPU arenas, enable background_thread for off-path purging, and lengthen dirty_decay_ms/muzzy_decay_ms».

Exposition of content

In the chapter, the memory allocator is described as a source of unpredictable pauses. Standard malloc can block threads during allocation, creating jitter. jemalloc and tcmalloc solve this through per-CPU arenas and background purging.

Practical consequence: for CPU-bound data pipelines (data loading, tokenization, augmentation), allocator tuning can yield noticeable stability gains. This does not increase average performance but reduces tail latencies.

The chapter's recommendation: use MALLOC_CONF with narenas:8, dirty_decay_ms:10000, muzzy_decay_ms:10000, background_thread:true.

Block 12 Summary
Key point of the chapter

The memory allocator is a source of unpredictable pauses. jemalloc/tcmalloc smooth out jitter.

Practical consequence

Configure MALLOC_CONF for per-CPU arenas and background purging. This reduces tail latencies in the data pipeline.

• • •
Block 13 · Persistence

GPU Persistence Mode

Quote from the book · Chapter 3

«By default, if no application is using a GPU, the driver may put the GPU into a lower-power state and unload some of the driver's context. Initialization can take on the order of a second or two. Persistence mode is enabled by running the nvidia-persistenced daemon and keeps the GPU driver loaded and the hardware in a ready state».

Exposition of content

In the chapter, persistence mode is described as a way to avoid job startup latency. Without it, the first CUDA call after idle time may take a second or two. With it, the GPU is always ready.

Practical consequence: on AI clusters, persistence mode is enabled on all GPUs at server boot. This does not accelerate computations but cuts startup latency. Especially important when using MIG, where the configuration is reset on each startup without persistence.

Recommendation: systemctl enable nvidia-persistenced.

Block 13 Summary
Key point of the chapter

Persistence mode cuts job startup latency. The GPU is always ready.

Practical consequence

systemctl enable nvidia-persistenced on all GPU servers. Especially important when using MIG.

• • •
Block 14 · MPS and MIG

MPS and MIG

Quote from the book · Chapter 3

«Normally, when multiple processes share a single GPU, the GPU's scheduler timeslices between them. NVIDIA's MPS is a feature that creates a sort of umbrella under which multiple processes can run on the GPU concurrently. MIG allows a GPU to be sliced into as many as seven smaller logical GPUs — each with its own dedicated portion of memory and compute units».

Exposition of content

In the chapter, MPS and MIG are described as tools for raising utilization. MPS allows multiple processes to share a GPU without time-slicing, raising utilization. MIG provides hardware isolation with dedicated SMs, L2, and HBM.

Practical consequence: MPS is suitable for inference workloads where individual tasks don't load the GPU fully. MIG — for multi-tenancy and isolation. However, for tightly-coupled training workloads where all GPUs must work synchronously, MIG is not suitable due to P2P being disabled.

Important limitation: at the time of writing, P2P between MIG instances is disabled. This makes MIG unsuitable for distributed training but useful for inference.

Figure 3-6. GPU Without MPS — Time-Slicing with Idle Gaps

Sequential switching between processes

t₀t₁t₂t₃t₄t₅t₆t₇
Process A
A
idle
A
idle
A
idle
A
idle
Process B
idle
B
idle
B
idle
B
idle
B
Process A kernels Process B kernels Idle gap
⚠ GPU ≈ 50% idle from ping-pong switching

Figure 3-7. GPU With MPS — Overlapping

Concurrent kernel execution across processes

t₀t₁t₂t₃t₄t₅
Process A
A
A
A
A
A
A
Process B
B
B
B
B
B
B
GPU (SM)
A+B
A+B
A+B
A+B
A+B
A+B
Process A kernels Process B kernels Concurrent execution
✓ Idle gaps eliminated, GPU utilization ↑ 80–90%

Figure 3-8. Seven MIG Slices on One GPU

Hardware isolation of SM, L2, and HBM

PHYSICAL GPU USER 0 1g.23gb USER 1 2g.45gb USER 2 3g.90gb USER 3 4g.90gb USER 4 5g.112gb USER 5 6g.135gb USER 6 7g.180gb

MIG — hardware isolation: dedicated SMs, L2 slices, and HBM. Up to 7 isolated GPU instances on a single board.

Description: Strong isolation for multi-tenant inference. However, at the time of writing P2P between MIG instances is disabled — including NVLink and PCIe. MIG is not suited for large-scale distributed training.
Block 14 Summary
Key point of the chapter

MPS — for raising utilization through concurrent execution. MIG — for hardware isolation and multi-tenancy.

Limitation

P2P between MIG instances is disabled. MIG is not suitable for tightly-coupled training workloads. For inference — yes, for training — no.

Practical consequence

MPS — for inference clusters. MIG — for multi-tenant inference servers. Do not use MIG for distributed training.

• • •
Block 15 · Containers

Optimizing Containers for GPU

Quote from the book · Chapter 3

«A container on a node shares the host OS kernel so that CPU and memory operations perform at near-native speed. With the NVIDIA Container Toolkit, GPU access from within a Docker container is direct and does not incur overhead. Modern benchmarks (MLPerf Inference v5.0) demonstrate that properly configured containers differ by < 2% from bare metal. Use official NVIDIA base images from NGC».

Exposition of content

In the chapter, containers are described as a way to ensure environment reproducibility without performance loss. NVIDIA Container Toolkit allows the container to directly access the GPU. The difference from bare metal is less than 2%.

Practical consequence: the host driver version must be no older than the minimum required by the CUDA version inside the container. For CUDA 13.x — R580+, for CUDA 12.x — R525+. A mismatch leads to initialization errors.

The chapter separately addresses the OverlayFS problem: copy-on-write adds I/O overhead. For intensive training, mount host directories into the container via bind mounts — they bypass overlay.

Block 15 Summary
Key point of the chapter

Containers with NVIDIA Container Toolkit deliver performance within 2% of bare metal when properly configured.

Practical consequence

Driver and CUDA versions must match. Bind mounts for I/O-intensive workloads. Official NGC images as a base.

• • •
Block 16 · Orchestration

Kubernetes for Topology-Aware Orchestration

Quote from the book · Chapter 3

«Kubernetes (K8s) is a popular container orchestrator for AI training and inference. The NVIDIA device plugin for Kubernetes advertises GPU hardware to the scheduler. The NVIDIA Kubernetes GPU Operator automates the installation and lifecycle of all NVIDIA software, including DCGM monitoring. Kubernetes Topology Manager can provide detailed topology information».

Exposition of content

In the chapter, Kubernetes is described as an orchestrator that can account for GPU topology. NVIDIA device plugin makes GPUs visible to the scheduler, GPU Operator automates software management, Topology Manager provides topological awareness.

Practical consequence: for multi-GPU tasks, topology-aware scheduling is important. Policies best-effort, restricted, or single-numa-node help place pods on NVLink-connected GPUs and avoid cross-NUMA traffic.

The chapter separately addresses the MIG problem: the scheduler cannot split a request across GPUs or nodes. If no single node has the required number of free slices, the pod stays in Pending.

Block 16 Summary
Key point of the chapter

Kubernetes with NVIDIA device plugin and Topology Manager provides topology-aware GPU placement.

Practical consequence

Topology Manager policies to minimize cross-NUMA traffic. Host networking for RDMA. MIG pods require whole slices on one node.

• • •
Block 17 · Forecast Verification

Forecast Verification and Current Data

Fregly's book was written in 2025. Much has changed since. Below is a comparison of the chapter's forecasts with open data and clarification of figures.

Confirmed Forecast 1: System optimizations yield double-digit percentage improvements

«System-level optimizations often remain in the shadow of algorithmic ones, but can yield double-digit percentage improvements».

Confirmed. In practice, NUMA pinning yields +5–10%, pinned memory — 2–3× on H2D, persistence mode cuts seconds of startup latency. Combined at cluster scale, this translates into millions of dollars in savings.

Confirmed Forecast 2: MIG and MPS will become standard for multi-tenancy

«MPS and MIG — tools for raising utilization».

Confirmed. In 2025–2026, MIG and MPS became standard for inference clusters. Kubernetes device plugin and GPU Operator support automatic MIG profile management. NVIDIA Dynamo uses MIG for multi-tenant inference.

Confirmed Forecast 3: Containers will not cost performance

«Modern benchmarks demonstrate that properly configured containers differ by < 2% from bare metal».

Confirmed — with a source caveat. MLPerf Inference v5.0 is a benchmark of inference system performance, not a comparison of containers vs. bare metal — it does not measure containerization overhead as such. The «under 2%» figure comes from NVIDIA Container Toolkit practice, reinforced by the fact that most MLPerf submissions run on NVIDIA's official container stack (Container Toolkit, NGC base images) with no measurable degradation versus native execution. The conclusion itself holds: Red Hat OpenShift and Kubernetes are widely used in production deployments.

Clarification vm.swappiness = 0 needs a caveat

«Set vm.swappiness = 0».

The motivation is right, the implementation is dated. On modern Linux kernels, 0 does not fully disable swapping: under memory pressure anonymous pages still get paged out, and the node reaches a hard OOM sooner instead of degrading gracefully. For ML nodes, low values of 1–10 with sufficient RAM are the common recommendation; dropping the swap partition entirely is a deliberate choice for clusters with strict memory placement control.

Partially confirmed Forecast 4: P2P between MIG instances is disabled

«At the time of writing P2P between MIG instances is disabled — including NVLink and PCIe».

Partially confirmed. The limitation persists in most configurations. However, NVIDIA is working on improving MIG isolation and P2P may become available in future generations. For now, MIG is not recommended for distributed training.

Addition Kubernetes Topology Manager and DRA

The chapter describes Topology Manager but does not mention Dynamic Resource Allocation (DRA). In 2025, DRA became a key mechanism for flexible GPU resource allocation in Kubernetes. DRA allows declarative description of GPU resources, including MIG profiles, and dynamic allocation. This provides greater flexibility than the static device plugin.

Addition NVIDIA Dynamo and disaggregated inference

The chapter focuses on Kubernetes as an orchestrator but does not mention NVIDIA Dynamo — a framework for disaggregated inference that uses NIXL for KV cache transfer and integrates with Kubernetes. Dynamo became the standard for production disaggregated prefill/decode deployments in 2025–2026.

• • •
Block 18 · Missing Aspects

What's Not Covered in the Chapter

The chapter describes the architecture and principles but leaves out several aspects that emerged in real-world operation.

Additional observations

DRA (Dynamic Resource Allocation) — in 2025, Kubernetes introduced DRA as a replacement for the static device plugin. DRA allows declarative description of GPU resources, including MIG profiles, and dynamic allocation. This provides greater flexibility for multi-tenant clusters.

NVIDIA Dynamo — a framework for disaggregated inference that integrates with Kubernetes and uses NIXL for KV cache transfer. Dynamo became the standard for production deployments in 2025–2026.

GPU Operator and MIG Manager — GPU Operator automates MIG management, including recreating profiles after reboot. This solves the problem of MIG configuration reset on restart.

Container Device Interface (CDI) — a standard for describing GPU devices in containers. CDI simplifies GPU passthrough to containers and is used in modern versions of NVIDIA Container Toolkit.

• • •
Block 19 · Takeaways

Key Takeaways

  1. Data and compute locality is critical. Use local NVMe SSD caches and minimize network I/O.
  2. Adopt NUMA-aware configuration and CPU affinity. numactl and taskset prevent cross-NUMA traffic.
  3. Maximize driver efficiency. Enable persistence mode; use MPS or MIG for multi-tenant environments.
  4. Preload and batch data. Use prefetch_factor and pin_memory=True in the DataLoader.
  5. Optimize memory transfer. Pinned memory and huge pages accelerate H2D.
  6. Overlap communication with compute. DDP with bucket size ~25 MiB is standard.
  7. Tune the network stack. RDMA, jumbo frames, IRQ affinity.
  8. Containers should not cost performance. Use NVIDIA Container Toolkit and bind mounts.
  9. Topology-aware scheduling. Kubernetes Topology Manager and NVIDIA device plugin.
  10. DRA and Dynamo — new standards. Dynamic Resource Allocation for flexible GPU allocation, Dynamo for disaggregated inference.
Overall Review Summary

Chapter 3 of Fregly's book is a systematic overview of the GPU system environment. The key idea: performance is the result of the entire stack, from OS to Kubernetes. An engineer must be equally comfortable at all levels. Forecast verification shows: the book proved accurate in its predictions. MIG and MPS became standard, containers don't cost performance, NUMA optimizations yield double-digit percentages. The main takeaway: system-level optimizations are not a "soft" part but a mandatory element of performance.

Sources: Chris Fregly, «AI Systems Performance Engineering» (O'Reilly, 2026), Chapter 3 — quotes provided in limited volume for review and critical analysis purposes. NVIDIA Container Toolkit documentation; NVIDIA Kubernetes GPU Operator; MLPerf Inference v5.0; Uptime Institute; Dell'Oro Group.