Настоящий материал представляет собой обзор шестнадцатой главы книги 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 посвящена профилированию, отладке и настройке производительности инференса LLM в масштабе. Глава охватывает полный цикл: от мониторинга и сбора метрик до конкретных техник оптимизации — динамического батчинга, планирования, квантования и оптимизаций на уровне приложений. Значительное внимание уделяется практическим аспектам эксплуатации inference-кластеров: диагностике неполадок, работе с KV-кэшем, управлению памятью и обеспечению качества обслуживания (QoS).
«Эксплуатация крупного кластера для инференса LLM требует инструментов мониторинга и отладки, которые гарантируют, что всё работает как ожидается. Они также помогают быстро выявлять узкие места, когда производительность отклоняется от целевой».
Глава построена как практическое руководство по эксплуатации inference-кластеров. Сначала рассматриваются инструменты профилирования и мониторинга (Nsight Systems, Nsight Compute, Prometheus, Grafana, DCGM), затем — методология диагностики неполадок и рецепты устранения типовых проблем. Далее следуют конкретные техники оптимизации: динамический батчинг, непрерывное планирование, чанковый префилл, перекрытие коммуникаций и вычислений, управление памятью и KV-кэшем, квантование для инференса и оптимизации на уровне приложений. Завершается глава вопросами QoS, раннего отклонения запросов и fault tolerance.
Ключевая идея главы: производительность inference-системы — это не только скорость отдельных ядер, но и эффективность планирования, управления памятью и обработки запросов на всех уровнях стека. Инженер по производительности должен уметь измерять, диагностировать и оптимизировать каждый из этих уровней.
Производительность инференса LLM — это многоуровневая задача, охватывающая мониторинг, планирование, управление памятью и оптимизацию на уровне приложений.
Инженер должен уметь работать с инструментами профилирования (Nsight, DCGM, PyTorch Profiler) и применять техники оптимизации на каждом уровне стека.
Фундаментальная методология настройки производительности инференса — итеративный цикл:
Развёртывание новой версии движка инференса или квантованной модели на всём кластере одновременно — это риск превратить 5-минутную оптимизацию в часовой даунтайм. Инкрементальный подход ограничивает «радиус поражения» и позволяет откатить изменение до того, как оно затронет всех пользователей.
Настройка производительности — непрерывный цикл: наблюдение → гипотеза → исправление → проверка → повтор. Каждое исправление вскрывает следующее узкое место.
Изменения вносятся по одному, с измерением эффекта каждого. Канареечные выкатки ограничивают риск.
NVIDIA Nsight Systems — это профилировщик уровня системы, который показывает временную шкалу работы CPU и GPU с микросекундным разрешением. Видны потоки CPU, ядра GPU, события CUDA, коммуникации NCCL, операции memcpy — всё на единой шкале времени.
Ключевая техника — аннотация NVTX (NVIDIA Tools Extension). Пометка регионов кода метками вроде «Prefill», «Decode», «All-to-all» даёт цветные блоки на временной шкале, по которым сразу видно, сколько времени занимает каждая фаза и где возникают простои.
#include <nvtx3/nvToolsExt.h>
#include "my_model.hpp"
#include <vector>
#define NVTX_PUSH(name, argb) \
do { \
nvtxEventAttributes_t a{}; \
a.version = NVTX_VERSION; \
a.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE; \
a.colorType = NVTX_COLOR_ARGB; \
a.color = (unsigned int)(argb); \
a.messageType = NVTX_MESSAGE_TYPE_ASCII; \
a.message.ascii = (name); \
nvtxRangePushEx(&a); \
} while (0)
#define NVTX_POP() do { nvtxRangePop(); } while (0)
void run_inference(
const std::vector<Token>& prompt_tokens,
Model& model,
int num_generate_steps) {
NVTX_PUSH("Prefill", 0xFF4F86F7);
model.encode(prompt_tokens);
NVTX_POP();
for (int t = 0; t < num_generate_steps; ++t) {
NVTX_PUSH("Decode", 0xFFFF8C00);
Token next_token = model.decode_next();
NVTX_POP();
}
}
Для многопоточных сценариев критически важно именовать потоки CUDA и оборачивать каждый в отдельные диапазоны NVTX. Без именования потоков дорожки GPU на временной шкале выглядят как бессмысленная мешанина — с именованием сразу видно, перекрываются ли передача данных и вычисления.
Nsight Compute профилирует отдельные ядра CUDA. Можно сосредоточиться на конкретных частях ядра — например, на транзакциях памяти — через профилирование по секциям.
Менее известная, но крайне полезная функция — CUDA Program Counter (PC) Sampling. Она сэмплирует счётчики программы и выявляет горячие точки внутри ядер с минимальными накладными расходами. В отличие от полной трассировки, PC Sampling можно запускать на живых продакшен-серверах, не деградируя обслуживание.
Сэмплирование счётчика команд для поиска горячих инструкций
PyTorch Profiler, основанный на библиотеке Kineto, предоставляет разбивку на уровне операторов для CPU и GPU. Он записывает формы тензоров, снимки памяти и поддерживает экспорт трассировок в Chrome Tracing / Perfetto для совместного анализа.
with torch.profiler.profile(
activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA],
record_shapes=True,
profile_memory=True,
with_stack=True
) as prof:
with profiler.record_function("train_step"):
torch.cuda.nvtx.range_push("forward")
outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
loss = outputs.loss
torch.cuda.nvtx.range_pop()
torch.cuda.nvtx.range_push("backward")
loss.backward()
torch.cuda.nvtx.range_push("optimizer_step")
optimizer.step()
torch.cuda.nvtx.range_pop()
optimizer.zero_grad()
torch.cuda.nvtx.range_pop()
print(prof.key_averages().table(
sort_by="self_cuda_time_total",
row_limit=10,
fields=["self_cuda_time_total", "calls"]
))
Профилирование — двухэтапный процесс: Nsight Systems для общей картины и поиска горячих ядер, Nsight Compute для детального анализа. NVTX-аннотации делают временную шкалу читаемой.
PyTorch Profiler (на базе Kineto) даёт op-уровневую разбивку и поддерживает экспорт в Chrome Tracing / Perfetto. PC Sampling в Nsight Compute позволяет локализовать горячие инструкции с минимальными накладными расходами.
В продакшене постоянный мониторинг важнее эпизодического профилирования. Стек Prometheus + Grafana + DCGM — стандарт де-факто для GPU-кластеров.
Поток метрик от GPU-узлов к дашбордам
| Метрика | DCGM-счётчик | Что означает |
|---|---|---|
| Загрузка SM | DCGM_FI_DEV_GPU_UTIL | Процент времени, когда SM заняты |
| Загрузка copy-движка | DCGM_FI_DEV_MEM_COPY_UTIL | Активность движков копирования памяти |
| Использование памяти | DCGM_FI_DEV_FB_USED | Занятая память фреймбуфера |
| Температура | DCGM_FI_DEV_GPU_TEMP | Температура GPU |
| Энергопотребление | DCGM_FI_DEV_POWER_USAGE | Мощность в ваттах |
| Ошибки ECC | DCGM_FI_DEV_ECC_* | Корректируемые и неисправимые ошибки |
| Ошибки NVLink | DCGM_FI_DEV_NVLINK_* | Повторы, CRC, восстановление линков |
vllm:gpu_prefix_cache_queries и vllm:gpu_prefix_cache_hits в vLLM.| Метрика | Условие | Серьёзность | Примечания |
|---|---|---|---|
| Загрузка GPU | < 10% более 60 с | Простой | Недоиспользование |
| Загрузка GPU | > 90% | Узкое место | Возможное насыщение |
| Использование памяти | > 80% | Предупреждение | Приближение к OOM |
| Использование памяти | > 95% | Критично | Высокий риск OOM |
| Температура | > 85 °C | Предупреждение | Приближение к троттлингу |
| Температура | > 95 °C | Критично | Риск повреждения |
| Ошибки NVLink (повтор) | ≥ 1 | Критично | Проблема линка |
| Ошибки CRC NVLink | > 100/с | Критично | Деградация линка |
| Неисправимые ошибки ECC | ≥ 1 | Критично | Повреждение данных |
Числовые значения — ориентировочные. Фактические пороги зависят от архитектуры GPU, условий охлаждения и SLO. Настраивайте их на основе baseline-измерений.
NCCL_COMM_FAILURE в логах.Пример лога vLLM, указывающего на преемпцию KV-кэша:
WARNING 2025-05-03 14:22:07 scheduler.py:1057 Sequence group 0 is preempted by
PreemptionMode.RECOMPUTE because not enough KV cache space.
total_cumulative_preemption_cnt=1
Это означает, что движку не хватило памяти для KV-кэша, и он вытеснил активную последовательность. Результат — пересчёт KV при повторном планировании, дополнительные вычисления и рост задержки. Если такие сообщения появляются регулярно: увеличьте порог использования памяти GPU, уменьшите максимальное число батчированных токенов, включите PagedAttention или рассмотрите квантование KV-кэша.
Постоянный мониторинг через Prometheus + Grafana + DCGM — стандарт де-факто для GPU-кластеров. Ключевые метрики: загрузка SM, использование памяти, перцентили задержки, доля попаданий в кэш.
Корреляция метрик (RPS + p99, SM + copy-движок, NCCL errors + загрузка GPU) позволяет быстро локализовать первопричину.
| Симптом | Вероятная причина | Рекомендуемое действие |
|---|---|---|
| Загрузка SM < 50% | Маленькие батчи или отсутствие fused-ядер | Увеличить размер батча, включить FlashAttention, добавить fused-ядра, профилировать через nsys --trace=cuda |
| Предупреждения о преемпции KV-кэша | Недостаточно места в KV-кэше | Повысить порог памяти GPU, уменьшить max batch tokens, включить PagedAttention |
| Высокая хвостовая задержка (p95 > 200 мс) | Горячая точка декодирования или блокировка головы очереди | Проверить логи маршрутизатора, настроить порог предвыборки, включить спекулятивное декодирование |
| Доля попаданий в кэш < 60% | Несбалансированный шардинг или отсутствие префиксного кэша | Проверить конфигурацию префиксного кэша (LMCache, NIXL), увеличить TTL, добавить реплики |
| Неожиданный OOM | Перегрузка памяти GPU | Снизить память на инстанс, включить выгрузку на CPU/NVMe, привязать процессы к сокетам |
| Нерегулярные выбросы | Тепловой троттлинг или несогласованные частоты | Синхронизировать частоты, следить за температурой, ограничить частоту через nvidia-smi -lgc |
compute-sanitizer --tool memcheck your_binary для обнаружения ошибок памяти, гонок данных и выходов за границы.NCCL_DEBUG=WARN для подробных логов. Используйте ncclCommGetAsyncError с ncclCommAbort для обнаружения и обработки асинхронных ошибок.Диагностика неполадок инференса — систематический процесс: от симптома к вероятной причине и конкретному действию. Таблица рецептов покрывает типовые сценарии.
Для отладки корректности используются compute-sanitizer, NCCL_DEBUG и мониторинг аппаратных счётчиков ошибок.
Высокопроизводительный инференс требует скоординированных оптимизаций на каждом уровне стека. Проблема только на одном уровне — это удача. В реальности узкие места мигрируют между уровнями по мере их устранения.
| Уровень стека | Ключевые техники |
|---|---|
| Модель | Прунинг, дистилляция, разреженность (MoE), FlashAttention, обучение с учётом квантования (QAT) |
| Ядро | Fused-операции (Linear + GELU + LayerNorm), FlashInfer, Tensor Core, блочный тайлинг, асинхронные передачи (cp.async, TMA) |
| Среда выполнения | Динамический/непрерывный батчинг, PagedAttention, CUDA Graphs, пулинг буферов, многопотоковые CUDA, синхронизация на основе событий |
| Оркестрация | Разделение префилла и декодирования, интеллектуальная маршрутизация, изоляция мультитенантности, автомасштабирование с тёплыми резервами |
| Развёртывание | Геораспределённое граничное обслуживание, умные API-шлюзы с батчингом, CI/CD для вариантов моделей, NVLink/NVSwitch, InfiniBand, NUMA-аффинность |
| QoS и масштабирование | Динамический батчинг с учётом SLA, изоляция через MIG, дашборды профилирования в реальном времени, динамическое переключение параллелизма (TP, PP, DP) |
Ключевая идея — синергии между уровнями. Квантование (модель) снижает потребление памяти, позволяя увеличить размеры батчей (среда выполнения) без OOM, что, в свою очередь, позволяет оркестрации объединять больше запросов на цикл GPU. Одна оптимизация на нижнем уровне может разблокировать несколько оптимизаций на верхних.
Полностековые оптимизации — необходимое условие для высокопроизводительного инференса. Узкие места мигрируют между уровнями по мере их устранения.
Поддерживайте стек ПО в актуальном состоянии. Новые версии CUDA, cuDNN, NCCL, Transformer Engine содержат оптимизации, недоступные на старых версиях.
Статический батчинг фиксирует размер батча, дополняет все последовательности до самой длинной и ждёт завершения каждого запроса перед возвратом. Результат: неограниченная задержка для ранних прибывших запросов и впустую потраченные циклы GPU на паддинг.
Динамический батчинг собирает батчи на лету. Система накапливает входящие запросы в течение короткого таймаута (обычно 2–10 мс) или до достижения целевого размера батча, затем отправляет батч на GPU.
Накопление запросов vs мгновенный старт с тем, что пришло
| Аспект | Статический | Динамический | Непрерывный |
|---|---|---|---|
| Триггер | Фиксированный размер | Цель по размеру или таймаут | Событие завершения токена |
| Ограничение задержки | Неограниченное | Ограничено max_batch_delay_ms | Минимальное |
| Паддинг | Высокий | Умеренный | Низкий |
| Простой GPU | Плохое | Лучше | Отличное |
| Сложность | Простая | Умеренная | Сложная |
Непрерывный батчинг (batching in-flight, iteration-level scheduling) — следующий шаг. Вместо ожидания завершения полных последовательностей, система пополняет батч на каждой итерации генерации токенов. Завершённые запросы вытесняются, новые немедленно занимают их слоты.
Завершённые последовательности уходят, новые встраиваются прямо посреди генерации
Непрерывное планирование относится к GPU как планировщик ОС к CPU. Если модель маленькая или размер батча ограничен SLO, одна копия модели может не насыщать GPU. Тогда движок запускает несколько потоков инференса одновременно на одном GPU.
PagedAttention в vLLM — конкретный пример. KV-кэш разбивается на страницы, и вычисления динамически группируются по страницам между активными последовательностями. Под тяжёлой нагрузкой это даёт почти 100% загрузку GPU.
Когда промпты очень длинные (например, 20 000 токенов), можно разбить их на чанки и чередовать работу префилла и декодирования. Это называется чанковым префиллом (chunked prefill) или планированием без простоев.
| Размер чанка | Число чанков | Операции внимания на чанк | Всего токенов MLP |
|---|---|---|---|
| 20K | 1 | 200M | 20K |
| 10K | 2 | 50M + 150M = 200M | 20K |
| 5K | 4 | 12,5M + 37,5M + 62,5M + 87,5M = 200M | 20K |
Ключевое понимание: чанкирование не уменьшает общее число операций внимания. Self-attention выполняет N(N+1) ÷ 2 скалярных произведений Q × K на слой на голову — стоимость квадратична по N, O(N²). Чанкирование меняет только то, когда работа становится доступной декодеру. Выгода — сглаживание задержки и улучшение перекрытия, а не сокращение вычислений.
Наивный планировщик FIFO может перегрузить один GPU, если порядок прибытия не оптимален. Рассмотрим шесть промптов с длинами 6K, 2K, 6K, 2K, 2K, 2K и два GPU.
Непрерывный батчинг и чанковый префилл — ключевые техники для максимизации пропускной способности при сохранении низкой задержки. Планирование с учётом задержки снижает критический путь на 42% в примере с шестью промптами.
Чанкирование не уменьшает общее число операций внимания — оно только сглаживает задержку и улучшает перекрытие.
В распределённом инференсе перекрытие коммуникаций с вычислениями — критический фактор производительности. Системы вроде GB200/GB300 NVL72 обеспечивают до ~130 ТБ/с агрегированной пропускной способности NVLink внутри стойки, но даже с такими скоростями синхронные коммуникации создают пузыри.
Базовый приём — отдельные потоки CUDA для передачи и вычислений:
cudaStream_t transfer_stream, compute_stream;
cudaStreamCreate(&transfer_stream);
cudaStreamCreate(&compute_stream);
// Передача в transfer_stream
cudaMemcpyAsync(h_logits, d_logits, bytes,
cudaMemcpyDeviceToHost, transfer_stream);
// Вычисление в compute_stream — перекрывается с передачей
my_kernel<<<grid, block, 0, compute_stream>>>(...);
// Синхронизация только когда данные нужны
cudaEventSynchronize(transfer_done_event);
Обязательно используйте page-locked (pinned) буферы хоста для передач по PCIe или NIC — драйвер CUDA может выполнять DMA напрямую и перекрывать с вычислениями.
Для MoE-моделей all-to-all можно перекрыть, разделив батч токенов пополам: пока первая половина обрабатывается экспертами, вторая отправляется. К моменту завершения первой половины данные второй уже прибыли на GPU-получатели.
GPUDirect RDMA позволяет сетевым адаптерам (InfiniBand NIC) читать и писать в память GPU напрямую, минуя память хоста. Это снижает задержку кросс-узловых передач KV-кэша или активаций экспертов и освобождает ядра CPU.
CUDA Graphs позволяют захватить асинхронные паттерны и снизить накладные расходы на запуск ядер — особенно полезно для повторяющихся паттернов декодирования.
Непрерывная работа GPU на 100% вызовет тепловой троттлинг, если охлаждение недостаточно. Иногда работа на 90% с эффективными ядрами превосходит 100% с троттлингом.
nvidia-smi -lgc — незначительно снижает пропускную способность, но обеспечивает стабильность.nvidia-smi -pl (если охлаждение адекватно).Страничный KV-кэш (PagedAttention в vLLM) разбивает KV-кэш на страницы и динамически выделяет их между последовательностями. Это устраняет фрагментацию памяти, свойственную подходам с фиксированным выделением.
Выгрузка KV-кэша (swap) в память CPU или на NVMe — вариант для редко используемых данных. LMCache в vLLM позволяет регулировать соотношение кэша на GPU и CPU. RadixAttention в SGLang лениво вытесняет наименее недавно использованные префиксы.
Однако выгрузка — не бесплатно: при высокой частоте свопа загрузка copy-движков растёт, а загрузка SM падает. Если виден всплеск copy-движка с одновременным падением SM — система свопит. Решения: применить квантование FP8/FP4 для уменьшения размера KV, увеличить выделение памяти GPU под кэш, изменить стратегию свопа.
Перекрытие коммуникаций и вычислений — критический фактор производительности распределённого инференса. GPUDirect RDMA и CUDA Graphs помогают скрыть задержки.
Управление памятью через PagedAttention, LMCache и RadixAttention устраняет фрагментацию и позволяет обслуживать больше одновременных запросов.
| Формат | Бит на элемент | Ускорение vs FP32 | След памяти vs FP32 | Примечания |
|---|---|---|---|---|
| FP32 | 32 | 1× | 1× | Базовая точность |
| TF32 | 19 (мантисса 10 бит) | ~1,5× | 1× | Только Tensor Cores |
| FP16/BF16 | 16 | 2× | 0,5× | Стандарт для инференса |
| FP8 (E4M3/E5M2) | 8 | 4× | 0,25× | Требует калибровки |
| INT4 | 4 | 8× (теоретически) | 0,125× | Квантование только весов |
| FP4 (NVFP4) | 4 + блок-масштабы | ~8× | ~0,18× (с метаданными) | Требует микромасштабирования |
Анализ диапазона, подбор масштаба, перевод в FP8/FP4
Квантование только весов сжимает веса до 4-битных целых, сохраняя активации в более высокой точности (FP8, FP16). Это снижает след памяти весов примерно в 4 раза по сравнению с FP16.
GPTQ применяет приближённый алгоритм второго порядка для послойного квантования весов до 3–4 бит за несколько часов на GPU. Для многих моделей 4-битное GPTQ сохраняет 99%+ точности FP16 с ~2× ускорением инференса.
AWQ (Activation-aware Weight Quantization) идентифицирует небольшую долю «значимых» каналов весов, которые производят большие величины активаций. AWQ применяет масштабирование на конкретный канал перед приведением весов к 4-битной точности.
Квантование активаций сложнее, потому что их распределения сильно варьируются при разных входах. SmoothQuant — метод PTQ для 8-битного квантования активаций без обучения. Он переносит часть ошибки квантования с активаций на веса через простое масштабирование по строкам/столбцам.
Гибридный подход W4A8 сочетает 4-битные веса (INT4) с 8-битными активациями (FP8 или INT8). TensorRT-LLM и другие движки предоставляют этот путь с почти без потерь точности при правильной калибровке.
Квантование — один из самых эффективных способов снижения стоимости инференса. GPTQ и AWQ для 4-битных весов, SmoothQuant для 8-битных активаций, W4A8 для максимальной оптимизации.
Всегда валидируйте точность на downstream-задачах и проводите A/B-тестирование. 4-битное квантование весов сохраняет 99%+ точности для многих моделей.
Механизм внимания трансформера имеет временную сложность O(n²), где n — размер входа в токенах. Сокращение промпта с 10 000 до 5 000 токенов уменьшает работу self-attention в 4 раза.
Кэширование префиксов (мемоизация префиксов) — одна из самых эффективных оптимизаций. Если несколько запросов разделяют общий префикс (системный промпт, документ, история диалога), KV-кэш для префикса вычисляется один раз и переиспользуется.
Без кэширования: N запросов длины L требуют O(N × L) работы. С кэшированием: O(N + L) — префикс обрабатывается один раз, каждый запрос добавляет только свой уникальный суффикс.
Каждый узел — токен, зелёная подсветка — переиспользование общего префикса
enable_prefix_caching=True. Движок определяет, совпадают ли первые N токенов входящего промпта с уже кэшированным префиксом, и если да — копирует данные KV-кэша вместо пересчёта.Новые узлы, активные узлы, вытеснение по LRU
Не все запросы требуют мощности самой большой модели. Каскадирование — подход, при котором простые запросы направляются к меньшей, более быстрой модели, а сложные — к большой.
Маршрутизация 60% запросов к модели в 10 раз меньше может сократить вычислительные затраты в ~5 раз.
Модель генерирует по одному токену за раз (за исключением спекулятивного декодирования EAGLE и много-головного декодирования Medusa). Система группирует токены в батчи по 2–5, сбрасывает поток и отправляет через SSE/WebSockets/HTTP Streaming.
Человек читает со скоростью 4–13 токенов в секунду. Без потоковой выдачи пользователь смотрит на пустой экран 5 секунд, затем получает весь ответ разом. С потоковой выдачей первый батч токенов приходит через 0,25 секунды — и пользователь начинает читать сразу.
Технические детали: TCP_NODELAY для минимизации задержки; потокобезопасные очереди для передачи токенов сетевому потоку; управление контролем потока; HTTP/2 и постоянные соединения.
Короткая пауза после серии кликов перед отправкой запроса
Оптимизации на уровне приложений — сжатие промптов, кэширование префиксов, каскадирование моделей, потоковая выдача — дают значительный эффект без изменения модели или железа.
Кэширование префиксов превращает O(N × L) работы в O(N + L). Сжатие промптов уменьшает работу self-attention квадратично.
Книга Fregly писалась в 2025 году, когда inference-стек активно развивался. Ниже представлено сопоставление прогнозов главы 16 с открытыми данными.
«DCGM собирает метрики с GPU-узлов Kubernetes, Prometheus их накапливает, Grafana визуализирует».
Подтверждено. DCGM Exporter стал стандартом де-факто для GPU-наблюдаемости в Kubernetes. Для vLLM workloads DCGM метрики интегрируются с Prometheus recording rules для расчёта стоимости. AIPerf и другие инструменты включают DCGM/pynvml метрики в выходные данные бенчмарков.
«Continuous batching: завершённые последовательности покидают батч, новые встраиваются прямо посреди генерации».
Подтверждено. Continuous batching реализован в vLLM, SGLang, TensorRT-LLM и стал стандартом для production-инференса. PagedAttention в vLLM и RadixAttention в SGLang обеспечивают динамическое управление KV-кэшем.
«Чанковый префилл: разбить длинные промпты на чанки и чередовать работу префилла и декодирования».
Подтверждено. Chunked prefill реализован в vLLM как stall-free scheduling. Рекомендуемые параметры: --enable-chunked-prefill --max-num-batched-tokens 2048. Это предотвращает блокировку коротких запросов длинными префиллами.
«GPTQ и AWQ для 4-битных весов сохраняют 99%+ точности FP16 с ~2× ускорением».
Подтверждено. GPTQ и AWQ интегрированы в Hugging Face Transformers, vLLM, TensorRT-LLM. W4A8 (INT4 веса + FP8 активации) стал стандартным путём для максимальной оптимизации. SmoothQuant обеспечивает 8-битное квантование активаций.
«Кэширование префиксов превращает O(N × L) работы в O(N + L)».
Подтверждено. Prefix caching реализован в vLLM (enable_prefix_caching=True) и SGLang (RadixAttention). Для рабочих нагрузок с общими системными промптами или историей диалога это даёт кратное ускорение.
«Отдельные потоки CUDA для передачи и вычислений; GPUDirect RDMA; CUDA Graphs».
Подтверждено. Overlap коммуникаций и вычислений — стандартная практика. GPUDirect RDMA используется для кросс-узловых передач KV-кэша. CUDA Graphs интегрированы в inference-движки. NVIDIA Dynamo использует NIXL для асинхронной передачи KV-кэша с перекрытием.
Шестнадцатая глава книги Fregly — систематическое руководство по профилированию, отладке и настройке инференса LLM в масштабе. Ключевая идея: производительность inference-системы — это многоуровневая задача, охватывающая мониторинг, планирование, управление памятью и оптимизацию на уровне приложений. Для инженера это означает, что понимание методологии профилирования и принципов работы каждого инструмента важнее, чем знание конкретных цифр текущего поколения.
Проверка прогнозов показывает: книга оказалась точной в своих предсказаниях. DCGM + Prometheus + Grafana стали стандартом мониторинга. Continuous batching, chunked prefill, GPTQ/AWQ, prefix caching и overlap коммуникаций с вычислениями — все эти техники реализованы в production-движках (vLLM, SGLang, TensorRT-LLM, NVIDIA Dynamo). Главный вывод остаётся неизменным: инвестиции в методологию профилирования и мониторинга обеспечивают адаптацию к любому стеку.
Источники: Chris Fregly, «AI Systems Performance Engineering» (O'Reilly, 2026), Глава 16 — цитаты приводятся в ограниченном объёме в целях обзора и критического анализа. Документация NVIDIA Nsight Systems, Nsight Compute, DCGM, vLLM, SGLang, TensorRT-LLM; NVIDIA Dynamo Documentation; MLPerf Training/Inference v5.0; Red Hat Developer «Deploying distributed AI inference: Blueprints & troubleshooting» (2026); NVIDIA Technical Blog «Benchmarking LLM Inference at Scale with AIPerf» (2026).
This material is a review of Chapter 16 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 16 of Fregly's book is dedicated to profiling, debugging, and tuning LLM inference at scale. The chapter covers the full cycle: from monitoring and metric collection to specific optimization techniques — dynamic batching, scheduling, quantization, and application-level optimizations. Significant attention is paid to the practical aspects of operating inference clusters: troubleshooting, working with KV cache, memory management, and ensuring quality of service (QoS).
«Operating a large LLM inference cluster requires monitoring and debugging tools that make sure everything is running as expected. They also help you quickly identify bottlenecks when performance strays from its target».
The chapter is structured as a practical guide to operating inference clusters. First, profiling and monitoring tools (Nsight Systems, Nsight Compute, Prometheus, Grafana, DCGM) are examined, followed by troubleshooting methodology and recipes for typical problems. Next, specific optimization techniques are presented: dynamic batching, continuous scheduling, chunked prefill, overlapping communication and computation, memory and KV cache management, quantization for inference, and application-level optimizations. The chapter concludes with QoS, early rejection, and fault tolerance.
The key idea of the chapter: inference system performance is not just the speed of individual kernels but the efficiency of scheduling, memory management, and request handling at every level of the stack. The performance engineer must be able to measure, diagnose, and optimize each of these levels.
LLM inference performance is a multi-level task spanning monitoring, scheduling, memory management, and application-level optimization.
The engineer must be proficient with profiling tools (Nsight, DCGM, PyTorch Profiler) and apply optimization techniques at every level of the stack.
The fundamental methodology for tuning inference performance is an iterative cycle:
Deploying a new inference engine version or quantized model across the entire cluster at once risks turning a 5-minute optimization into an hour-long outage. The incremental approach limits the blast radius and lets you roll back before it affects all users.
Performance tuning is a continuous cycle: observe → hypothesize → fix → verify → repeat. Each fix reveals the next bottleneck.
Changes are made one at a time, with the effect of each measured. Canary rollouts limit risk.
NVIDIA Nsight Systems is a system-level profiler showing the CPU and GPU timeline with microsecond resolution. You see CPU threads, GPU kernels, CUDA events, NCCL communications, memcpy operations — all on a single timeline.
The key technique is NVTX (NVIDIA Tools Extension) annotation. Marking code regions with labels like "Prefill", "Decode", "All-to-all" gives colored blocks on the timeline that immediately show how long each phase takes and where stalls occur.
#include <nvtx3/nvToolsExt.h>
#include "my_model.hpp"
#include <vector>
#define NVTX_PUSH(name, argb) \
do { \
nvtxEventAttributes_t a{}; \
a.version = NVTX_VERSION; \
a.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE; \
a.colorType = NVTX_COLOR_ARGB; \
a.color = (unsigned int)(argb); \
a.messageType = NVTX_MESSAGE_TYPE_ASCII; \
a.message.ascii = (name); \
nvtxRangePushEx(&a); \
} while (0)
#define NVTX_POP() do { nvtxRangePop(); } while (0)
void run_inference(
const std::vector<Token>& prompt_tokens,
Model& model,
int num_generate_steps) {
NVTX_PUSH("Prefill", 0xFF4F86F7);
model.encode(prompt_tokens);
NVTX_POP();
for (int t = 0; t < num_generate_steps; ++t) {
NVTX_PUSH("Decode", 0xFFFF8C00);
Token next_token = model.decode_next();
NVTX_POP();
}
}
For multi-threaded scenarios it's critical to name CUDA streams and wrap each in separate NVTX ranges. Without naming, GPU tracks on the timeline look like a meaningless jumble — with naming, you immediately see whether data transfer and computation overlap.
Nsight Compute profiles individual CUDA kernels. You can focus on specific kernel parts — for example, memory transactions — via section-based profiling.
A lesser-known but extremely useful feature is CUDA Program Counter (PC) Sampling. It samples program counters and identifies hot spots inside kernels with minimal overhead. Unlike full tracing, PC Sampling can run on live production servers without degrading service.
Sampling the program counter to find hot instructions
PyTorch Profiler, based on the Kineto library, provides op-level breakdowns of CPU and CUDA/GPU runtimes. It records tensor shapes, memory snapshots, and supports trace export to Chrome Tracing / Perfetto for collaborative analysis.
with torch.profiler.profile(
activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA],
record_shapes=True,
profile_memory=True,
with_stack=True
) as prof:
with profiler.record_function("train_step"):
torch.cuda.nvtx.range_push("forward")
outputs = model(input_ids, attention_mask=attention_mask, labels=labels)
loss = outputs.loss
torch.cuda.nvtx.range_pop()
torch.cuda.nvtx.range_push("backward")
loss.backward()
torch.cuda.nvtx.range_push("optimizer_step")
optimizer.step()
torch.cuda.nvtx.range_pop()
optimizer.zero_grad()
torch.cuda.nvtx.range_pop()
print(prof.key_averages().table(
sort_by="self_cuda_time_total",
row_limit=10,
fields=["self_cuda_time_total", "calls"]
))
Profiling is a two-stage process: Nsight Systems for the big picture and finding hot kernels, Nsight Compute for detailed analysis. NVTX annotations make the timeline readable.
PyTorch Profiler (based on Kineto) provides op-level breakdown and supports export to Chrome Tracing / Perfetto. PC Sampling in Nsight Compute allows localizing hot instructions with minimal overhead.
In production, continuous monitoring is more important than ad-hoc profiling. The Prometheus + Grafana + DCGM stack is the de facto standard for GPU clusters.
Metric flow from GPU nodes to dashboards
| Metric | DCGM counter | Meaning |
|---|---|---|
| SM utilization | DCGM_FI_DEV_GPU_UTIL | Percentage of time SMs are busy |
| Copy engine load | DCGM_FI_DEV_MEM_COPY_UTIL | Memory copy engine activity |
| Memory usage | DCGM_FI_DEV_FB_USED | Framebuffer memory occupied |
| Temperature | DCGM_FI_DEV_GPU_TEMP | GPU temperature |
| Power draw | DCGM_FI_DEV_POWER_USAGE | Power in watts |
| ECC errors | DCGM_FI_DEV_ECC_* | Correctable and uncorrectable errors |
| NVLink errors | DCGM_FI_DEV_NVLINK_* | Replays, CRC, link recovery |
vllm:gpu_prefix_cache_queries and vllm:gpu_prefix_cache_hits in vLLM.| Metric | Condition | Severity | Notes |
|---|---|---|---|
| GPU utilization | < 10% for 60 s | Idle | Underutilization |
| GPU utilization | > 90% | Bottleneck | Possible saturation |
| Memory usage | > 80% | Warning | Approaching OOM |
| Memory usage | > 95% | Critical | High OOM risk |
| Temperature | > 85 °C | Warning | Approaching throttling |
| Temperature | > 95 °C | Critical | Damage risk |
| NVLink errors (replay) | ≥ 1 | Critical | Link problem |
| NVLink CRC errors | > 100/s | Critical | Link degradation |
| Uncorrectable ECC errors | ≥ 1 | Critical | Data corruption |
The numerical values are indicative. Actual thresholds depend on your GPU architecture, cooling conditions, and SLO. Set them based on baseline measurements.
NCCL_COMM_FAILURE in logs.Example vLLM log indicating KV-cache preemption:
WARNING 2025-05-03 14:22:07 scheduler.py:1057 Sequence group 0 is preempted by
PreemptionMode.RECOMPUTE because not enough KV cache space.
total_cumulative_preemption_cnt=1
This means the engine ran out of memory for the KV cache and evicted an active sequence. Result: KV recomputation on rescheduling, extra compute, and latency growth. If such messages appear regularly: raise the GPU memory threshold, reduce max batched tokens, enable PagedAttention, or consider KV-cache quantization.
Continuous monitoring through Prometheus + Grafana + DCGM is the de facto standard for GPU clusters. Key metrics: SM utilization, memory usage, latency percentiles, cache hit rate.
Metric correlation (RPS + p99, SM + copy engine, NCCL errors + GPU utilization) allows rapid localization of the root cause.
| Symptom | Likely cause | Recommended action |
|---|---|---|
| SM utilization < 50% | Small batches or missing fused kernels | Increase batch size, enable FlashAttention, add fused kernels, profile via nsys --trace=cuda |
| KV-cache preemption warnings | Insufficient KV-cache space | Raise GPU memory threshold, reduce max batch tokens, enable PagedAttention |
| High tail latency (p95 > 200 ms) | Decode hot spot or head-of-line blocking | Check router logs, tune prefetch threshold, enable speculative decoding |
| Cache hit rate < 60% | Unbalanced sharding or missing prefix cache | Check prefix cache configuration (LMCache, NIXL), increase TTL, add replicas |
| Unexpected OOM | GPU memory overload | Reduce per-instance memory, enable CPU/NVMe offload, pin processes to sockets |
| Irregular spikes | Thermal throttling or inconsistent clocks | Synchronize clocks, monitor temperature, lock clock via nvidia-smi -lgc |
compute-sanitizer --tool memcheck your_binary to detect memory errors, data races, and out-of-bounds.NCCL_DEBUG=WARN for detailed logs. Use ncclCommGetAsyncError with ncclCommAbort to detect and handle async errors.Inference troubleshooting is a systematic process: from symptom to likely cause and concrete action. The recipes table covers typical scenarios.
For correctness debugging, use compute-sanitizer, NCCL_DEBUG, and monitoring of hardware error counters.
High-performance inference requires coordinated optimizations at every level of the stack. A problem at only one level is luck. In reality, bottlenecks migrate between levels as they are removed.
| Stack level | Key techniques |
|---|---|
| Model | Pruning, distillation, sparsity (MoE), FlashAttention, quantization-aware training (QAT) |
| Kernel | Fused ops (Linear + GELU + LayerNorm), FlashInfer, Tensor Cores, block tiling, async transfers (cp.async, TMA) |
| Runtime | Dynamic/continuous batching, PagedAttention, CUDA Graphs, buffer pooling, multi-stream CUDA, event-based sync |
| Orchestration | Prefill/decode separation, intelligent routing, multi-tenancy isolation, autoscaling with warm reserves |
| Deployment | Geo-distributed edge serving, smart API gateways with batching, CI/CD for model variants, NVLink/NVSwitch, InfiniBand, NUMA affinity |
| QoS and scaling | SLA-aware dynamic batching, MIG isolation, real-time profiling dashboards, dynamic parallelism switching (TP, PP, DP) |
The key idea is cross-level synergies. Quantization (model) reduces memory consumption, allowing larger batch sizes (runtime) without OOM, which in turn lets orchestration pack more requests per GPU cycle. One optimization at a lower level can unlock several at higher levels.
Full-stack optimizations are a necessary condition for high-performance inference. Bottlenecks migrate between levels as they are removed.
Keep the software stack up to date. New versions of CUDA, cuDNN, NCCL, Transformer Engine contain optimizations unavailable in older versions.
Static batching fixes the batch size, pads all sequences to the longest one, and waits for each request to complete before returning. Result: unbounded latency for early arrivals and wasted GPU cycles on padding.
Dynamic batching assembles batches on the fly. The system accumulates incoming requests within a short timeout (typically 2–10 ms) or until a target batch size is reached, then sends the batch to the GPU.
Accumulating requests vs starting immediately with what arrived
| Aspect | Static | Dynamic | Continuous |
|---|---|---|---|
| Trigger | Fixed size | Size target or timeout | Token completion event |
| Latency bound | Unbounded | Bounded by max_batch_delay_ms | Minimal |
| Padding | High | Moderate | Low |
| GPU idle time | Poor | Better | Excellent |
| Complexity | Simple | Moderate | Complex |
Continuous batching (batching in-flight, iteration-level scheduling) is the next step. Instead of waiting for full sequences to complete, the system refills the batch at every token generation iteration. Finished requests are evicted, new ones immediately take their slots.
Finished sequences leave, new ones slide in mid-generation
Continuous scheduling treats the GPU like an OS scheduler treats the CPU. If the model is small or the batch size is SLO-limited, a single model copy may not saturate the GPU. Then the engine launches multiple inference streams simultaneously on one GPU.
PagedAttention in vLLM is a concrete example. The KV cache is split into pages, and computation is dynamically grouped by page between active sequences. Under heavy load this yields nearly 100% GPU utilization.
When prompts are very long (e.g., 20,000 tokens), you can split them into chunks and interleave prefill and decode work. This is called chunked prefill, or stall-free scheduling.
| Chunk size | Chunk count | Attention ops per chunk | Total MLP tokens |
|---|---|---|---|
| 20K | 1 | 200M | 20K |
| 10K | 2 | 50M + 150M = 200M | 20K |
| 5K | 4 | 12.5M + 37.5M + 62.5M + 87.5M = 200M | 20K |
Key insight: chunking does not reduce the total number of attention operations. Self-attention performs N(N+1) ÷ 2 Q × K dot products per layer per head — cost is quadratic in N, O(N²). Chunking only changes when work becomes available to the decoder. The benefit is latency smoothing and better overlap, not reduced compute.
A naive FIFO scheduler can overload one GPU if arrival order is suboptimal. Consider six prompts with lengths 6K, 2K, 6K, 2K, 2K, 2K and two GPUs.
Continuous batching and chunked prefill are key techniques for maximizing throughput while maintaining low latency. Latency-aware scheduling reduces the critical path by 42% in the six-prompt example.
Chunking does not reduce the total number of attention operations — it only smooths latency and improves overlap.
In distributed inference, overlapping communication with computation is a critical performance factor. Systems like GB200/GB300 NVL72 deliver up to ~130 TB/s aggregate NVLink bandwidth within a rack, but even at such speeds synchronous communication creates bubbles.
A baseline technique is separate CUDA streams for transfer and compute:
cudaStream_t transfer_stream, compute_stream;
cudaStreamCreate(&transfer_stream);
cudaStreamCreate(&compute_stream);
// Transfer on transfer_stream
cudaMemcpyAsync(h_logits, d_logits, bytes,
cudaMemcpyDeviceToHost, transfer_stream);
// Compute on compute_stream — overlaps with transfer
my_kernel<<<grid, block, 0, compute_stream>>>(...);
// Sync only when data is needed
cudaEventSynchronize(transfer_done_event);
Always use page-locked (pinned) host buffers for PCIe or NIC transfers — the CUDA driver can DMA directly and overlap with computation.
For MoE models, all-to-all can be overlapped by splitting the token batch in half: while the first half is processed by experts, the second is being sent. By the time the first half completes, the second half has arrived at receiving GPUs.
GPUDirect RDMA lets network adapters (InfiniBand NICs) read and write GPU memory directly, bypassing host memory. This reduces cross-node KV-cache or expert activation transfer latency and frees CPU cores.
CUDA Graphs capture asynchronous patterns and reduce kernel launch overhead — especially useful for repetitive decoding patterns.
Continuous 100% GPU operation will cause thermal throttling if cooling is insufficient. Sometimes running at 90% with efficient kernels beats 100% with throttling.
nvidia-smi -lgc — slightly reduces throughput but ensures stability.nvidia-smi -pl (if cooling is adequate).Paged KV cache (PagedAttention in vLLM) splits the KV cache into pages and dynamically allocates them between sequences. This eliminates the memory fragmentation inherent in fixed-allocation approaches.
KV-cache offload (swap) to CPU memory or NVMe is an option for rarely used data. LMCache in vLLM lets you tune the GPU/CPU cache ratio. RadixAttention in SGLang lazily evicts least-recently-used prefixes.
However, offload is not free: at high swap frequency, copy engine load rises while SM utilization drops. If you see a copy engine spike with a simultaneous SM drop — the system is swapping. Solutions: apply FP8/FP4 quantization to shrink KV size, increase GPU memory allocated to the cache, change the swap strategy.
Overlapping communication and computation is a critical factor for distributed inference performance. GPUDirect RDMA and CUDA Graphs help hide transfer latencies.
Memory management via PagedAttention, LMCache, and RadixAttention eliminates fragmentation and enables serving more concurrent requests.
| Format | Bits per element | Speedup vs FP32 | Memory footprint vs FP32 | Notes |
|---|---|---|---|---|
| FP32 | 32 | 1× | 1× | Baseline precision |
| TF32 | 19 (10-bit mantissa) | ~1.5× | 1× | Tensor Cores only |
| FP16/BF16 | 16 | 2× | 0.5× | Inference standard |
| FP8 (E4M3/E5M2) | 8 | 4× | 0.25× | Requires calibration |
| INT4 | 4 | 8× (theoretical) | 0.125× | Weight-only quantization |
| FP4 (NVFP4) | 4 + block scales | ~8× | ~0.18× (with metadata) | Requires micro-scaling |
Range analysis, scale selection, conversion to FP8/FP4
Weight-only quantization compresses weights to 4-bit integers while keeping activations at higher precision (FP8, FP16). This reduces the weight memory footprint roughly 4× compared to FP16.
GPTQ applies an approximate second-order algorithm for layer-wise weight quantization to 3–4 bits in a few hours on GPU. For many models, 4-bit GPTQ retains 99%+ of FP16 accuracy with ~2× inference speedup.
AWQ (Activation-aware Weight Quantization) identifies a small fraction of "salient" weight channels that produce large activation magnitudes. AWQ applies per-channel scaling before quantizing weights to 4-bit precision.
Activation quantization is harder because distributions vary widely across inputs. SmoothQuant is a PTQ method for 8-bit activation quantization without training. It shifts part of the quantization error from activations to weights via simple row/column scaling.
The hybrid W4A8 approach combines 4-bit weights (INT4) with 8-bit activations (FP8 or INT8). TensorRT-LLM and other engines provide this path with nearly no accuracy loss given proper calibration.
Quantization is one of the most effective ways to reduce inference cost. GPTQ and AWQ for 4-bit weights, SmoothQuant for 8-bit activations, W4A8 for maximum optimization.
Always validate accuracy on downstream tasks and perform A/B testing. 4-bit weight quantization retains 99%+ accuracy for many models.
Transformer attention has time complexity O(n²), where n is input size in tokens. Reducing a prompt from 10,000 to 5,000 tokens cuts self-attention work by 4×.
Prefix caching (prefix memoization) is one of the most effective optimizations. If several requests share a common prefix (system prompt, document, dialogue history), the KV cache for the prefix is computed once and reused.
Without caching: N requests of length L require O(N × L) work. With caching: O(N + L) — the prefix is processed once, each request only adds its unique suffix.
Each node is a token, green highlighting shows shared prefix reuse
enable_prefix_caching=True. The engine checks whether the first N tokens of an incoming prompt match an already cached prefix, and if so, copies KV cache data instead of recomputing.New nodes, active nodes, LRU eviction
Not every request requires the largest model. Cascading routes simple requests to a smaller, faster model and complex ones to the large model.
Routing 60% of requests to a model 10× smaller can cut compute costs by ~5×.
The model generates tokens one at a time (except for speculative decoding like EAGLE and multi-head decoding like Medusa). The system groups tokens into batches of 2–5, flushes the stream, and sends via SSE/WebSockets/HTTP Streaming.
Humans read at 4–13 tokens per second. Without streaming, the user stares at a blank screen for 5 seconds, then receives the whole answer at once. With streaming, the first batch of tokens arrives in 0.25 seconds — and the user starts reading immediately.
Technical details: TCP_NODELAY to minimize latency; thread-safe queues for passing tokens to the network thread; flow control; HTTP/2 and persistent connections.
Short pause after a burst of clicks before sending a request
Application-level optimizations — prompt compression, prefix caching, model cascading, streaming output — deliver significant gains without changing the model or hardware.
Prefix caching turns O(N × L) work into O(N + L). Prompt compression reduces self-attention work quadratically.
Fregly's book was written in 2025, when the inference stack was rapidly evolving. Below is a comparison of Chapter 16's forecasts with open data.
«DCGM collects metrics from Kubernetes GPU nodes, Prometheus aggregates them, Grafana visualizes».
Confirmed. DCGM Exporter became the de facto standard for GPU observability in Kubernetes. For vLLM workloads, DCGM metrics integrate with Prometheus recording rules for cost calculation. AIPerf and other tools include DCGM/pynvml metrics in benchmark outputs.
«Continuous batching: finished sequences leave the batch, new ones slide in mid-generation».
Confirmed. Continuous batching is implemented in vLLM, SGLang, TensorRT-LLM and has become the standard for production inference. PagedAttention in vLLM and RadixAttention in SGLang provide dynamic KV-cache management.
«Chunked prefill: split long prompts into chunks and interleave prefill and decode work».
Confirmed. Chunked prefill is implemented in vLLM as stall-free scheduling. Recommended parameters: --enable-chunked-prefill --max-num-batched-tokens 2048. This prevents short requests from being blocked by long prefills.
«GPTQ and AWQ for 4-bit weights retain 99%+ of FP16 accuracy with ~2× speedup».
Confirmed. GPTQ and AWQ are integrated into Hugging Face Transformers, vLLM, TensorRT-LLM. W4A8 (INT4 weights + FP8 activations) has become the standard path for maximum optimization. SmoothQuant provides 8-bit activation quantization.
«Prefix caching turns O(N × L) work into O(N + L)».
Confirmed. Prefix caching is implemented in vLLM (enable_prefix_caching=True) and SGLang (RadixAttention). For workloads with shared system prompts or dialogue history, it provides multiplicative speedup.
«Separate CUDA streams for transfer and compute; GPUDirect RDMA; CUDA Graphs».
Confirmed. Overlap of communication and computation is standard practice. GPUDirect RDMA is used for cross-node KV-cache transfers. CUDA Graphs are integrated into inference engines. NVIDIA Dynamo uses NIXL for asynchronous KV-cache transfer with overlap.
Chapter 16 of Fregly's book is a systematic guide to profiling, debugging, and tuning LLM inference at scale. The key idea: inference system performance is a multi-level task spanning monitoring, scheduling, memory management, and application-level optimization. For an engineer, this means that understanding profiling methodology and the principles behind each tool is more important than knowing specific numbers of the current generation.
Forecast verification shows: the book proved accurate in its predictions. DCGM + Prometheus + Grafana became the monitoring standard. Continuous batching, chunked prefill, GPTQ/AWQ, prefix caching, and overlap of communication with computation — all these techniques are implemented in production engines (vLLM, SGLang, TensorRT-LLM, NVIDIA Dynamo). The main takeaway remains unchanged: investments in profiling and monitoring methodology ensure adaptation to any stack.
Sources: Chris Fregly, «AI Systems Performance Engineering» (O'Reilly, 2026), Chapter 16 — quotes provided in limited volume for review and critical analysis purposes. NVIDIA Nsight Systems, Nsight Compute, DCGM, vLLM, SGLang, TensorRT-LLM documentation; NVIDIA Dynamo Documentation; MLPerf Training/Inference v5.0; Red Hat Developer «Deploying distributed AI inference: Blueprints & troubleshooting» (2026); NVIDIA Technical Blog «Benchmarking LLM Inference at Scale with AIPerf» (2026).