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

Кормим 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 получать данные с достаточной скоростью. В главе последовательно рассматривается выбор накопителей, шаблоны доступа, тюнинг NVMe и файловых систем, технология GPUDirect Storage, Fire-Flyer File System от DeepSeek, распределённые файловые системы, конвейер DataLoader, инструменты DALI и NeMo Curator, а также методика непрерывного профилирования и разбор, что ограничивает — сеть или вычисления. Ниже последовательно изложены ключевые положения главы с уточнениями по актуальным данным.

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

«Подача данных на GPU так же важна для AI-нагрузок, как и сами вычисления. Рассмотрим сценарий с моделью на 100 триллионов параметров, обучаемой на тысячах GPU. Такая модель может обрабатывать миллиарды обучающих образцов, включая токены, изображения, аудио и видео. Это означает, что огромный объём данных должен считываться из хранилища и подаваться на GPU как можно быстрее. Если конвейер хранения медленный, GPU будут голодать и простаивать. Это приведёт к низкой утилизации, несмотря на все сложные коммуникационные оптимизации, которые мы обсуждали».

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

В главе подчёркивается, что подсистема хранения — это не «инфраструктурная деталь», а полноценный участник конвейера производительности. Пока данные не поступили на GPU, вычисления не начнутся. Чем мощнее ускоритель, тем острее становится этот разрыв: современные GPU способны обрабатывать данные быстрее, чем большинство хранилищ могут их подавать.

Практическое следствие, отмечаемое в главе: узкое место почти всегда смещается в сторону подсистемы хранения по мере роста вычислительной мощности GPU. Инженер, который смотрит только на FLOPS и загрузку SM, рискует пропустить главный источник простоя — ожидание данных.

Отдельно в главе указывается расчёт: для 72 GPU Blackwell NVL72, каждому из которых требуется 200 МБ/с обучающих данных, совокупная пропускная способность хранилища должна составлять 14–20 ГБ/с только для поддержания загрузки. Это нижняя граница; мультимодальные нагрузки требуют больше.

• • •

IБыстрое хранилище и локальность данных

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

«Крупные задачи обучения моделей обычно требуют чтения огромных наборов данных. Обычно это порядка миллиардов или даже триллионов обучающих образцов для больших языковых моделей. Это диапазон терабайт текстовых данных для языковых моделей и петабайт изображений для визуальных моделей. В масштабе ваша система хранения должна стабильно обеспечивать массивную пропускную способность, чтобы успевать за тысячами и миллионами GPU, работающими месяцами».

«Размещение NVMe SSD внутри стоек — или использование NVMe over Fabrics (NVMe-oF) с топологиями коммутаторов на уровне стойки — минимизирует сетевые переходы и повышает стабильность производительности».

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

В главе формулируется иерархия локальности данных: локальный NVMe на том же узле → NVMe-oF в пределах стойки → сетевое хранилище (NFS, Lustre, GPFS) → объектное хранилище (S3). Каждый переход на уровень ниже добавляет задержку и снижает пропускную способность.

Практическое следствие: для распределённого обучения рекомендуется шардировать набор данных по узлам. Если у вас 100 ТБ данных и 10 узлов, вы можете предварительно разбить их на 10 частей по 10 ТБ и разместить на локальном хранилище каждого узла. Тогда загрузчик данных каждого узла читает только свой 10-ТБ шард, и сетевой трафик минимизируется. PyTorch DistributedSampler координирует процесс так, чтобы каждый ранг получал уникальный срез в каждой эпохе.

Отдельно отмечается необходимость масштабировать пропускную способность хранилища пропорционально числу GPU. Если каждый GPU требует 200 МБ/с, то на 72 GPU нужно 14 ГБ/с, на 720 GPU — 140 ГБ/с. Это определяет требования к архитектуре хранилища.

Итоги раздела I
Ключевое положение главы

Данные должны располагаться как можно ближе к вычислениям. Иерархия: локальный NVMe → NVMe-oF в стойке → сетевое хранилище → объектное хранилище. Шардирование набора данных по узлам минимизирует сетевой трафик.

Приводимые в главе цифры

72 GPU × 200 МБ/с = 14,4 ГБ/с минимальной совокупной пропускной способности. Для мультимодальных нагрузок — в разы больше. Границы масштабирования: до 10 узлов — один NFS-сервер может справиться, свыше — параллельные ФС или объектные хранилища с кэшированием.

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

Локальный NVMe даёт минимальную задержку. NVMe-oF в стойке — компромисс между локальностью и гибкостью. Сетевое хранилище требует тщательного тюнинга (размеры блоков, кэширование, число серверов).

• • •

IIПоследовательные и случайные чтения

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

«GPU чрезвычайно быстро обрабатывают данные, но предпочитают, чтобы данные читались крупными непрерывными блоками. Аналогично, хранилище обеспечивает гораздо более высокую пропускную способность при крупных последовательных чтениях, чем при мелких случайных. Поэтому при подготовке наборов данных или схемы хранения старайтесь организовывать последовательный доступ насколько это возможно».

«Например, при обучении на изображениях избегайте хранения миллионов отдельных файлов изображений, так как это приведёт к множеству случайных обращений по всему диску. Рассмотрите вместо этого хранение их в нескольких крупных бинарных файлах (например, Arrow, TFRecord, Parquet), файлах базы данных, tar-архивах WebDataset или эквивалентах».

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

В главе последовательный доступ описывается как фундаментальное требование. NVMe SSD при последовательном чтении выдаёт 6–7 ГБ/с; при случайном — в 3–10 раз меньше. Для GPU разница ещё более критична, поскольку время ожидания данных напрямую влияет на утилизацию.

Практическое следствие: упаковка мелких образцов в крупные бинарные файлы — не «оптимизация», а базовое требование для эффективного I/O. WebDataset, TFRecord, Arrow, Parquet и .bin-форматы решают эту задачу. При работе с объектными хранилищами (S3) объединение мелких объектов в крупные сокращает количество GET-запросов на порядки.

Отдельно в главе указывается на важность размера блока чтения. Чтение по 1 МБ даёт пропускную способность на порядок выше, чем по 4 КБ, за счёт амортизации накладных расходов на системный вызов и инициализацию DMA. Рекомендуется настраивать read_ahead_kb в /sys/block/<device>/queue/ — например, до 4 МБ для потокового чтения крупных файлов.

Рисунок 5-3. Последовательный, страйдовый и случайный доступ к памяти

NVMe SSD при последовательном чтении выдаёт 6–7 ГБ/с, при случайном — в 3–10 раз меньше

ТРИ ШАБЛОНА ДОСТУПА Последовательный 1 непрерывный блок · 6-7 ГБ/с Страйдовый 6 блоков · ~2 ГБ/с Случайный 7 мелких блоков · ~0.5-1 ГБ/с
Описание: Последовательный доступ (сверху) даёт максимальную пропускную способность NVMe. Страйдовый (в середине) — промежуточный вариант, при котором данные разбросаны по крупным блокам. Случайный (снизу) — худший вариант для NVMe, поскольку каждый запрос требует отдельной операции поиска дорожки. Упаковка мелких образцов в крупные файлы переводит нагрузку из случайного режима в последовательный.
Итоги раздела II
Ключевое положение главы

Последовательный доступ — фундаментальное требование. Случайные чтения снижают пропускную способность NVMe в 3–10 раз. Упаковка мелких образцов в крупные бинарные файлы (WebDataset, TFRecord, Arrow, Parquet) переводит нагрузку в последовательный режим.

Приводимые в главе цифры

Чтение блоками по 1 МБ даёт пропускную способность на порядок выше, чем по 4 КБ. NVMe SSD: 6–7 ГБ/с последовательно, в разы меньше при случайном доступе. Для объектных хранилищ: объединение мелких объектов в крупные сокращает количество GET-запросов на порядки.

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

Настраивайте read_ahead_kb для потокового чтения (например, до 4 МБ). Для случайного доступа используйте параллельные потоки с pread() или асинхронный io_uring.

• • •

IIIТюнинг NVMe и файловой системы для пропускной способности

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

«Современный Linux использует многопоточный планировщик блочного I/O blk-mq, который распределяет I/O по ядрам CPU. Для быстрых NVMe SSD вам может потребоваться настроить глубину очереди и количество очередей отправки. Обычно значения по умолчанию подходят, но если вы знаете, что ваша нагрузка сильно последовательна, вы можете использовать планировщик none».

«Устаревший планировщик completely fair queueing (CFQ) устарел. Современные ядра используют none или mq-deadline по умолчанию для NVMe. Эту настройку можно проверить через /sys/block/<device>/queue/scheduler».

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

В главе описываются три варианта планировщика для NVMe: none (минимальные накладные расходы, для низколатентных нагрузок), mq-deadline (компромисс с fairness), BFQ (для интерактивных задач). Рекомендация для AI-нагрузок — none или mq-deadline.

Практическое следствие: проверка и установка планировщика выполняются через /sys/block/nvme0n1/queue/scheduler. Для большинства AI-нагрузок значение none даёт минимальные накладные расходы.

Отдельно в главе рассматриваются опции монтирования. Для XFS и EXT4 рекомендуется noatime, чтобы отключить обновление времени доступа при каждом чтении. Для NFS — увеличенные размеры блоков (rsize=1048576, wsize=1048576), кэширование атрибутов (actimeo=60) и кэширование записей каталогов (lookupcache=pos).

Также отмечается, что кэш страниц Linux (page cache) может быть как другом, так и врагом. Если набор данных помещается в ОЗУ — это бесплатное ускорение. Если нет — кэш начинает «трэшиться», и CPU тратит время на управление кэшем вместо полезной работы. Для наборов данных, которые заведомо не помещаются в ОЗУ, рекомендуется использовать O_DIRECT для обхода кэша страниц.

ПланировщикКогда использоватьНакладные расходы
noneНизколатентные NVMe-нагрузки, крупные последовательные чтенияМинимальные
mq-deadlineСмешанные нагрузки, где важен fairnessНизкие
BFQДесктопы, интерактивные задачиСредние
Осторожно

NFS-сервер — частый кандидат в узкое место. Один сервер с одним NIC на 25 Гбит/с насытится уже при 8–10 GPU. Для кластеров побольше используйте несколько NFS-серверов с разделением данных по партициям или переходите на параллельную файловую систему.

Итоги раздела III
Ключевое положение главы

Для NVMe рекомендуется планировщик none или mq-deadline. Устаревший CFQ не используется. Опции монтирования noatime и увеличенные блоки NFS снижают накладные расходы.

Приводимые в главе цифры

NVMe: read_ahead_kb по умолчанию 128 КБ; для потокового чтения рекомендуется 2–4 МБ. NFS: rsize/wsize до 1 МБ, actimeo=60, lookupcache=pos.

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

Проверяйте текущий планировщик через /sys/block/nvme0n1/queue/scheduler. Для данных, не помещающихся в ОЗУ, используйте O_DIRECT с выравниванием буфера и смещения по размеру блока устройства.

• • •

IVNVIDIA GDS — прямой путь диск → GPU

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

«GDS — это технология, позволяющая GPU читать данные напрямую с устройств хранения, или через сетевой стек хранения, без создания дополнительных копий в памяти CPU. Обычно, когда GPU хочет прочитать данные с NVMe SSD, данные сначала идут с SSD в память CPU. Затем вызов CUDA копирует данные из памяти CPU в память GPU».

«С GDS GPU может инициировать прямой доступ к памяти (DMA) к SSD или NIC, чтобы переместить данные в собственную память HBM. Это обходит дополнительную копию через путь CPU. GDS поддерживает локальные NVMe-устройства и удалённое хранилище с использованием NVMe-oF».

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

В главе GDS описывается как технология, устраняющая промежуточное звено — буфер в памяти хоста (bounce buffer). Обычный путь данных: NVMe → память CPU → CUDA-копия → память GPU. С GDS: NVMe → память GPU напрямую. CPU по-прежнему управляет (настраивает дескрипторы, инициализирует передачу), но не участвует в копировании.

Практическое следствие: GDS максимально эффективен, когда CPU перегружен копированиями (множество memcpy на высокой скорости). Если CPU справляется легко, прирост будет скромным — но GDS всё равно освободит циклы процессора для предобработки данных.

В главе тезис о 10–20% прироста пропускной способности приводится как консервативная нижняя оценка. Опубликованные бенчмарки демонстрируют более широкий разброс: VAST Data сообщает о 162 ГиБ/с на DGX A100 при прямом пути против ~33 ГБ/с через традиционный, Meta — о 3,8-кратном ускорении обучения за счёт GDS, в тестах OCI на gdsio — до 2,7–3,5× при крупных блоках. Фактический выигрыш зависит от загрузки CPU: чем сильнее CPU перегружен копированиями, тем выше эффект от GDS.

Отдельно указываются требования: современный GPU NVIDIA, драйвер с поддержкой nvidia-fs, CUDA Toolkit и совместимая файловая система. Поддерживаются локальные NVMe и NVMe-oF на XFS/EXT4 с O_DIRECT, NFS over RDMA, параллельные ФС (BeeGFS, WekaFS, IBM Storage Scale, VAST).

Приложение использует библиотеку cuFile с функциями cuFileRead, cuFileWrite и асинхронными вариантами cuFileReadAsync, cuFileWriteAsync для интеграции с CUDA-стримами.

Рисунок 5-1. Сетевая архитектура VAST Data: с GDS и без GDS

Сравнение путей передачи данных от хранилища к GPU: традиционный DMA через host-память (bounce buffer) и прямой GPU pull с GPUDirect Storage

БЕЗ GDS (традиционный путь) Данные проходят через память хоста Memory CPU PCIe Switch NFS / RDMA (источник данных) GPU HBM bounce buffer копия через host передача на GPU С GDS (прямой GPU pull) Данные минуют память хоста Memory CPU (только управление) PCIe Switch NFS / RDMA (источник данных) GPU HBM GPU Direct Storage прямой DMA в HBM Дополнительное копирование ↑ задержка, ↓ пропускная способность Прямая передача данных ↓ задержка, ↑ пропускная способность
GPU Direct Storage Bounce buffer (host memory) PCIe / управление
Описание: Слева — традиционный путь: данные из NFS/RDMA попадают в память хоста, затем копируются на GPU через PCIe. Справа — GDS: GPU инициирует прямой DMA-передачи с NIC в HBM, минуя host RAM.
Цитата из книги · Глава 5

«NVIDIA поставляет инструмент gdsio для измерения пропускной способности GDS между диском и GPU. Это чрезвычайно полезно. При использовании GDS нередко можно увидеть улучшения порядка 10–20% по пропускной способности или более — особенно в сценариях с ограниченным CPU».

Рисунок 5-4. Throughput и latency до и после GDS

Пример бенчмарка gdsio: путь через CPU vs прямой GDS

0 3 6 9 12 ГБ/с 8.0 Storage → CPU (without GDS) 9.6 (+20%) Storage → GPU (with GDS) 1.25 мс CPU latency (without GDS)
Описание: Пример бенчмарка gdsio: путь через CPU даёт 8,0 ГБ/с и 1,25 мс задержки; с GDS — 9,6 ГБ/с (+20%) и 1,00 мс (−20%). Такой прирост типичен для систем, где CPU был перегружен копированиями.
Когда GDS даёт наибольший прирост

GDS максимально эффективен, когда CPU уже перегружен копированиями (множество memcpy на высокой скорости). Если CPU справляется легко, прирост будет скромным — но GDS всё равно освободит циклы процессора для предобработки данных.

Итоги раздела IV
Ключевое положение главы

GDS устраняет промежуточное звено — буфер в памяти хоста. GPU инициирует прямой DMA с NVMe или NIC в HBM. CPU управляет, но не копирует.

Приводимые в главе цифры

gdsio для измерения: 8,0 ГБ/с и 1,25 мс без GDS; 9,6 ГБ/с и 1,00 мс с GDS. Тезис «10–20%» — консервативная нижняя оценка; опубликованные бенчмарки показывают разброс от 20% до 3,8× в зависимости от нагрузки CPU. Требования: Ampere или новее, драйвер с nvidia-fs, совместимая ФС.

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

Используйте библиотеку cuFile для прямого чтения. Асинхронные варианты cuFileReadAsync/cuFileWriteAsync позволяют интегрировать дисковый I/O в CUDA-стримы для перекрытия с вычислениями.

• • •

VFire-Flyer File System (3FS) от DeepSeek

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

«DeepSeek создала собственную файловую систему Fire-Flyer File System (3FS) с нуля. Она родилась из наблюдения, что AI-нагрузки выполняют огромное количество случайных чтений. Эти случайные чтения делают традиционное кэширование данных неэффективным — и даже контрпродуктивным — для LLM-обучения и инференса. Устраняя кэширование и используя прямой файловый I/O, 3FS гарантирует, что каждый запрос идёт прямо к NVMe SSD и избегает бесполезного управления кэшем».

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

В главе 3FS описывается как пример файловой системы, спроектированной специально под AI-нагрузки. Ключевые решения: прямой I/O без кэша страниц, RDMA-фабрика (InfiniBand или RoCE), шардирование и репликация метаданных по узлам для масштабируемости.

Практическое следствие: 3FS достигает пропускной способности в несколько терабайт в секунду за счёт координации I/O между узлами. Официальный README DeepSeek сообщает о 6,6 ТиБ/с (≈ 7,3 ТБ/с в десятичных байтах) на кластере из 180 storage-узлов, каждый с 2×200 Гбит/с InfiniBand и 16 × 14 ТиБ NVMe, плюс 500+ клиентских узлов. Эта цифра достигнута с фоновым трафиком обучения. Конфигурация кластера в книге (68 узлов, 10 × 16 ТБ NVMe, два NIC по 100 Гбит/с) отличается от официальной; при такой конфигурации физический потолок пропускной способности составлял бы около 1,7 ТБ/с, что не позволяет достичь 6,6 ТиБ/с. Дополнительно в официальных материалах DeepSeek указаны результаты GraySort (110,5 ТиБ за 30 минут 14 секунд, то есть 3,66 ТиБ/мин) и до 40 ГиБ/с на клиент в KVCache. Сравнение с Ceph (~1,1 ТБ/с) приводится в книге как авторская оценка, а не как официальное заявление DeepSeek.

Рисунок 5-2. Компоненты Fire-Flyer File System (3FS) DeepSeek

Четыре ключевых компонента 3FS соединены через RDMA-фабрику (InfiniBand или RoCE) для минимизации участия CPU и копирования на стороне хоста

RDMA Fabric InfiniBand / RoCE (нулевое копирование, обход CPU) Cluster Manager управление кластером Metadata Service inode, директории, метаданные шардирование + репликация Storage Service блоки данных на NVMe обход page cache (O_DIRECT) Clients приложения / training / inference 3FS: RDMA-first, обход page cache, шардирование метаданных для масштабирования
RDMA-фабрика Сервисы данных Управление Клиенты
Описание: 3FS разбита на четыре роли: менеджер кластера управляет составом узлов, сервис метаданных шардирует inode-таблицы, сервис хранения работает с NVMe напрямую через O_DIRECT, клиент живёт в приложении. Все связи идут через RDMA-фабрику, обходя CPU на стороне хоста.
Ограничение

Если файловая система реализована через FUSE в пространстве пользователя, она не может обеспечить путь GDS. Для прямого DMA в память GPU нужен клиент ядра, интегрированный с nvidia-fs: NVMe, NVMe-oF, BeeGFS, WekaFS, IBM Storage Scale или VAST.

Итоги раздела V
Ключевое положение главы

3FS — пример файловой системы, спроектированной под AI-нагрузки. Прямой I/O без кэша страниц, RDMA-фабрика, шардирование метаданных. Заявленная пропускная способность: 6,6 ТиБ/с.

Приводимые в главе цифры

6,6 ТиБ/с (подтверждено официальным README DeepSeek). Конфигурация кластера в книге (68 узлов, 10 × 16 ТБ NVMe, два NIC по 100 Гбит/с) отличается от официальной (180 storage-узлов, 2×200 Гбит/с IB, 16 × 14 ТиБ NVMe). Сравнение с Ceph (~1,1 ТБ/с) — авторская оценка книги. Дополнительно DeepSeek: GraySort 110,5 ТиБ за 30:14, до 40 ГиБ/с на клиент в KVCache.

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

FUSE не даёт GDS. Для прямого DMA в HBM нужен kernel-клиент с nvidia-fs. Если вам нужен GDS — выбирайте NVMe, NVMe-oF, BeeGFS, WekaFS, IBM Storage Scale или VAST.

• • •

VIРаспределённые файловые системы и объектные хранилища

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

«При обучении на нескольких узлах распространённая схема — использование общей файловой системы, такой как NFS-сервер, или параллельной файловой системы типа Lustre, GPFS, Ceph и т.д. С этими системами все узлы могут получать доступ к одному и тому же набору данных. Хотя это удобно, такие файловые системы могут стать узким местом, если их неправильно настроить».

«Хотя NFS прост в настройке, один NFS-сервер легко может стать узким местом по пропускной способности, если многие узлы читают одновременно. Если вам приходится использовать NFS, убедитесь, что сервер имеет несколько быстрых NIC. Также стоит рассмотреть использование нескольких NFS-серверов для разделения набора данных, чтобы каждый сервер обрабатывал свою партицию данных».

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

В главе рассматриваются параллельные файловые системы (Lustre, GPFS) и объектные хранилища (S3). Для Lustre описывается механизм страйпинга файлов по Object Storage Targets (OST): если каждый OST даёт 500 МБ/с, четыре OST обеспечат теоретический пик 2 ГБ/с на один файл.

Практическое следствие: для облачных кластеров Amazon FSx for Lustre предлагает готовый управляемый Lustre с кэшированием поверх S3. Однако в главе отмечается необходимость проверять реальный прирост производительности и обосновывать дополнительные затраты на кэш.

Для объектного хранилища S3 в главе рекомендуется предварительная загрузка данных на локальный NVMe перед стартом обучения, кэширующий слой (FSx for Lustre, Alluxio) или потоковое чтение с range-запросами и многопоточными GET. Использование специализированных инструментов (s5cmd, AWS S3 C++ SDK) позволяет получить максимальную производительность.

Отдельно рассматривается сжатие данных. Хранение сжатых данных снижает нагрузку на I/O за счёт дополнительной CPU- или GPU-работы на декодирование. Современные GPU (Blackwell) имеют встроенный движок декомпрессии (LZ4, Snappy, Deflate), который распаковывает данные прямо в HBM, не занимая SM. Это позволяет снизить нагрузку на CPU и ускорить подачу данных.

Осторожно

NFS-сервер — частый кандидат в узкое место. Один сервер с одним NIC на 25 Гбит/с насытится уже при 8–10 GPU. Для кластеров побольше используйте несколько NFS-серверов с разделением данных по партициям или переходите на параллельную файловую систему.

Баланс

Если время распаковки превышает сэкономленное время чтения — сжатие не окупается. Всегда измеряйте обе стороны уравнения. Современные GPU с аппаратной декомпрессией сдвигают баланс в сторону сжатия.

Итоги раздела VI
Ключевое положение главы

NFS подходит для небольших кластеров (до 8–10 GPU на сервер). Для больших — параллельные ФС (Lustre, GPFS) или объектные хранилища с кэшированием. Сжатие данных снижает нагрузку на I/O, если декодирование не становится новым узким местом.

Приводимые в главе цифры

Lustre: страйпинг по 4 OST с 500 МБ/с каждый даёт 2 ГБ/с на файл. S3: задержка 20–50 мс на GET-запрос. Рекомендуется предварительная загрузка или кэширующий слой.

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

Используйте lfs setstripe для Lustre. Для S3 — s5cmd, AWS S3 C++ SDK, многопоточные range-запросы. Для сжатия — форматы с аппаратной поддержкой (nvJPEG, Decompression Engine на Blackwell).

• • •

VIIКонвейер данных и DataLoader

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

«В дополнение к сырому I/O хранилища, конвейер предобработки и загрузки данных на CPU (или GPU) является критической частью общей производительности AI-нагрузки. Хорошо настроенный конвейер данных гарантирует, что GPU никогда не простаивают в ожидании новых данных. Также важно, чтобы нужный объём CPU-работы выполнялся параллельно для подачи данных на GPU».

«Использование нескольких рабочих процессов/потоков. Как упоминалось, фреймворки типа PyTorch DataLoader позволяют указать num_workers. Каждый воркер работает параллельно, чтобы получать и предобрабатывать данные. Обычно это отдельные процессы, чтобы избежать проблем с GIL Python. Главный процесс асинхронно получает батчи из очереди воркеров».

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

В главе описывается архитектура загрузчика данных в PyTorch: несколько воркеров (процессов, а не потоков, чтобы обойти GIL) параллельно читают и предобрабатывают данные, а главный процесс асинхронно получает готовые батчи из очереди. Рекомендуется использовать pin_memory=True для закрепления буферов в физической памяти и persistent_workers=True для сохранения воркеров между эпохами.

Практическое следствие: параметр num_workers определяет параллелизм загрузки. Слишком мало — GPU простаивает; слишком много — воркеры конкурируют за CPU и I/O. Для 72-ядерного Grace CPU можно задействовать больше воркеров, но с учётом закона убывающей отдачи.

Отдельно в главе рассматривается prefetch_factor — количество батчей, которые каждый воркер готовит заранее. По умолчанию 2. Если I/O имеет пиковые всплески, рекомендуется увеличить до 4–8. В очереди одновременно до num_workers × prefetch_factor готовых батчей.

Также отмечается, что предобработка может быть перенесена на GPU с помощью таких библиотек, как NVIDIA DALI, что снижает нагрузку на CPU и позволяет распараллелить декодирование и аугментацию с вычислениями.

МоментCPU / воркерыGPU
T₀Загружает батч N, предобрабатываетВычисляет батч N−1
T₁Загружает батч N+1Копирует батч N (H2D DMA), вычисляет
T₂Загружает батч N+2Вычисляет батч N+1
GIL

Воркеры PyTorch DataLoader — это процессы, а не потоки. Это не случайно: GIL Python делает многопоточную загрузку данных неэффективной для CPU-интенсивных задач. Если вы пишете свой загрузчик на чистом Python с тяжёлыми циклами — это красный флаг. Используйте векторизованные библиотеки (Hugging Face Tokenizers на Rust, TorchText на C++).

Совет

Для изоляции DataLoader временно установите num_workers=0 — это отключит предвыборку и покажет чистую стоимость загрузки без фонового планирования потоков. Но учтите: без GPU-ядер накладные расходы на запуск тоже снижаются, поэтому «чистая» скорость загрузки будет выглядеть заниженной.

Итоги раздела VII
Ключевое положение главы

DataLoader должен работать в нескольких процессах (не потоках) из-за GIL. pin_memory=True и persistent_workers=True — базовые настройки. num_workers и prefetch_factor подбираются эмпирически.

Приводимые в главе цифры

pin_memory=True улучшает производительность на 10–20% за счёт ускорения H2D-передач. prefetch_factor=2 по умолчанию; рекомендуется 4–8 при пиковых нагрузках.

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

Сравнивайте время загрузки и время вычислений. Если загрузка занимает 40 мс, а вычисления — 20 мс, GPU простаивает 67% времени. После оптимизации загрузка может упасть до 5 мс.

• • •

VIIIDALI и NeMo Curator

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

«Для сложной или тяжёлой предобработки данных NVIDIA предоставляет Data Loading Library (DALI). DALI ускоряет обработку данных, либо перемещая её на GPU, либо используя оптимизированный C++ код на CPU. Это особенно полезно для изображений и видео, где декодирование и аугментация могут выиграть от GPU-ускорения».

«NeMo Curator помогает подготавливать крупные мультимодальные наборы данных для обучения LLM. Он полезен при работе с терабайтами данных из разных источников. Curator поддерживает такие этапы обработки, как очистка, токенизация и перемешивание».

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

В главе DALI описывается как инструмент переноса декодирования и аугментации на GPU. Конвейер DALI определяется декларативно как граф операторов. Используются собственные пулы потоков и очереди — без GIL. Для задач классификации, детекции и сегментации есть готовые конвейеры.

Практическое следствие: при использовании DALI загрузка CPU падает с 800% (8 ядер на 100%) до 200% (2 ядра для чтения файлов), а декодирование и аугментация выполняются на GPU параллельно с вычислениями. Однако если использовать DALI только для декодирования JPEG, а потом передавать сырые пиксели обратно на CPU для аугментаций — дополнительные копии H2D-D2H съедят весь выигрыш.

NeMo Curator описывается как фреймворк для офлайн-подготовки данных к обучению LLM. Он выполняет очистку, фильтрацию по качеству, дедупликацию, токенизацию, перемешивание и упаковку в крупные файлы (.bin + .idx). Результат — подготовленный набор данных, который обучающий конвейер читает без парсинга JSON и токенизации на лету.

Отдельно в главе отмечается, что предобработка данных до обучения экономит время и позволяет использовать более простые и быстрые загрузчики во время обучения.

Важный нюанс

Если использовать DALI только для декодирования JPEG, а потом передавать сырые пиксели обратно на CPU для аугментаций и сборки батчей — дополнительные копии H2D-D2H съедят весь выигрыш. Держите данные на GPU на всём пути: декодирование → аугментация → обучение. Альтернатива — TorchVision V2 transforms на GPU или кастомные CUDA-ядра.

Стратегия

Подготавливайте данные до обучения. Офлайн-предобработка стоит времени один раз, а ускоряет каждый запуск. Рассмотрите хранение N перемешанных копий для N эпох — это сэкономит на перемешивании во время выполнения ценой дискового пространства.

Итоги раздела VIII
Ключевое положение главы

DALI переносит декодирование и аугментацию на GPU, снижая нагрузку на CPU. NeMo Curator выполняет офлайн-подготовку данных для LLM, упаковывая их в крупные файлы.

Приводимые в главе цифры

DALI снижает загрузку CPU с 800% до 200% при обработке изображений. Curator упаковывает данные в .bin + .idx, которые читаются memory-mappable.

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

Держите данные на GPU на всём пути: декодирование → аугментация → обучение. Офлайн-предобработка через NeMo Curator ускоряет каждый запуск обучения.

• • •

IXНепрерывное профилирование и тюнинг

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

«Инженерия производительности — это итеративный процесс. Чтобы гарантировать, что ваше распределённое приложение обучения или инференса остаётся эффективным по мере масштабирования или модификации, вы должны принять непрерывный рабочий процесс профилирования и тюнинга. Это означает регулярный сбор данных о производительности, выявление узких мест, применение оптимизаций и повторное измерение».

«Со временем обновления аппаратного и программного обеспечения изменят оптимальные настройки, поэтому вам нужно непрерывно профилировать и настраивать. Чтобы опережать это, команды, ориентированные на производительность, часто поддерживают панели мониторинга производительности для отслеживания таких метрик, как samples/sec с течением времени».

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

В главе описывается методология непрерывного профилирования: установить базовый уровень, профилировать multi-GPU запуск для выявления узких мест, углубиться в конкретные ядра при необходимости, определить причину, применить исправления, повторно измерить после каждого изменения. Рекомендуется менять одну-две вещи за раз, чтобы понимать, что именно помогло.

Практическое следствие: автоматизированные ночные запуски профилирования позволяют ловить регрессии, вызванные обновлениями драйверов, изменениями кода или ростом набора данных. Панели мониторинга с метриками samples/sec помогают отслеживать производительность во времени.

Отдельно в главе рассматриваются инструменты: iostat, iotop, nvme-cli для уровня ОС и устройств; Nsight Systems для сквозной временной шкалы; Nsight Compute для эффективности конкретных ядер; PyTorch Profiler для трейсинга операций; DCGM для метрик GPU.

Также в главе описывается методика диагностики, что ограничивает систему — сеть или вычисления: изменение размера батча при фиксированном объёме коммуникаций. Если пропускная способность сети остаётся неизменной при уменьшении батча — нагрузка ограничена сетью. Если падает — вычислениями.

ИнструментЧто показываетУровень
iostat, iotopЗагрузка дисков, IOPS, задержкиОС
nvme-cliСостояние NVMe-устройств, SMARTУстройство
Nsight Systems (nsys)Сквозная временная шкала: CPU + GPU + I/OСистема
Nsight Compute (ncu)Эффективность конкретных CUDA-ядерЯдро
PyTorch ProfilerТрейс операций, DataLoader, H2D-копированияФреймворк
DCGMМетрики GPU: загрузка, память, температураGPU
Итоги раздела IX
Ключевое положение главы

Профилирование — итеративный процесс. Меняйте одну-две вещи за раз. Регулярные ночные запуски ловят регрессии. Панели мониторинга отслеживают производительность во времени.

Приводимые в главе цифры

8 GPU дают только 5-кратное ускорение (вместо 8-кратного) — эффективность 62,5%, нужно искать узкое место. При ограничении сетью пропускная способность сети не меняется при уменьшении батча.

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

Используйте Nsight Systems для сквозной шкалы, Nsight Compute для ядер, iostat для дисков. Для диагностики сети и вычислений — эксперимент с размером батча.

• • •

XДиагностика: сеть или вычисления

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

«Чтобы понять, что ограничивает систему — вычисления или коммуникации — можно изменить соотношение вычислений к коммуникациям и посмотреть, как это повлияет на достигнутую пропускную способность сети. Рассмотрим профилирование обратного прохода обучения. В данный момент ваш gradient all-reduce использует только 60 ГБ/с из 100 ГБ/с NIC».

«Если achieved network utilization упадёт ниже 60 ГБ/с, скажем, до 40 ГБ/с, значит GPU не успевают производить данные достаточно быстро. В этом случае сеть простаивает в ожидании данных от GPU. Следовательно, вычисления — ограничивающий фактор, а не сеть».

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

В главе описывается простой и эффективный метод диагностики: зафиксировать объём коммуникаций (all-reduce зависит от числа параметров, а не от размера батча) и изменять размер батча. Если при уменьшении батча пропускная способность сети не меняется — нагрузка ограничена сетью. Если падает — вычислениями.

Практическое следствие: этот метод не требует сложных профилировщиков и может быть выполнен с помощью стандартных инструментов мониторинга. Достаточно измерить пропускную способность NIC или NVLink при разных размерах батча.

Также в главе отмечается важность измерения времени простоя GPU в ожидании данных. Сравнение времени загрузки и времени вычислений показывает, какая часть времени GPU простаивает.

Рисунок 5-5. Диагностика: сеть или вычисления

Изменение размера батча при фиксированном объёме all-reduce

0 30 60 90 ГБ/с Размер батча Маленький Большой Network-bound: NIC = 60 ГБ/с Compute-bound: NIC растёт с батчем
Описание: Если при уменьшении размера батча пропускная способность сети остаётся на уровне 60 ГБ/с (жёлтая линия) — нагрузка ограничена сетью: сеть насыщена, GPU могли бы работать быстрее. Если пропускная способность падает при уменьшении батча (голубая линия) — нагрузка ограничена вычислениями: GPU не успевают производить данные для сети.
Итоги раздела X
Ключевое положение главы

Метод диагностики: зафиксировать объём коммуникаций (all-reduce зависит от числа параметров) и изменять размер батча. Если NIC не меняется — нагрузка ограничена сетью; если падает — вычислениями.

Приводимые в главе цифры

Пример: all-reduce использует 60 ГБ/с из 100 ГБ/с NIC. Если при уменьшении батча пропускная способность остаётся 60 ГБ/с — сеть. Если падает до 40 ГБ/с — вычисления.

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

Для диагностики не нужны сложные профилировщики. Достаточно измерить пропускную способность NIC или NVLink при разных размерах батча.

• • •

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

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

Уточнение цифр по разделам

Уточнено Разделы I–IV. Быстрое хранилище, NVMe, GDS

В главе указано 14 ГБ/с для 72 GPU. Это соответствует действительности: 72 × 200 МБ/с = 14,4 ГБ/с. Рекомендация использовать none или mq-deadline для NVMe соответствует современным практикам. Тезис о 10–20% прироста от GDS является консервативной нижней оценкой; опубликованные бенчмарки показывают более широкий разброс в зависимости от загрузки CPU.

Дополнение Blackwell и Decompression Engine

Книга написана в момент, когда GB200 NVL72 был актуальной платформой. Blackwell добавляет встроенный движок декомпрессии (LZ4, Snappy, Deflate), который распаковывает данные прямо в HBM, не занимая SM. Это меняет баланс в пользу сжатия данных на диске — декодирование перестаёт быть узким местом. В главе этот аспект упоминается, но без деталей о новых возможностях Blackwell.

Уточнено Раздел V. Fire-Flyer File System

Цифра 6,6 ТиБ/с подтверждается официальным README DeepSeek. Однако конфигурация кластера в книге (68 узлов, 10 × 16 ТБ NVMe, два NIC по 100 Гбит/с) отличается от официальной (180 storage-узлов, 2×200 Гбит/с InfiniBand, 16 × 14 ТиБ NVMe, 500+ клиентских узлов); при книжной конфигурации физический потолок составлял бы ~1,7 ТБ/с, что не позволяет достичь 6,6 ТиБ/с. Цифра подтверждена, конфигурация — нет. Сравнение с Ceph (~1,1 ТБ/с) — авторская оценка книги, а не заявление DeepSeek. Дополнительно DeepSeek сообщает: GraySort 110,5 ТиБ за 30 минут 14 секунд, до 40 ГиБ/с на клиент в KVCache.

Подтверждено Раздел VII. DataLoader

Рекомендации по pin_memory=True, persistent_workers=True и подбору num_workers подтверждаются практикой. Прирост производительности на 10–20% при включении pin_memory — реалистичная оценка. prefetch_factor=4–8 рекомендуется для нагрузок с пиковым I/O.

Подтверждено Раздел VIII. DALI и NeMo Curator

DALI активно используется для CV-задач, NeMo Curator — для подготовки LLM-датасетов. Снижение загрузки CPU с 800% до 200% при использовании DALI — типичный результат. NeMo Curator упаковывает данные в .bin + .idx, которые читаются memory-mappable.

Проверка прогнозов

Подтверждён Прогноз 1: GPU будут голодать без оптимизации I/O

«Если конвейер хранения медленный, GPU будут голодать и простаивать».

Подтверждён. Практика показывает, что плохо настроенный DataLoader может тратить впустую 30–50% времени GPU. Оптимизация конвейера ввода-вывода часто даёт больше, чем алгоритмические оптимизации ядер.

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

«GPU предпочитают, чтобы данные читались крупными непрерывными блоками».

Подтверждён. Упаковка мелких файлов в крупные форматы (WebDataset, TFRecord, Arrow, Parquet) стала стандартом. NVMe SSD при последовательном чтении выдаёт 6–7 ГБ/с, при случайном — в 3–10 раз меньше.

Подтверждён как нижняя оценка Прогноз 3: GDS будет давать 10–20% прироста

«При использовании GDS нередко можно увидеть улучшения порядка 10–20% по пропускной способности».

Подтверждён как консервативная нижняя оценка. Пример gdsio в главе показывает 8,0 → 9,6 ГБ/с (+20%) и 1,25 → 1,00 мс (−20%). Опубликованные бенчмарки показывают более широкий разброс: VAST Data — 162 ГиБ/с на DGX A100 против ~33 ГБ/с традиционного пути; Meta — 3,8× ускорение обучения; OCI — до 2,7–3,5×. Выигрыш зависит от загрузки CPU.

Подтверждён Прогноз 4: 3FS покажет multi-TB/s

«3FS достигает пропускной способности в несколько терабайт в секунду».

Подтверждён. DeepSeek сообщает о 6,6 ТиБ/с. Однако конфигурация кластера в книге (68 узлов, 10 × 16 ТБ NVMe, два NIC по 100 Гбит/с) отличается от официальной (180 storage-узлов, 2×200 Гбит/с IB, 16 × 14 ТиБ NVMe). Сравнение с Ceph (~1,1 ТБ/с) — авторская оценка книги.

Частично подтверждён Прогноз 5: FUSE не даст GDS

«Если файловая система реализована через FUSE в пространстве пользователя, она не может обеспечить путь GDS».

Подтверждён с оговоркой. В целом верно: GDS требует kernel-клиента с nvidia-fs. Однако существуют гибридные решения, где FUSE используется для метаданных, а данные идут через kernel-клиент. Это редкие конфигурации, и для большинства случаев утверждение остаётся справедливым.

• • •

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

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

Аппаратная декомпрессия на Blackwell

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

Глава упоминает, что современные GPU добавляют on-die Decompression Engine (LZ4, Snappy, Deflate), но не детализирует, насколько это меняет баланс. На Blackwell декомпрессия выполняется аппаратно и не занимает SM, что делает хранение данных в сжатом виде гораздо более привлекательным. Если раньше распаковка на CPU могла стать узким местом, то теперь она практически бесплатна с точки зрения GPU-циклов. Это позволяет снизить требования к пропускной способности хранилища без потери производительности.

NVMe over Fabrics и коммутаторы

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

Глава упоминает NVMe-oF, но не рассматривает топологию коммутаторов и их влияние на производительность. В реальных развёртываниях выбор между RoCEv2 и InfiniBand, настройка PFC/ECN, размеры буферов и глубина очередей на коммутаторах могут влиять на пропускную способность сильнее, чем выбор накопителей. Для больших кластеров рекомендуется выделенная сеть хранения.

Программные определённые хранилища (SDS)

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

Глава фокусируется на аппаратных и файловых системах, но не рассматривает программно-определяемые хранилища (Ceph, MinIO, WekaFS). Некоторые из них (WekaFS) поддерживают GDS и могут быть хорошим выбором для гибридных и облачных развёртываний. Стоит изучить их как альтернативу традиционным NFS и Lustre.

Стоимость хранения

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

Глава не рассматривает экономику хранения. NVMe SSD стоят значительно дороже HDD и объектных хранилищ. Для больших наборов данных часто применяется многоуровневая стратегия: «горячие» данные на NVMe, «тёплые» на HDD или сетевом хранилище, «холодные» в объектном хранилище. Оптимизация не только скорости, но и стоимости хранения — часть работы performance-инженера.

Безопасность и изоляция

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

Глава не затрагивает вопросы безопасности: шифрование данных, изоляцию I/O между арендаторами, контроль доступа. В мультитенантных кластерах эти аспекты могут влиять на выбор хранилища и его настройку. NVMe-oF с шифрованием, SED (Self-Encrypting Drives) и контроль доступа — темы, требующие отдельного рассмотрения.

Облачные хранилища и их особенности

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

Глава упоминает Amazon S3 и FSx for Lustre, но не рассматривает специфику других облачных хранилищ (Google Cloud Storage, Azure Blob Storage). У каждого есть свои особенности: разные модели консистентности, разные лимиты на запросы, разные API. При выборе облачного хранилища для AI-нагрузок стоит тестировать их реальную производительность, а не полагаться на маркетинговые цифры.

• • •

XIIIДополнительные выводы, выходящие за пределы главы

  1. Подсистема хранения — это не «инфраструктура», а часть конвейера производительности. Глава показывает, что оптимизация I/O может дать больше, чем оптимизация ядер. Плохо настроенный загрузчик тратит впустую 30–50% времени GPU, тогда как оптимизация ядра — несколько процентов.
  2. GDS — не «серебряная пуля», а инструмент для конкретного сценария. GDS максимально эффективен, когда CPU перегружен копированиями. Если CPU справляется, прирост будет скромным. Но в любом случае GDS освобождает циклы CPU для предобработки данных.
  3. 3FS — пример того, как файловая система может быть спроектирована под AI-нагрузки. Устранение page cache, RDMA-фабрика, шардирование метаданных — эти решения дают 6,6 ТиБ/с. Конфигурация кластера в книге отличается от официального README DeepSeek, но сама цифра подтверждена.
  4. DataLoader — не «чёрный ящик». num_workers, pin_memory, persistent_workers, prefetch_factor — эти параметры нужно настраивать эмпирически. Для 72-ядерного Grace CPU можно использовать больше воркеров, но с учётом закона убывающей отдачи.
  5. Профилирование — непрерывный процесс. Ночные запуски, панели мониторинга, регрессионные тесты — это не «nice to have», а базовая гигиена production-системы. Производительность имеет свойство тихо деградировать.
  6. Диагностика сети и вычислений не требует сложных инструментов. Эксперимент с размером батча при фиксированном объёме коммуникаций — простой и эффективный метод. Если NIC не меняется при уменьшении батча — нагрузка ограничена сетью; если падает — вычислениями.
  7. Аппаратная декомпрессия на Blackwell меняет баланс. Хранение данных в сжатом виде становится более привлекательным, так как распаковка выполняется аппаратно и не занимает SM. Это снижает требования к пропускной способности хранилища.
  8. Стоимость хранения — часть уравнения. Многоуровневая стратегия (NVMe → HDD → объектное хранилище) позволяет оптимизировать не только скорость, но и стоимость. Performance-инженер должен учитывать экономику хранения.
• • •

XIVКлючевые положения

  1. Данные рядом с GPU. Локальный NVMe → NVMe-oF в стойке → сетевое хранилище → объектное хранилище. Шардируйте набор данных по узлам.
  2. Последовательный доступ. Упаковывайте мелкие образцы в крупные бинарные файлы (WebDataset, TFRecord, Arrow, Parquet). Настраивайте read_ahead_kb для потокового чтения.
  3. Тюнинг NVMe. Планировщик none или mq-deadline. Опции монтирования noatime. O_DIRECT для данных, не помещающихся в ОЗУ.
  4. GDS. Прямой DMA диск → GPU. Прирост 10–30% в зависимости от загрузки CPU (консервативная нижняя оценка). Требуется nvidia-fs и совместимая ФС.
  5. 3FS. Прямой I/O без кэша страниц, RDMA-фабрика, шардирование метаданных. 6,6 ТиБ/с (цифра подтверждена официальным README DeepSeek; конфигурация в книге отличается).
  6. Распределённые ФС. NFS для небольших кластеров; Lustre, GPFS для больших; S3 с кэшированием для облаков.
  7. DataLoader. pin_memory=True, persistent_workers=True, подбор num_workers и prefetch_factor.
  8. DALI и NeMo Curator. Переносите предобработку на GPU. Подготавливайте данные офлайн.
  9. Непрерывное профилирование. Nsight Systems, Nsight Compute, iostat, DCGM. Меняйте по одному параметру за раз.
  10. Диагностика сети и вычислений. Эксперимент с размером батча при фиксированном объёме коммуникаций.
Общий итог обзора

Пятая глава книги Fregly — систематический разбор подсистемы хранения и конвейера данных для AI-нагрузок. Ключевая идея: GPU не могут работать быстрее, чем им подают данные. Оптимизация ввода-вывода — от выбора накопителей до настройки DataLoader — может дать больше, чем оптимизация ядер. GDS, 3FS, DALI, NeMo Curator — это инструменты, которые позволяют выжать максимум из подсистемы хранения. По мере роста моделей и кластеров роль эффективного I/O будет только возрастать.

Проверка прогнозов показывает: книга оказалась точной в своих предсказаниях. GDS даёт 10–30% прироста, 3FS показывает multi-TB/s, DataLoader-настройки работают. Аппаратная декомпрессия на Blackwell меняет баланс в пользу сжатия данных. Главный вывод остаётся неизменным: поддерживайте конвейер заполненным — от диска до HBM.

Источники: Chris Fregly, «AI Systems Performance Engineering» (O'Reilly, 2026), Глава 5 — цитаты приводятся в ограниченном объёме в целях обзора и критического анализа. Документация NVIDIA GDS, NVIDIA DALI, NVIDIA NeMo Curator; DeepSeek 3FS; VAST Data; Meta; Oracle Cloud Infrastructure; MLPerf Storage; Uptime Institute; технические отчёты DeepSeek-V3.

FinCodeCow · AI Infrastructure Review

Feeding the GPU: Storage and Data Pipeline

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

This material is a review of Chapter 5 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 about the platform, verification of forecasts against open sources, 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 5 of Fregly's book is dedicated to the storage subsystem and data pipeline — the layer that determines whether the GPU will receive data fast enough. The chapter consistently examines storage selection, access patterns, NVMe and filesystem tuning, GPUDirect Storage, DeepSeek's Fire-Flyer File System, distributed filesystems, the DataLoader pipeline, DALI and NeMo Curator tools, as well as continuous profiling methodology and diagnosis of what limits the system — network or compute. The key points of the chapter are presented below, along with clarifications based on current data.

Quote from the book · Chapter 5

«Feeding data to the GPUs is as important as the compute itself for AI workloads. Consider a scenario with a 100-trillion-parameter model training on thousands of GPUs. Such a model might process billions of training samples, including tokens, images, audio, video, etc. This means that an enormous amount of data must be read from storage and fed to the GPUs as quickly as possible. If the storage pipeline is slow, the GPUs will starve and sit idle. This results in low utilization despite the sophisticated communication optimizations that we've discussed».

Exposition of content

The chapter emphasizes that the storage subsystem is not an «infrastructure detail» but a full participant in the performance pipeline. Until data reaches the GPU, computation cannot begin. The more powerful the accelerator, the sharper this gap becomes: modern GPUs can process data faster than most storage systems can deliver it.

The practical consequence noted in the chapter: the bottleneck almost always shifts toward the storage subsystem as GPU compute power grows. An engineer who looks only at FLOPS and SM utilization risks missing the main source of idle time — waiting for data.

The chapter separately provides the calculation: for 72 Blackwell GPUs in an NVL72 rack, each requiring 200 MB/s of training data, aggregate storage throughput must be 14–20 GB/s just to maintain load. This is the lower bound; multimodal workloads require more.

• • •

IFast Storage and Data Locality

Quote from the book · Chapter 5

«Large model training jobs usually need to read huge datasets. It's common to have on the order of billions or even trillions of training samples for large language models. This is in the range of terabytes of text data for language models and petabytes of images for vision models. At ultra scale, your storage system must consistently provide massive throughput to keep up with the thousands and millions of GPUs potentially running for months at a time».

«Colocating NVMe SSDs within racks—or using NVMe over Fabrics (NVMe-oF) with rack-local switch topologies—minimizes network hops and improves performance consistency».

Exposition of content

The chapter formulates a data locality hierarchy: local NVMe on the same node → NVMe-oF within the rack → network storage (NFS, Lustre, GPFS) → object storage (S3). Each transition down a level adds latency and reduces bandwidth.

Practical consequence: for distributed training, sharding the dataset across nodes is recommended. If you have 100 TB of data and 10 nodes, you can pre-split it into 10 parts of 10 TB each and place them on the local storage of each node. Then each node's data loader reads only its own 10-TB shard, and network traffic is minimized. PyTorch DistributedSampler coordinates the process so each rank gets a unique slice per epoch.

The chapter separately notes the need to scale storage throughput proportionally to the number of GPUs. If each GPU requires 200 MB/s, then 72 GPUs need 14 GB/s, and 720 GPUs need 140 GB/s. This determines storage architecture requirements.

Section I Summary
Key point of the chapter

Data should be located as close to compute as possible. Hierarchy: local NVMe → NVMe-oF in the rack → network storage → object storage. Sharding the dataset across nodes minimizes network traffic.

Figures cited in the chapter

72 GPUs × 200 MB/s = 14.4 GB/s minimum aggregate throughput. For multimodal workloads — many times more. Scaling boundaries: up to 10 nodes — a single NFS server may suffice; beyond — parallel filesystems or object storage with caching.

Practical consequence

Local NVMe provides minimum latency. NVMe-oF in the rack is a compromise between locality and flexibility. Network storage requires careful tuning (block sizes, caching, number of servers).

• • •

IISequential vs Random Reads

Quote from the book · Chapter 5

«GPUs are extremely fast at crunching data, but they prefer that the data be read in large contiguous chunks for efficiency. Similarly, storage measures much higher throughput for large, sequential reads than for small, random reads. As such, when preparing your datasets or storage layout, try to arrange for sequential access as much as possible».

«For instance, when training with images, avoid storing millions of individual image files since this will lead to lots of random seeks all over the disk. Consider, instead, storing them in a few large binary (e.g., Arrow, TFRecord, or Parquet) files, database files, WebDataset tar files, or equivalents».

Exposition of content

The chapter describes sequential access as a fundamental requirement. An NVMe SSD delivers 6–7 GB/s sequentially; randomly, it delivers 3–10× less. For GPUs the difference is even more critical, since data wait time directly affects utilization.

Practical consequence: packing small samples into large binary files is not an «optimization» but a basic requirement for efficient I/O. WebDataset, TFRecord, Arrow, Parquet, and .bin formats solve this task. When working with object storage (S3), merging small objects into large ones cuts the number of GET requests by orders of magnitude.

The chapter separately notes the importance of read block size. Reading in 1 MB chunks gives an order of magnitude more throughput than 4 KB, by amortizing syscall and DMA initialization overhead. It recommends tuning read_ahead_kb in /sys/block/<device>/queue/ — for example, to 4 MB for streaming reads of large files.

Figure 5-3. Sequential, Strided, and Random Memory Access

NVMe SSD delivers 6–7 GB/s sequentially, 3–10× less randomly

THREE ACCESS PATTERNS Sequential 1 continuous block · 6-7 GB/s Strided 6 blocks · ~2 GB/s Random 7 small blocks · ~0.5-1 GB/s
Description: Sequential access (top) gives maximum NVMe throughput. Strided (middle) is an intermediate variant where data is scattered across large blocks. Random (bottom) is the worst case for NVMe, since each request requires a separate seek operation. Packing small samples into large files shifts the load from random to sequential mode.
Section II Summary
Key point of the chapter

Sequential access is a fundamental requirement. Random reads reduce NVMe throughput by 3–10×. Packing small samples into large binary files (WebDataset, TFRecord, Arrow, Parquet) shifts the load to sequential mode.

Figures cited in the chapter

Reading in 1 MB blocks gives an order of magnitude more throughput than 4 KB. NVMe SSD: 6–7 GB/s sequentially, many times less randomly. For object storage: merging small objects into large ones cuts GET requests by orders of magnitude.

Practical consequence

Tune read_ahead_kb for streaming reads (e.g., up to 4 MB). For random access, use parallel threads with pread() or asynchronous io_uring.

• • •

IIINVMe and Filesystem Tuning for Throughput

Quote from the book · Chapter 5

«Modern Linux uses a multiqueue block I/O scheduler, blk-mq, that spreads I/O across the CPU cores. For fast NVMe SSDs, you might need to tune the queue depths and number of submission queues. Usually the defaults are fine, but if you know that your workload is heavily sequential, you might use the "none" I/O scheduler».

«The legacy completely fair queueing (CFQ) scheduler is obsolete. Modern kernels use the none or mq-deadline multiqueue scheduler by default for NVMe. This setting can be checked using /sys/block/<device>/queue/scheduler».

Exposition of content

The chapter describes three scheduler options for NVMe: none (minimal overhead, for low-latency workloads), mq-deadline (compromise with fairness), BFQ (for interactive tasks). The recommendation for AI workloads is none or mq-deadline.

Practical consequence: checking and setting the scheduler is done through /sys/block/nvme0n1/queue/scheduler. For most AI workloads, the value none gives minimal overhead.

The chapter separately examines mount options. For XFS and EXT4, noatime is recommended to disable access-time updates on every read. For NFS — increased block sizes (rsize=1048576, wsize=1048576), attribute caching (actimeo=60), and directory-entry caching (lookupcache=pos).

It also notes that the Linux page cache can be both a friend and a foe. If the dataset fits in RAM — this is free acceleration. If not — the cache starts thrashing, and the CPU spends time managing the cache instead of doing useful work. For datasets that definitely don't fit in RAM, using O_DIRECT to bypass the page cache is recommended.

SchedulerWhen to useOverhead
noneLow-latency NVMe workloads, large sequential readsMinimal
mq-deadlineMixed workloads where fairness mattersLow
BFQDesktops, interactive tasksMedium
Caution

The NFS server is a frequent bottleneck candidate. A single server with a single 25 Gb/s NIC will saturate at 8–10 GPUs. For larger clusters, use multiple NFS servers with partitioned data or move to a parallel filesystem.

Section III Summary
Key point of the chapter

For NVMe, the none or mq-deadline scheduler is recommended. The obsolete CFQ is not used. Mount options noatime and larger NFS blocks reduce overhead.

Figures cited in the chapter

NVMe: read_ahead_kb defaults to 128 KB; for streaming reads 2–4 MB is recommended. NFS: rsize/wsize up to 1 MB, actimeo=60, lookupcache=pos.

Practical consequence

Check the current scheduler via /sys/block/nvme0n1/queue/scheduler. For data that doesn't fit in RAM, use O_DIRECT with buffer and offset alignment to the device block size.

• • •

IVNVIDIA GDS — Direct Path from Disk to GPU

Quote from the book · Chapter 5

«GDS is a feature that allows GPUs to read data directly from storage devices, or through the network storage stack, without creating extra copies in CPU memory. Normally, when a GPU wants to read data from an NVMe SSD, the data first goes from SSD to CPU memory. Then a CUDA call copies the data from CPU memory to GPU memory».

«With GDS, the GPU can initiate a direct memory access (DMA) against the SSD or NIC to move the data into its own HBM memory. This bypasses the extra copy through the CPU's path. GDS supports local NVMe devices and remote storage using NVMe-oF».

Exposition of content

The chapter describes GDS as a technology that eliminates the intermediate link — the bounce buffer in host memory. The usual data path: NVMe → CPU memory → CUDA copy → GPU memory. With GDS: NVMe → GPU memory directly. The CPU still orchestrates (sets up descriptors, initiates transfers), but doesn't participate in copying.

Practical consequence: GDS is most effective when the CPU is already overloaded with copies (many high-speed memcpy calls). If the CPU is coping easily, gains will be modest — but GDS will still free CPU cycles for data preprocessing.

The chapter presents the 10–20% throughput gain thesis as a conservative lower bound. Published benchmarks show a wider spread: VAST Data reports 162 GiB/s on DGX A100 on the direct path versus ~33 GB/s through the traditional one, Meta — a 3.8× training speedup with GDS, in OCI tests on gdsio — up to 2.7–3.5× with large blocks. The actual gain depends on CPU load: the more the CPU is overloaded with copies, the higher the GDS effect.

Requirements are separately noted: a modern NVIDIA GPU, a driver with nvidia-fs support, the CUDA Toolkit, and a compatible filesystem. Supported: local NVMe and NVMe-oF on XFS/EXT4 with O_DIRECT, NFS over RDMA, parallel filesystems (BeeGFS, WekaFS, IBM Storage Scale, VAST).

The application uses the cuFile library with cuFileRead, cuFileWrite and asynchronous cuFileReadAsync, cuFileWriteAsync for integration with CUDA streams.

Figure 5-1. VAST Data Network Architecture: With and Without GDS

Comparison of data paths from storage to GPU: traditional DMA through host memory (bounce buffer) and direct GPU pull with GPUDirect Storage

WITHOUT GDS (traditional path) Data passes through host memory Memory CPU PCIe Switch NFS / RDMA (data source) GPU HBM bounce buffer copy via host transfer to GPU WITH GDS (direct GPU pull) Data bypasses host memory Memory CPU (control only) PCIe Switch NFS / RDMA (data source) GPU HBM GPU Direct Storage direct DMA to HBM Extra copy ↑ latency, ↓ throughput Direct data transfer ↓ latency, ↑ throughput
GPU Direct Storage Bounce buffer (host memory) PCIe / control
Description: Left — the traditional path: data from NFS/RDMA lands in host memory, then is copied to the GPU via PCIe. Right — GDS: the GPU initiates direct DMA from NIC to HBM, bypassing host RAM.
Quote from the book · Chapter 5

«NVIDIA provides a tool called gdsio to benchmark GDS throughput between disk and GPU. This is super useful. When using GDS, it's not uncommon to see improvements on the order of 10%–20% in throughput or more—especially in CPU-constrained scenarios».

Figure 5-4. Throughput and Latency Before and After GDS

Example gdsio benchmark: CPU path vs direct GDS

0 3 6 9 12 GB/s 8.0 Storage → CPU (without GDS) 9.6 (+20%) Storage → GPU (with GDS) 1.25 ms CPU latency (without GDS)
Description: Example gdsio benchmark: the CPU path gives 8.0 GB/s and 1.25 ms latency; with GDS — 9.6 GB/s (+20%) and 1.00 ms (−20%). Such a gain is typical for systems where the CPU was overloaded with copies.
When GDS helps most

GDS is most effective when the CPU is already overloaded with copies (many high-speed memcpy calls). If the CPU is coping easily, gains will be modest — but GDS will still free CPU cycles for data preprocessing.

Section IV Summary
Key point of the chapter

GDS eliminates the intermediate link — the bounce buffer in host memory. The GPU initiates direct DMA from NVMe or NIC to HBM. The CPU orchestrates but doesn't copy.

Figures cited in the chapter

gdsio for measurement: 8.0 GB/s and 1.25 ms without GDS; 9.6 GB/s and 1.00 ms with GDS. The «10–20%» thesis is a conservative lower bound; published benchmarks show a spread from 20% to 3.8× depending on CPU load. Requirements: Ampere or newer, driver with nvidia-fs, compatible filesystem.

Practical consequence

Use the cuFile library for direct reads. Asynchronous variants cuFileReadAsync/cuFileWriteAsync allow disk I/O to be integrated into CUDA streams for overlap with compute.

• • •

VFire-Flyer File System (3FS) by DeepSeek

Quote from the book · Chapter 5

«DeepSeek created a custom, open source filesystem called Fire-Flyer File System (3FS) from the ground up. It was born out of their observation that AI workloads perform massive numbers of random reads. These random reads make conventional read data caching ineffective—and even counterproductive—for LLM training and inference workloads. By eliminating caching and employing direct file I/O, 3FS ensures that every request goes straight to the NVMe SSD device and avoids wasteful cache management».

Exposition of content

The chapter describes 3FS as an example of a filesystem designed specifically for AI workloads. Key decisions: direct I/O without page cache, RDMA fabric (InfiniBand or RoCE), metadata sharding and replication across nodes for scalability.

Practical consequence: 3FS achieves multi-terabyte-per-second throughput by coordinating I/O across nodes. The official DeepSeek README reports 6.6 TiB/s (≈ 7.3 TB/s in decimal bytes) on a cluster of 180 storage nodes, each with 2×200 Gb/s InfiniBand and 16 × 14 TiB NVMe, plus 500+ client nodes. This figure is achieved with background training traffic. The cluster configuration in the book (68 nodes, 10 × 16 TB NVMe, two 100 Gb/s NICs) differs from the official one; with such a configuration, the physical throughput ceiling would be about 1.7 TB/s, which does not allow reaching 6.6 TiB/s. Additionally, DeepSeek official materials report GraySort results (110.5 TiB in 30 minutes 14 seconds, i.e., 3.66 TiB/min) and up to 40 GiB/s per client in KVCache. The comparison with Ceph (~1.1 TB/s) is given in the book as the author's estimate, not as an official DeepSeek statement.

Figure 5-2. Fire-Flyer File System (3FS) Components by DeepSeek

The four key components of 3FS are connected through an RDMA fabric (InfiniBand or RoCE) to minimize CPU involvement and host-side copies

RDMA Fabric InfiniBand / RoCE (zero-copy, CPU bypass) Cluster Manager cluster membership Metadata Service inodes, directories, metadata sharding + replication Storage Service data blocks on NVMe page cache bypass (O_DIRECT) Clients apps / training / inference 3FS: RDMA-first, page cache bypass, metadata sharding for scale
RDMA fabric Data services Control plane Clients
Description: 3FS splits into four roles: the cluster manager tracks node membership, the metadata service shards inode tables, the storage service talks to NVMe directly via O_DIRECT, and the client lives inside the application. All links go through the RDMA fabric, bypassing the host CPU.
Limitation

If a filesystem is implemented via FUSE in user space, it cannot provide a GDS path. Direct DMA to GPU memory needs a kernel client integrated with nvidia-fs: NVMe, NVMe-oF, BeeGFS, WekaFS, IBM Storage Scale, or VAST.

Section V Summary
Key point of the chapter

3FS is an example of a filesystem designed for AI workloads. Direct I/O without page cache, RDMA fabric, metadata sharding. Claimed throughput: 6.6 TiB/s.

Figures cited in the chapter

6.6 TiB/s (confirmed by the official DeepSeek README). The cluster configuration in the book (68 nodes, 10 × 16 TB NVMe, two 100 Gb/s NICs) differs from the official one (180 storage nodes, 2×200 Gb/s IB, 16 × 14 TiB NVMe). The comparison with Ceph (~1.1 TB/s) is the book author's estimate. Additionally DeepSeek: GraySort 110.5 TiB in 30:14, up to 40 GiB/s per client in KVCache.

Practical consequence

FUSE does not provide GDS. For direct DMA to HBM, a kernel client with nvidia-fs is needed. If you need GDS — choose NVMe, NVMe-oF, BeeGFS, WekaFS, IBM Storage Scale, or VAST.

• • •

VIDistributed Filesystems and Object Storage

Quote from the book · Chapter 5

«When training on multiple nodes, a common setup is to use a shared filesystem like an NFS server, or a parallel filesystem like Lustre, GPFS, Ceph, etc. With these systems, all nodes can access the same dataset. While convenient, these filesystems can become a bottleneck if not configured properly».

«Though it's simple to set up, a single NFS server can easily become a throughput bottleneck if many nodes are reading at once. If you must use NFS, ensure the server has multiple fast NICs. You should also consider using multiple NFS servers to split up the dataset so that each server handles a partition of data».

Exposition of content

The chapter examines parallel filesystems (Lustre, GPFS) and object storage (S3). For Lustre, the mechanism of striping files across Object Storage Targets (OST) is described: if each OST delivers 500 MB/s, four OSTs give a theoretical peak of 2 GB/s per file.

Practical consequence: for cloud clusters, Amazon FSx for Lustre offers a managed Lustre with caching on top of S3. However, the chapter notes the need to verify actual performance improvement and justify the additional cache costs.

For S3 object storage, the chapter recommends pre-loading data to local NVMe before training starts, a caching layer (FSx for Lustre, Alluxio), or streaming with range requests and multithreaded GETs. Specialized tools (s5cmd, AWS S3 C++ SDK) allow maximum performance.

Data compression is examined separately. Storing compressed data reduces I/O load at the cost of extra CPU or GPU work for decoding. Modern GPUs (Blackwell) have a built-in decompression engine (LZ4, Snappy, Deflate) that unpacks data directly into HBM without occupying SMs. This reduces CPU load and accelerates data delivery.

Caution

The NFS server is a frequent bottleneck candidate. A single server with a single 25 Gb/s NIC will saturate at 8–10 GPUs. For larger clusters, use multiple NFS servers with partitioned data or move to a parallel filesystem.

Balance

If decoding time exceeds the saved read time, compression doesn't pay off. Always measure both sides of the equation. Modern GPUs with hardware decompression shift the balance in favor of compression.

Section VI Summary
Key point of the chapter

NFS is suitable for small clusters (up to 8–10 GPUs per server). For larger ones — parallel filesystems (Lustre, GPFS) or object storage with caching. Data compression reduces I/O load if decoding doesn't become the new bottleneck.

Figures cited in the chapter

Lustre: striping across 4 OSTs with 500 MB/s each gives 2 GB/s per file. S3: 20–50 ms latency per GET request. Pre-loading or a caching layer is recommended.

Practical consequence

Use lfs setstripe for Lustre. For S3 — s5cmd, AWS S3 C++ SDK, multithreaded range requests. For compression — formats with hardware support (nvJPEG, Decompression Engine on Blackwell).

• • •

VIIData Pipeline and DataLoader

Quote from the book · Chapter 5

«In addition to raw storage I/O, the preprocessing and data loading pipeline on the CPU (or GPU) is a critical part of overall AI workload performance. A well-tuned data pipeline ensures that GPUs are never idle waiting for new data. Additionally, it's important that the right amount of CPU work is being done in parallel to feed the GPU beast».

«Use multiple worker processes/threads. As mentioned, frameworks like PyTorch DataLoader let you specify num_workers. Each worker runs in parallel to fetch and preprocess data. Usually these are separate processes to avoid Python GIL issues. The main process asynchronously fetches batches from the worker processes using a queue».

Exposition of content

The chapter describes the PyTorch data loader architecture: multiple workers (processes, not threads, to bypass the GIL) read and preprocess data in parallel, while the main process asynchronously receives ready batches from the queue. It recommends pin_memory=True to pin buffers in physical memory and persistent_workers=True to keep workers alive between epochs.

Practical consequence: the num_workers parameter controls loading parallelism. Too few — the GPU idles; too many — workers contend for CPU and I/O. For a 72-core Grace CPU, more workers can be used, but with the law of diminishing returns in mind.

The chapter separately examines prefetch_factor — the number of batches each worker prepares in advance. Default is 2. If I/O has spikes, raising it to 4–8 is recommended. The queue holds up to num_workers × prefetch_factor ready batches.

It also notes that preprocessing can be moved to the GPU using libraries like NVIDIA DALI, reducing CPU load and allowing decoding and augmentation to run in parallel with compute.

MomentCPU / workersGPU
T₀Loads batch N, preprocessesComputes batch N−1
T₁Loads batch N+1Copies batch N (H2D DMA), computes
T₂Loads batch N+2Computes batch N+1
GIL

PyTorch DataLoader workers are processes, not threads. This is intentional: Python's GIL makes multithreaded loading inefficient for CPU-intensive tasks. If you write your own loader in pure Python with heavy loops — that's a red flag. Use vectorized libraries (Hugging Face Tokenizers in Rust, TorchText in C++).

Tip

To isolate the DataLoader, temporarily set num_workers=0 — this disables prefetch and shows the raw loading cost without background thread scheduling. But note: without GPU kernels, per-launch overhead also drops, so the "pure" load speed will look lower than it really is.

Section VII Summary
Key point of the chapter

The DataLoader must work in multiple processes (not threads) due to the GIL. pin_memory=True and persistent_workers=True are baseline settings. num_workers and prefetch_factor are tuned empirically.

Figures cited in the chapter

pin_memory=True improves performance by 10–20% by accelerating H2D transfers. prefetch_factor=2 by default; 4–8 is recommended for spike loads.

Practical consequence

Compare loading time and compute time. If loading takes 40 ms and compute takes 20 ms, the GPU is idle 67% of the time. After optimization, loading can drop to 5 ms.

• • •

VIIIDALI and NeMo Curator

Quote from the book · Chapter 5

«For complex or heavy data preprocessing, NVIDIA provides their Data Loading Library (DALI). DALI accelerates data processing by either moving it to the GPU or using optimized CPU code written in C++. It's especially useful for image and video data where decoding and augmentation can benefit from GPU acceleration».

«NVIDIA NeMo is a toolkit for developing and training language models. Within the NeMo toolkit is the NeMo suite of libraries and frameworks, including the open source NeMo Curator framework. Curator helps prepare large multimodal datasets for LLM training».

Exposition of content

The chapter describes DALI as a tool for moving decoding and augmentation to the GPU. A DALI pipeline is defined declaratively as a graph of operators. It uses its own thread pools and queues — no GIL. Ready-made pipelines exist for classification, detection, and segmentation.

Practical consequence: when using DALI, CPU load drops from 800% (8 cores at 100%) to 200% (2 cores for file reads), while decoding and augmentation run on the GPU in parallel with compute. However, if DALI is used only for JPEG decoding and raw pixels are then sent back to the CPU for augmentation, the extra H2D-D2H copies will eat all the gains.

NeMo Curator is described as a framework for offline preparation of data for LLM training. It performs cleaning, quality filtering, deduplication, tokenization, shuffling, and packing into large files (.bin + .idx). The result is a prepared dataset that the training pipeline reads without JSON parsing or on-the-fly tokenization.

The chapter separately notes that preprocessing data before training saves time and allows simpler, faster loaders during training.

Important nuance

If you use DALI only for JPEG decoding and then send raw pixels back to the CPU for augmentation and batch assembly — the extra H2D-D2H copies will eat all the gains. Keep data on the GPU the whole way: decode → augment → train. Alternative — TorchVision V2 transforms on the GPU or custom CUDA kernels.

Strategy

Prepare data before training. Offline preprocessing costs time once and accelerates every run. Consider storing N shuffled copies for N epochs — this saves shuffling at runtime at the cost of disk space.

Section VIII Summary
Key point of the chapter

DALI moves decoding and augmentation to the GPU, reducing CPU load. NeMo Curator performs offline data preparation for LLMs, packing data into large files.

Figures cited in the chapter

DALI reduces CPU load from 800% to 200% when processing images. Curator packs data into .bin + .idx, which are memory-mappable.

Practical consequence

Keep data on the GPU the whole way: decode → augment → train. Offline preprocessing via NeMo Curator accelerates every training run.

• • •

IXContinuous Profiling and Tuning

Quote from the book · Chapter 5

«Performance engineering is an iterative process. To ensure that your distributed training or inference application stays efficient as you scale or modify it, you should adopt a continuous profiling and tuning workflow. This means regularly collecting performance data, identifying bottlenecks, applying optimizations, and then measuring again».

«Over time, hardware and software updates will change the optimal settings, so you need to continuously profile and tune. To stay ahead of this, performance-focused engineering teams often maintain performance dashboards to track metrics like samples/sec over time».

Exposition of content

The chapter describes a continuous profiling methodology: establish a baseline, profile the multi-GPU run for bottlenecks, drill into specific kernels if needed, identify the cause, apply fixes, and re-measure after each change. It recommends changing one or two things at a time to understand what helped.

Practical consequence: automated nightly profiling runs catch regressions from driver updates, code changes, or dataset growth. Dashboards with samples/sec metrics help track performance over time.

The chapter separately examines tools: iostat, iotop, nvme-cli for OS and device level; Nsight Systems for the end-to-end timeline; Nsight Compute for kernel efficiency; PyTorch Profiler for operation tracing; DCGM for GPU metrics.

It also describes a methodology for diagnosing what limits the system — network or compute: changing the batch size with a fixed communication volume. If network throughput remains unchanged when the batch is reduced — the load is network-limited. If it drops — compute-limited.

ToolWhat it showsLevel
iostat, iotopDisk load, IOPS, latencyOS
nvme-cliNVMe device status, SMARTDevice
Nsight Systems (nsys)End-to-end timeline: CPU + GPU + I/OSystem
Nsight Compute (ncu)Efficiency of individual CUDA kernelsKernel
PyTorch ProfilerOperation trace, DataLoader, H2D copiesFramework
DCGMGPU metrics: utilization, memory, temperatureGPU
Section IX Summary
Key point of the chapter

Profiling is an iterative process. Change one or two things at a time. Regular nightly runs catch regressions. Dashboards track performance over time.

Figures cited in the chapter

8 GPUs give only 5× speedup (instead of 8×) — efficiency is 62.5%, need to find the bottleneck. Under network limitation, network throughput does not change when the batch is reduced.

Practical consequence

Use Nsight Systems for the end-to-end timeline, Nsight Compute for kernels, iostat for drives. For network vs compute diagnosis — the batch-size experiment.

• • •

XDiagnosing Network vs Compute

Quote from the book · Chapter 5

«To understand if computation or communication is the limiting factor in a model training workload, you can change the ratio of computation to communication and see how this affects the achieved network throughput measured in GB/s on the NIC. Consider profiling the backward pass of a training job. It currently shows your gradient all-reduce is utilizing only 60 GB/s across a 100 GB/s NIC».

«If the achieved network utilization drops below 60 GB/s, to, say, 40 GB/s, the GPUs are starving the network by not finishing computations fast enough to keep the NIC busy. In this case, the network is idle, waiting for more data from the GPUs. As such, compute is the limiting factor and not the network».

Exposition of content

The chapter describes a simple and effective diagnostic method: fix the communication volume (all-reduce depends on parameter count, not batch size) and vary the batch size. If network throughput doesn't change when the batch is reduced — the load is network-limited. If it drops — compute-limited.

Practical consequence: this method doesn't require complex profilers and can be performed with standard monitoring tools. It's enough to measure NIC or NVLink throughput at different batch sizes.

It also notes the importance of measuring GPU idle time waiting for data. Comparing loading time and compute time shows what fraction of GPU time is idle.

Figure 5-5. Diagnosing Network vs Compute

Varying batch size with fixed all-reduce volume

0 30 60 90 GB/s Batch size Small Large Network-bound: NIC = 60 GB/s Compute-bound: NIC grows with batch
Description: If network throughput remains at 60 GB/s when the batch size is reduced (yellow line) — the load is network-limited: the network is saturated, GPUs could work faster. If throughput drops when the batch is reduced (cyan line) — the load is compute-limited: GPUs can't produce data fast enough for the network.
Section X Summary
Key point of the chapter

Diagnostic method: fix the communication volume (all-reduce depends on parameter count) and vary the batch size. If NIC doesn't change — network-limited; if it drops — compute-limited.

Figures cited in the chapter

Example: all-reduce uses 60 GB/s out of 100 GB/s NIC. If throughput stays at 60 GB/s when the batch is reduced — network. If it drops to 40 GB/s — compute.

Practical consequence

No complex profilers are needed for diagnosis. It's enough to measure NIC or NVLink throughput at different batch sizes.

• • •

XIForecast Verification and Current Data

Chapter 5 of 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.

Figure clarifications by section

Clarified Sections I–IV. Fast storage, NVMe, GDS

The chapter states 14 GB/s for 72 GPUs. This is correct: 72 × 200 MB/s = 14.4 GB/s. The recommendation to use none or mq-deadline for NVMe matches modern practice. The 10–20% GDS gain thesis is a conservative lower bound; published benchmarks show a wider spread depending on CPU load.

Addition Blackwell and Decompression Engine

The book was written when GB200 NVL72 was the current platform. Blackwell adds a built-in decompression engine (LZ4, Snappy, Deflate) that unpacks data directly into HBM without occupying SMs. This shifts the balance in favor of storing data compressed — decoding ceases to be the bottleneck. The chapter mentions this aspect but without details on Blackwell's new capabilities.

Clarified Section V. Fire-Flyer File System

The figure 6.6 TiB/s is confirmed by the official DeepSeek README. However, the cluster configuration in the book (68 nodes, 10 × 16 TB NVMe, two 100 Gb/s NICs) differs from the official one (180 storage nodes, 2×200 Gb/s InfiniBand, 16 × 14 TiB NVMe, 500+ client nodes); with the book configuration, the physical ceiling would be ~1.7 TB/s, which does not allow reaching 6.6 TiB/s. The figure is confirmed, the configuration is not. The comparison with Ceph (~1.1 TB/s) is the book author's estimate, not a DeepSeek statement. Additionally, DeepSeek reports: GraySort 110.5 TiB in 30 minutes 14 seconds, up to 40 GiB/s per client in KVCache.

Confirmed Section VII. DataLoader

Recommendations for pin_memory=True, persistent_workers=True and tuning num_workers are confirmed by practice. A 10–20% performance gain when enabling pin_memory is a realistic estimate. prefetch_factor=4–8 is recommended for workloads with peak I/O.

Confirmed Section VIII. DALI and NeMo Curator

DALI is actively used for CV tasks, NeMo Curator — for preparing LLM datasets. Reducing CPU load from 800% to 200% when using DALI is a typical result. NeMo Curator packs data into .bin + .idx, which are memory-mappable.

Forecast verification

Confirmed Forecast 1: GPUs will starve without I/O optimization

«If the storage pipeline is slow, the GPUs will starve and sit idle».

Confirmed. Practice shows that a poorly configured DataLoader can waste 30–50% of GPU time. Optimizing the I/O pipeline often yields more than algorithmic kernel optimizations.

Confirmed Forecast 2: Sequential access will be critical

«GPUs prefer that the data be read in large contiguous chunks».

Confirmed. Packing small files into large formats (WebDataset, TFRecord, Arrow, Parquet) has become standard. An NVMe SSD delivers 6–7 GB/s sequentially, 3–10× less randomly.

Confirmed as lower bound Forecast 3: GDS will give 10–20% gain

«When using GDS, it's not uncommon to see improvements on the order of 10%–20% in throughput».

Confirmed as a conservative lower bound. The gdsio example in the chapter shows 8.0 → 9.6 GB/s (+20%) and 1.25 → 1.00 ms (−20%). Published benchmarks show a wider spread: VAST Data — 162 GiB/s on DGX A100 versus ~33 GB/s traditional path; Meta — 3.8× training speedup; OCI — up to 2.7–3.5×. The gain depends on CPU load.

Confirmed Forecast 4: 3FS will show multi-TB/s

«3FS achieves multi-terabyte-per-second throughput».

Confirmed. DeepSeek reports 6.6 TiB/s. However, the cluster configuration in the book (68 nodes, 10 × 16 TB NVMe, two 100 Gb/s NICs) differs from the official one (180 storage nodes, 2×200 Gb/s IB, 16 × 14 TiB NVMe). The comparison with Ceph (~1.1 TB/s) is the book author's estimate.

Partially confirmed Forecast 5: FUSE will not provide GDS

«If a file system is implemented using FUSE in user space, it will not be able to deliver a GDS path».

Confirmed with caveat. Generally true: GDS requires a kernel client with nvidia-fs. However, hybrid solutions exist where FUSE is used for metadata and data goes through the kernel client. These are rare configurations, and for most cases the statement remains valid.

• • •

XIIWhat's Not Covered in the Chapter

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

Hardware Decompression on Blackwell

Additional observations

The chapter mentions that modern GPUs add an on-die Decompression Engine (LZ4, Snappy, Deflate) but doesn't detail how much this shifts the balance. On Blackwell, decompression is performed in hardware and doesn't occupy SMs, making compressed data storage much more attractive. If CPU decompression could previously become a bottleneck, it's now virtually free in terms of GPU cycles. This reduces storage bandwidth requirements without sacrificing performance.

NVMe over Fabrics and Switches

Additional observations

The chapter mentions NVMe-oF but doesn't examine switch topology and its impact on performance. In real deployments, the choice between RoCEv2 and InfiniBand, PFC/ECN tuning, buffer sizes, and switch queue depths can influence throughput more than the choice of drives. For large clusters, a dedicated storage network is recommended.

Software-Defined Storage (SDS)

Additional observations

The chapter focuses on hardware and filesystems but doesn't examine software-defined storage (Ceph, MinIO, WekaFS). Some of them (WekaFS) support GDS and can be a good choice for hybrid and cloud deployments. They are worth studying as an alternative to traditional NFS and Lustre.

Storage Cost

Additional observations

The chapter doesn't examine storage economics. NVMe SSDs cost significantly more than HDDs and object storage. For large datasets, a multi-tier strategy is often used: «hot» data on NVMe, «warm» on HDD or network storage, «cold» in object storage. Optimizing not only speed but also storage cost is part of the performance engineer's job.

Security and Isolation

Additional observations

The chapter doesn't address security: data encryption, I/O isolation between tenants, access control. In multi-tenant clusters, these aspects can influence storage selection and configuration. NVMe-oF with encryption, SED (Self-Encrypting Drives), and access control are topics requiring separate consideration.

Cloud Storage and Its Peculiarities

Additional observations

The chapter mentions Amazon S3 and FSx for Lustre but doesn't examine the specifics of other cloud storages (Google Cloud Storage, Azure Blob Storage). Each has its own features: different consistency models, different request limits, different APIs. When choosing cloud storage for AI workloads, it's worth testing their actual performance rather than relying on marketing figures.

• • •

XIIIAdditional Conclusions Beyond the Chapter

  1. The storage subsystem is not «infrastructure» but part of the performance pipeline. The chapter shows that I/O optimization can yield more than kernel optimization. A poorly configured loader wastes 30–50% of GPU time, while kernel optimization yields a few percent.
  2. GDS is not a «silver bullet» but a tool for a specific scenario. GDS is most effective when the CPU is overloaded with copies. If the CPU is coping, gains will be modest. But in any case, GDS frees CPU cycles for data preprocessing.
  3. 3FS is an example of how a filesystem can be designed for AI workloads. Eliminating page cache, RDMA fabric, metadata sharding — these decisions give 6.6 TiB/s. The cluster configuration in the book differs from the official DeepSeek README, but the figure itself is confirmed.
  4. The DataLoader is not a «black box». num_workers, pin_memory, persistent_workers, prefetch_factor — these parameters need to be tuned empirically. For a 72-core Grace CPU, more workers can be used, but with the law of diminishing returns in mind.
  5. Profiling is a continuous process. Nightly runs, dashboards, regression tests — not a «nice to have» but basic hygiene for a production system. Performance tends to silently degrade.
  6. Network vs compute diagnosis doesn't require complex tools. The batch-size experiment with fixed communication volume is a simple and effective method. If the NIC doesn't change when the batch is reduced — network-limited; if it drops — compute-limited.
  7. Hardware decompression on Blackwell shifts the balance. Storing compressed data becomes more attractive, since decompression is performed in hardware and doesn't occupy SMs. This reduces storage bandwidth requirements.
  8. Storage cost is part of the equation. A multi-tier strategy (NVMe → HDD → object storage) allows optimizing not only speed but also cost. The performance engineer must consider storage economics.
• • •

XIVKey Points

  1. Data close to the GPU. Local NVMe → NVMe-oF in the rack → network storage → object storage. Shard the dataset across nodes.
  2. Sequential access. Pack small samples into large binary files (WebDataset, TFRecord, Arrow, Parquet). Tune read_ahead_kb for streaming reads.
  3. NVMe tuning. Scheduler none or mq-deadline. Mount options noatime. O_DIRECT for data that doesn't fit in RAM.
  4. GDS. Direct DMA disk → GPU. 10–30% gain depending on CPU load (conservative lower bound). Requires nvidia-fs and a compatible filesystem.
  5. 3FS. Direct I/O without page cache, RDMA fabric, metadata sharding. 6.6 TiB/s (figure confirmed by the official DeepSeek README; the configuration in the book differs).
  6. Distributed filesystems. NFS for small clusters; Lustre, GPFS for large ones; S3 with caching for clouds.
  7. DataLoader. pin_memory=True, persistent_workers=True, tune num_workers and prefetch_factor.
  8. DALI and NeMo Curator. Move preprocessing to the GPU. Prepare data offline.
  9. Continuous profiling. Nsight Systems, Nsight Compute, iostat, DCGM. Change one parameter at a time.
  10. Network vs compute diagnosis. The batch-size experiment with fixed communication volume.
Overall Review Summary

Chapter 5 of Fregly's book is a systematic overview of the storage subsystem and data pipeline for AI workloads. The key idea: GPUs cannot work faster than they are fed data. I/O optimization — from drive selection to DataLoader tuning — can yield more than kernel optimization. GDS, 3FS, DALI, NeMo Curator are tools that let you squeeze the maximum out of the storage subsystem. As models and clusters grow, the role of efficient I/O will only increase.

Forecast verification shows: the book proved accurate in its predictions. GDS gives 10–30% gain, 3FS shows multi-TB/s, DataLoader settings work. Hardware decompression on Blackwell shifts the balance in favor of compression. The main takeaway remains unchanged: keep the pipeline full — from disk to HBM.

Sources: Chris Fregly, «AI Systems Performance Engineering» (O'Reilly, 2026), Chapter 5 — quotes provided in limited volume for review and critical analysis purposes. NVIDIA GDS, NVIDIA DALI, NVIDIA NeMo Curator documentation; DeepSeek 3FS; VAST Data; Meta; Oracle Cloud Infrastructure; MLPerf Storage; Uptime Institute; DeepSeek-V3 technical reports.