AG
Все публикации

Хранение данных и ИИ: инженерный взгляд на архитектуру тракта данных

Гусев А.П.

Авторская техническая статья, 2026

СХДAIData EngineeringNVMe-oFGPUDirect StorageMLOps

Аннотация

ИИ-нагрузки превратили хранение из пассивного склада в узел конвейера, где каждая лишняя копия и каждый промежуточный буфер стоят денег. Тракт данных от носителя до GPU не успевает за ускорителями, и пока вы не знаете, что именно измерять и где резать, ускорители простаивают за ваш счёт.

Треугольник: задержка, полоса, предсказуемость

Быстрые вычисления делают видимым каждый лишний "прыжок" данных через CPU-память, каждую ненужную сериализацию, каждый промежуточный буфер. GPU простаивает, деньги сгорают.

Возьмём грубую оценку, чтобы перевести простой GPU в деньги. В облаке вы платите за GPU-часы независимо от того, заняты ускорители вычислениями или ждут данные. Если A100 стоит порядка $2-3/час (зависит от региона/типа инстанса/модели закупки), то на 8-GPU узле это $16-24/час. При 20-30% времени ожидания данных потери составят ~$3-7/час на узел. В год (8 760 часов) это десятки тысяч долларов на один узел и сотни тысяч на небольшой кластер, плюс косвенные потери от более медленного цикла экспериментов. [1]

Разрыв по полосе действительно - на порядки, но важно помнить: HBM (внутренняя память GPU) и NVMe (внешний ввод-вывод) - разные уровни иерархии. Это не «конкурирующие шины», а причина, почему лишние копирования и переходы на пути данных быстро превращаются в простой ускорителей. [28] Поиск по данным и метаданным получает новые требования к скорости, чтобы конвейер не терялся среди миллионов объектов и версий.

Вы спросите: "Если всё так неэффективно и разрыв между хранением и обработкой довольно большой, то как тогда достигать производительности?". Ответ прост: там, где не хватает мощности, на помощь приходят техники и механики, инженерные хитрости.

С точки зрения оборудования, параллельное чтение и предсказуемая полоса важнее пиковых цифр из маркетинговой брошюры. Поэтому часто выстраивают "горячий" слой (NVMe, кэш) - как правило, обязательный элемент современных СХД. Горячий слой обслуживает только те блоки, которые находятся в активном использовании, а всё остальное находится в более медленных, но ёмких уровнях.

С точки зрения разработки, ускорение тракта данных - почти всегда про дисциплину разработчика в приложении и стеке: явные операции ввода-вывода, понимание, где копируется буфер, отказ от неявных моделей доступа, добавляющих дрожание задержек. Железо даёт лишь возможность, реализация - за инженером. Главное в разработке - не прятаться за средние значения показателей. "В среднем нормально" - это не SLO. Если вы строите дашборд на p50, а конвейер падает на p99, проблема не в конвейере, а в вас. [11]

Чтобы "задержка, полоса, предсказуемость" не стали лозунгом, нужен конкретный набор метрик. Минимум, с которого я обычно начинаю:

SLI (что измеряем)Целевой SLO (пример)Чем мерить
Read latency p99 (hot tier, block)< 500 usfio --percentile_list=50:99:99.9 (перцентили), iostat -x (средние/утилизация)
Read latency p99 (object, range)< 50 mscurl -w '%{time_total}', s3-benchmark
Throughput min (sequential read, per node)>= 10 GB/sfio --rw=read --bs=1M --numjobs=N
Jitter ratio (p99 / p50)< 3xfio --percentile_list=50:99, Prometheus
Ожидание входных данных (доля времени, когда шаг обучения ждёт данные)< 10%профилировщик (например, Nsight Systems) + метрики загрузчика данных (время загрузки батча / время шага), dcgm-exporter (контекст утилизации)
Staging latency (cold -> hot, per TB)< 5 mintime s5cmd cp ..., custom monitoring

Быстрая проверка базовых показателей:

# p99 latency и throughput для NVMe
fio --name=storage-slo --ioengine=libaio --direct=1 --bs=1M \
    --iodepth=64 --rw=read --size=10G --filename=/dev/nvme0n1 \
    --numjobs=4 --group_reporting --percentile_list=50:90:99:99.9

# Быстрая телеметрия загрузки GPU (утилизация/память и т.п.)
# Её полезно видеть в контексте, но ожидание ввода-вывода корректнее измерять профилировщиком и метриками подачи данных (время загрузки батча / время шага).
nvidia-smi dmon -s u -d 1 -c 30

Правило простое: SLO не записан - его нет; не мониторится - считаем нарушенным. Это прямое следствие ИИ-нагрузок: "быстро" должно быть измеримым.


Три модели доступа: файл, объект, блок

Раз требования к задержке и полосе изменились, протоколы доступа не могут оставаться прежними. ИИ сдвигает способ чтения: потоково, параллельно, диапазонами, пакетами. Запрос "дай мне байты с X по Y" - базовый способ не гонять лишнее по сети.

Рассмотрим кратко каждую модель:

Файловый (POSIX/NFS)Объектный (S3-подобный) + диапазонные запросыБлочный (NVMe, NVMe-oF)
Типичный запросоткрыть -> читать -> закрытьGET + Range: bytes=X-Yread LBA offset+length
Параллельное чтениеограничено блокировкамиестественно масштабируется (на объект)естественно масштабируется (по очередям)
Мелкие файлы (< 1 MB)дорого, накладные расходы на метаданныечанки внутри одного объектанет понятия "файл"
Версионированиевнешними средствамивстроенное (версии в S3, DVC)нет, управляет приложение
Кешированиесложное (согласованность кэша)простое (неизменяемые объекты)кэш страниц ОС / O_DIRECT
Управлениеправа, атрибутытеги, политики, происхождениенет, голые блоки
Сценарий в MLинтерактивдатасеты, артефакты, моделипредзагрузка, контрольные точки, путь к GPU

Файловый доступ сохраняет смысл для интерактивной работы, старых конвейеров и как архивное хранилище. Достаточно просто проверить пропускную способность на развернутом сервисе.

# NFS mount, оптимизированный под параллельное ML-чтение
# nconnect=16 -- несколько TCP-соединений для параллелизма
# rsize/wsize=1M -- крупные блоки для последовательного чтения
mount -t nfs -o vers=4.1,rsize=1048576,wsize=1048576,hard,nconnect=16 \
  nfs-server:/datasets /mnt/datasets

# Проверка реальной полосы при параллельном чтении
fio --name=nfs-bw --directory=/mnt/datasets --rw=read --bs=1M \
    --numjobs=8 --size=1G --direct=1 --group_reporting

В примере nconnect=16 увеличивает параллелизм на стороне клиента (несколько TCP-соединений) и часто помогает «раскрыть» полосу. Но это не делает NFS параллельной ФС в смысле масштабирования метаданных и данных под веерное чтение множеством процессов. Когда упираетесь в архитектурные ограничения одного NAS-контроллера или метаданных, обычно нужна масштабируемая (кластерная) или параллельная файловая система (Lustre/аналог) либо изменение схемы доступа (шардирование, локальная предзагрузка на NVMe). [6]

Объектный доступ с диапазонными запросами, это сейчас основной интерфейс для ML-фреймворков:

# Диапазонное чтение с boto3 - читаем только нужный чанк, не весь объект
import boto3

s3 = boto3.client('s3')
resp = s3.get_object(
    Bucket='ml-datasets',
    Key='imagenet/train-00042.tar',
    Range='bytes=0-1048575'  # первый мегабайт
)
chunk = resp['Body'].read()
# Параллельная загрузка датасета из S3 на локальный NVMe (предзагрузка)
# s5cmd -- быстрее aws cli за счёт внутреннего параллелизма
s5cmd --numworkers 64 cp 's3://ml-datasets/imagenet/*' /nvme/staging/

В объектном хранилище обычно есть встроенное версионирование (например, S3 versioning), а DVC формализует данные в привязке к коду. Delta Lake 3.0 с UniForm нацелена на интероперабельность: один набор данных может становиться доступным разным движкам/табличным форматам через совместимые метаданные/представления. Это снижает потребность в полном копировании, но не отменяет ограничений совместимости и требований к дисциплине схем/операций. [5, 18]

И, наконец, блочный доступ - самый короткий путь от носителя к GPU:

# fio: профилирование NVMe для предзагрузки в ML
fio --name=nvme-ml --ioengine=libaio --direct=1 --bs=1M \
    --iodepth=64 --rw=read --size=10G --filename=/dev/nvme0n1 \
    --numjobs=4 --group_reporting --percentile_list=50:99:99.9
# GPUDirect Storage: проверка поддержки и бенчмарк
/usr/local/cuda/gds/tools/gdscheck -p
/usr/local/cuda/gds/tools/gdsio -f /dev/nvme0n1 -d 0 -s 1G -i 1M -x 0 -I 1

GPUDirect Storage строит быстрый путь данных между накопителем и памятью GPU: обходит кэш страниц ОС и снижает количество копирований и накладные расходы на CPU на критическом пути ввода-вывода. При этом файловая семантика и управление (права/метаданные/открытие файла) обычно остаются в стеке - «магического исчезновения CPU» не происходит, но узкое место часто смещается. NVMe-oF расширяет блочную семантику на фабрику: те же LBA, те же очереди команд, но по сети. На хорошей RDMA-сети NVMe-oF может давать очень низкую задержку на операцию (десятки микросекунд), но сравнивать корректнее сквозные p95/p99 для конкретного профиля ввода-вывода (размер блока, глубина очереди, конкурентность, доля чтений/записей). Цена: ноль абстракций, управление полностью на приложении. [2, 21]

Ещё один вариант - SPDK (Storage Performance Development Kit): драйвер NVMe в пользовательском пространстве, который обходит ядро целиком. Для потоков предзагрузки это предсказуемые задержки ~5-10 us без дрожания от планировщика. На практике SPDK используют как основу для NVMe-oF target и для специализированных демонов предзагрузки:

# SPDK: userspace NVMe, perf -- встроенный бенчмарк
sudo HUGEMEM=4096 scripts/setup.sh
sudo build/examples/perf -q 64 -o 1048576 -w read -t 10 \
    -r 'trtype:PCIe traddr:0000:03:00.0'

[31]

Ни одна из трёх моделей не лучше сама по себе. В реальном ML-конвейере работают все три в разных местах. Типичная схема: датасеты живут в объектном хранилище, перед тренировкой подтягиваются на локальный NVMe, конфиги остаются на файловой шаре. Метаданные живут в каталоге, а не размазаны по трём уровням. [19]

Метаданные в ML - это контекст, который должен пережить команды, кварталы и аудиты: происхождение данных, права доступа, схема, лицензии. Без этого платформа деградирует до свалки. А NVMe-oF/RDMA - ещё и операционная цена: аккуратная сеть, диагностика, дисциплина изменений.

Это особенно критично, когда в вашей компании нет культуры разборов инцидентов. Ведь тогда вы переносите сложность из приложения в инфраструктуру.


Data plane: архитектура и экономика тракта

Три модели разобрали по отдельности. Теперь посмотрим, как они складываются в единый тракт от холодного хранилища до GPU и сколько стоит, если этот тракт работает плохо.

Диаграмма загружается…

Диаграмма читается сверху вниз - от самого медленного хранилища к самому быстрому. На каждом ярусе данные становятся «горячее»: ближе к вычислениям, быстрее доступ, но дороже каждый гигабайт.

На верхнем ярусе - объектное хранилище (S3 или MinIO). Это архив: здесь живут датасеты, контрольные точки моделей и всё, что нужно версионировать и хранить годами. Доступ идёт по HTTP через S3 API, задержка измеряется миллисекундами (1-50 мс), а пропускная способность одного подключения - единицы гигабайт в секунду. Медленно, зато дёшево и надёжно.

Следующий шаг вниз - блочный кэш на NVMe SSD. Сюда заранее подгружают данные, которые скоро понадобятся GPU: батчи для обучения, промежуточные контрольные точки. Задержка падает до микросекунд (10-500 мкс) - это в тысячи раз быстрее объектного хранилища. Пропускная способность одного SSD - 3-7 ГБ/с. Обращение к диску идёт напрямую (O_DIRECT), минуя кэши ОС, а по сети - через NVMe-oF.

Ещё ближе к процессору - ярус PMEM / CXL. Долгое время между NVMe и оперативной памятью зиял разрыв в два порядка по задержке. Intel Optane DC PMEM (постоянная память) частично закрывал его: задержка ~200 нс - в сотни раз быстрее NVMe, хотя и на порядок медленнее обычной DRAM. Полоса - 8-10 ГБ/с на модуль. Главное преимущество PMEM - доступ через отображение в память (DAX-FS): процессор читает данные инструкциями чтения/записи, без системных вызовов и промежуточных буферов. В конвейере машинного обучения это может быть полезно для очень горячих структур (например, векторных представлений, индексов и часто читаемых артефактов), если это действительно подтверждено профилированием.

Intel прекратил производство Optane в 2022 году, и дальше в отрасли усилился интерес к CXL Type 3 как к расширителям памяти (расширению адресного пространства памяти через CXL/PCIe). Это операционно другой класс решений, чем PMEM с DAX. Характерные задержки и полоса у CXL зависят от топологии, ширины линка и поколения PCIe/CXL, поэтому их лучше рассматривать как диапазоны и проверять на целевой конфигурации. По оценкам KAD, рынок CXL Type 3 устройств в 2026 году составит $1,8-2,5 млрд, и основные потребители - кластеры для обучения LLM. Если вы проектируете новый кластер, имеет смысл смотреть на CXL 2.0 Type 3 устройства, но закладывать отдельный этап измерений и пилотного проекта. [33, 34]

Наконец, на нижнем ярусе - память GPU (HBM). Здесь данные уже непосредственно участвуют в вычислениях. Пропускная способность HBM на H100 - 3,35 ТБ/с, что на три порядка выше любого SSD. Передача данных с NVMe или PMEM в GPU может идти через GPUDirect Storage: по DMA с сокращением копирований и участия CPU на критическом пути. Задержка перехода - единицы микросекунд.

Каждый переход между ярусами стоит времени и денег. Задача архитектора - выстроить тракт так, чтобы данные перемещались ровно столько раз, сколько необходимо, и не больше.

Сколько стоит медленный тракт?

Каждый ярус хранения несёт свои расходы, но главная статья потерь - не стоимость дисков или облачного хранилища, а простой GPU. Дорогие ускорители не считают, а ждут данных. Чтобы перевести это ожидание в деньги, достаточно одной формулы:

Потери = стоимость GPU-узла в час × доля времени ожидания ввода-вывода × количество часов в году

Возьмём типичный узел с восемью A100 - его аренда обходится примерно в $24 в час. В году 8 760 часов. Если четверть этого времени GPU простаивает в ожидании данных (а 25% ожидания ввода-вывода - реалистичная оценка для неоптимизированного тракта), потери составят:

$24 × 0,25 × 8 760 = $52 560 в год - на одном узле.

Теперь представим, что мы оптимизировали слой предзагрузки - подготовку данных перед подачей на GPU. Допустим, ожидание ввода-вывода снизилось с 25% до 20%. Разница - всего пять процентных пунктов, но в деньгах:

$24 × 0,20 × 8 760 = $42 048, то есть экономия $10 512 в год на узел.

Если пойти дальше и подключить NVMe-oF с GPUDirect Storage, сократив ожидание до 15%, экономия вырастет до $21 024. А с ярусом PMEM/CXL и доступом без лишних копирований (10% ожидания) - до $31 536 с каждого узла ежегодно.

На кластере из десяти узлов каждый из этих шагов масштабируется линейно: пять сэкономленных процентных пунктов превращаются в $100K в год. И это без учёта косвенного эффекта - ускорения цикла экспериментов: меньше ожидание, больше итераций, быстрее результат.

Второй ощутимый источник расходов - перемещение данных между площадками (исходящий трафик). Возьмём датасет объёмом 10 ТБ, который раз в месяц нужно скопировать на другую площадку. При тарифе ~$0,09 за гигабайт каждая такая операция обходится в $900, а за год набегает около $10 000 - только на трафик. При активных ML-экспериментах, когда данные перемещаются чаще и в большем объёме, сумма легко уходит за сотню тысяч долларов. [23]

Наконец, само хранение: горячий ярус (NVMe, своя площадка) стоит $50-150 за терабайт в месяц, холодный (S3-подобное облачное хранилище) - $5-25 за терабайт в месяц. Горячий тракт дороже за терабайт, но дешевле в пересчёте на «полезный GPU-час» - данные доступны быстро и GPU не простаивает. Холодный тракт дёшев для хранения, но дорог для доставки. Выбор между ними определяется частотой доступа и соотношением чтений к записям в конкретном сценарии.


"Интеллектуальная" СХД: замкнутый контур, а не чат-бот

Тракт описан, расходы посчитаны. Может ли СХД управлять им автоматически?

Словосочетание "интеллектуальная СХД" звучит привлекательно, поэтому требует уточнения. Если под "интеллектом" понимать интерфейс с генерацией текста, пользы немного. Если замкнутый контур управления (измерил -> сопоставил с SLO/SLA -> принял решение -> применил -> проверил эффект -> откатился при необходимости), тогда разговор предметный. [8]

Первым внедряют предиктивку по отказам и деградациям. Из телеметрии (ошибки, температура, износ, задержки) система формирует конкретное действие: заранее выводит узел или диск из критического контура, инициирует миграцию, поднимает тикет, проверяет корректность перестройки. Второе направление - автономный QoS. Не "поставили лимит", а аккуратная подстройка приоритетов под профиль нагрузки и SLO, с жёсткими ограничениями того, что автоматика имеет право делать.

Безопасность растёт не от модели, а от процессов: сегментация прав, контроль изменений, тестовые восстановления, аудит. Модель в этой цепочке - инструмент, не гарантия. "Умная" СХД обязана оставаться детерминированной в критичных точках: политики по намерению, понятные ограничения, обязательный откат, трассировка решений. Иначе это не интеллект, а ускоритель инцидентов. Любая автоматика в инфраструктуре - это поверхность атаки и риск разрушения данных. Требования к контролю изменений и восстановлению тут ближе к задачам целостности данных, а не к подходу "попробуем, потом докрутим". [9, 12]

Без сквозного аудита все это превращается в декорацию: вы знаете, что модель обучена, но не можете доказать, на каких данных и кем они были изменены. Для регулируемых отраслей (финансы, медицина) это не вопрос выбора.


Резервирование: не наличие копий, а доказанная восстановимость

Целостность данных и прозрачность решений - фундамент. Резервирование - следующий слой, к которому тоже стоит прикладывать инженерный стандарт, а не надежду.

Резервное копирование долго жило по принципу: скопировать по расписанию и надеяться на лучшее. В аудит это не проходит. Правильный подход: не просто иметь копии, а регулярно доказывать, что восстановление произойдёт в нужное время и в нужном объёме. [13, 14]

Первый слой автоматизации - трезвый разбор: что действительно критично, что можно восстанавливать дольше, где достаточно моментального снимка, а где нужна удалённая площадка; когда делать окно, чтобы не перегружать боевой контур; где устранение дублей и приростные цепочки дают пользу, а где превращаются в хрупкую конструкцию с неожиданностями при восстановлении.

Пример из розничной торговли: сеть из 30 точек продаж, каждая порождает по 50 ГБ в сутки (чеки, телеметрия, видео). Потеря недели - это около 10 ТБ пробела в данных, сломанная аналитика и разборы без фактов. Поэтому проверяемое восстановление должно жить там же, где рождаются данные - ближе к пользователю.

Пример из медицины: диагностический центр с МРТ/КТ и локальной ИИ-сортировкой снимков. Снимки тяжёлые, передавать их в облако долго и дорого; сбой локального хранилища останавливает оборудование и срывает окна приёма. Здесь восстановление - часть клинического процесса, а не вспомогательная функция ИТ.

Репликация между площадками - отдельная задача со своими компромиссами. Основной: какую согласованность вы готовы терпеть и сколько исходящего трафика это будет стоить.

# Rclone: синхронизация между поставщиками (S3 -> GCS) с ограничением полосы
rclone sync s3:ml-datasets/production gcs:ml-backup/production \
    --bwlimit 500M --checkers 16 --transfers 8 \
    --log-file=/var/log/rclone-sync.log

# aws s3 sync: приростная синхронизация между регионами AWS
aws s3 sync s3://ml-data-us-east-1 s3://ml-data-eu-west-1 \
    --source-region us-east-1 --region eu-west-1

# gsutil rsync: GCP, с исключением временных файлов
gsutil -m rsync -r -x '.*\.tmp$' gs://ml-data-us gs://ml-data-eu
ИнструментМежду поставщикамиПриростностьСогласованностьИсходящий трафик
rclone syncда (S3, GCS, Azure, 40+ хранилищ)по контрольным суммам / времени измененияконечнаяполный объём изменений
aws s3 syncтолько AWSпо размеру / времениконечная (S3 - строгая согласованность при чтении после записи)$0,09/ГБ между регионами
gsutil rsyncтолько GCPпо контрольным суммамконечная$0,08-0,12/ГБ между регионами

Общее правило: репликация не заменяет резервное копирование (она отлично реплицирует и ошибки), но даёт площадку аварийного восстановления и снижает время возобновления работы.

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

Оговорка, которую я считаю обязательной: однократная запись и неизменяемость - не панацея. Если атакующий получил права на управление политиками, можно получить красиво зафиксированную катастрофу. Нужны разделение ролей, отдельные контуры доступа, контроль изменений и регулярные тестовые восстановления. Без этого неизменяемость - ещё одна галочка в отчёте. [15]


Облако, репатриация и цена абстракции

Качество восстановления зависит не только от процессов, но и от того, где физически живут данные.

Часть компаний действительно возвращает критичные контуры ближе к данным и к бизнес-риску. Причины обычно три: задержка, регуляторика и экономика. Но я бы описал это без лозунгов. Репатриацию нельзя продавать как универсальный рецепт. У разных отраслей и профилей доступа разные точки боли. Облако отлично работает там, где допуски широкие, данные не слишком тяжёлые, а стоимость перемещения и запросов не доминирует в TCO. [22]

Проблемы конкретные и измеримые:

ОграничениеКак проявляетсяМасштаб
Разброс задержек (шумные соседи)p99 задержка в 5-10 раз хуже p50 при пиках у соседейисследование OSDI'12: разброс >10x на общем хранилище
Стоимость исходящего трафика"дёшево залить" != "дёшево читать и выносить"10 TB/мес * $0.09/GB = ~$10K/год, масштабируется линейно
Привязка к вендору (API/форматы)миграция требует переписывания клиентапо оценке SpringerOpen, 40-60% компаний называют это барьером
Дефицит GPU в облакеочереди на A100/H100, нет гарантий доступностизависит от провайдера и региона
Наблюдаемостьвнутрь управляемого сервиса не заглянешьнет первопричины, только симптомы

[25, 26]

Некоторые провайдеры предлагают многоуровневое поведение NAS, которое снижает остроту проблемы горячего/холодного слоя без ручной предзагрузки:

СервисМеханизмЭкономика
AWS EFS Infrequent AccessАвтоперенос файлов без обращения 30+ дней в дешёвый слой~$0.016/GBмес (IA) vs ~$0.30/GBмес (standard)
GCP Filestore Enterpriseзональная репликация + автоматическое перемещение между уровнями~$0.20/GB*мес, встроенное аварийное восстановление
Azure Lustre (управляемый сервис)NAS для задач высокопроизводительных вычислений с интеграцией в объектное хранилище Azure Blobпредзагрузка из Azure Blob без исходящего трафика внутри региона

Многоуровневый NAS не решает фундаментальных проблем облака (привязка к вендору, наблюдаемость, исходящий трафик между провайдерами). Но для файловых нагрузок, где ручное управление уровнями слишком дорого в операционном смысле, это осмысленный компромисс. [38, 39]

Тут работает эффект "гравитации данных": чем больше масса данных и чем плотнее вокруг неё сервисы, тем дороже эту массу двигать. Часто выгоднее привезти вычисления к данным, чем данные к вычислениям. [24]

ИИ уходит на устройства. По данным Gartner, AI PC составят 31% мирового рынка ПК к концу 2025 и 55% в 2026. Модели и данные всё чаще живут на рабочих станциях, а хранение и восстановление становятся локальной задачей. Параллельно растёт край: по оценке IoT Analytics, число подключенных IoT-устройств достигнет 21.1 млрд в 2025. Данные рождаются не в "центре", а на периферии, и требования к надежности сдвигаются туда же: потеря на краю часто не компенсируется центральным архивом. [29, 30]

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


СХД как часть конвейера машинного обучения

Независимо от того, где живут данные, остаётся вопрос: как хранение встраивается в конвейер машинного обучения?

СХД постепенно превращается из уровня хранения в уровень данных: рядом с данными появляются каталогизация, индексация, версии, базовые витрины, а иногда и лёгкая обработка, чтобы не гонять по сети то, что можно отфильтровать на месте. Это касается не только центров обработки данных: локальные контуры - от периферийных узлов до персональных систем с ускорителями - тоже становятся частью уровня данных, потому что там живут модели, промежуточные буферы и критичные наборы. [4]

Вычисления рядом с данными хороши, когда сводятся к малым безопасным операциям: фильтрации, проекции, предагрегации. Опасны они тогда, когда превращаются в идеологию переноса всего внутрь СХД. Сам по себе подход не плох. Плоха экстраполяция частного успеха в универсальный рецепт.

Когда оправданоКогда опасно
Фильтрация, проекция, предагрегацияБизнес-логика, трансформации, модели
Детерминированные операцииОперации с побочными эффектами
Результат легко проверить и откатитьОшибка разрушает данные
Выигрыш по трафику измеримВыигрыш гипотетический

Отдельный, пока не массовый, случай вычислений рядом с данными - блок обработки данных (DPU). NVIDIA BlueField-2/3 через DOCA SDK позволяет выполнять фильтрацию с выборкой по условию прямо на сетевой карте. Данные читаются с накопителя NVMe через DPU, фильтруются по предикату, и готовый результат отправляется в память GPU через механизм прямого доступа GPUDirect RDMA, снижая нагрузку на центральный процессор сервера.

Диаграмма загружается…

На практике это выборка нужных столбцов по условию на уровне тракта хранения. При разреженном чтении (когда из 100 ГБ нужен 1 ГБ) экономия по полосе и копированиям может быть кратной, но её нужно подтверждать сквозными замерами "от накопителя до GPU". DOCA GPUNetIO обеспечивает прямой канал от сетевого адаптера к GPU без промежуточных копий: ядра GPU могут инициировать сетевые операции через GDAKI (GPUDirect Async Kernel-Initiated). Ограничения: операции должны быть простыми (фильтрация, проекция, лёгкая агрегация), среда выполнения на DPU ограничена по памяти и вычислительным ресурсам, отладка сложнее, чем на сервере, а инструментарий пока молодой. Если узкое место на центральном процессоре при разреженном чтении не доказано замерами, DPU остаётся преждевременной оптимизацией. [36, 37]

Что потребуется архитектурно, чтобы СХД работала как часть конвейера:

Что потребуетсяЗачемЧем обосновано
Сквозные метаданные (каталог, теги, происхождение данных, политики)Единый контракт между СХД и потребителями, исключающий зависимость от устных договорённостейБез отслеживания происхождения - невоспроизводимость экспериментов, провал аудита
Многоуровневое размещение под профили МО (предварительный прогрев, закрепление, локальность)Управление теплотой не по схеме горячее/холодное, а под конкретный конвейерСтоимость простоя GPU: десятки тыс. $/узел/год при неудачной подготовке данных
Интеграция с хранилищем признаков и аналитическим озеромСоглашение о модели данных: как рождаются признаки, как обеспечивается низкая задержка при оперативном обслуживанииБез интеграции - дублирование данных, рассинхронизация обучения и обслуживания
Быстрые пути данных (RDMA / NVMe-oF)Только там, где GPU действительно ждёт ввода-вывода, что подтверждено замерамиОценивать по сквозным p95/p99 на вашем профиле ввода-вывода, а не по «идеальным» цифрам
Версионирование наборов данныхВоспроизводимость как стандартная возможность, а не надстройкаБез версий невозможно ответить, на каких данных обучена конкретная версия модели

[20]


Автономная инфраструктура: автопилот с ограждениями

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

Автоподстройка кэша, балансировка, предиктивная замена компонентов, выявление аномалий - всё это уже работает. Снимает рутину, снижает среднее время восстановления. Нормальная инженерная автоматизация, ничего революционного. [8]

Полностью автономная переконфигурация и раскатка - принципиально другой уровень. Здесь необходимы политики и ограничения, определяющие, что автоматика имеет право менять и в каком диапазоне. Необходима объяснимость - трассировка решений, позволяющая понять, почему система поступила именно так. Обязателен откат, причём проверенный на практике, а не существующий только на бумаге, и аварийное отключение. Ограничение радиуса поражения касается не только программной части. Это и архитектура - секционирование, изоляция, поэтапные выкаты, - и организационная практика: кто подтверждает изменение, как тестируется откат. Без всего перечисленного автономность остаётся лишь красивым словом, за которым стоит отсутствие контроля. [27, 9]

Изменения в конфигурации хранилища должны проходить тот же контрольный шлюз, что и изменения в коде. Пример конвейера, который после terraform apply запускает нагрузочный тест и откатывает, если целевые показатели качества не выполнены:

# .github/workflows/storage-slo.yml
name: Storage SLO Gate
on:
  push:
    paths: ['infra/storage/**']

jobs:
  slo-check:
    runs-on: self-hosted
    steps:
      - uses: actions/checkout@v4
      - name: Apply storage config
        run: terraform apply -auto-approve infra/storage/

      - name: Run fio benchmark
        run: |
          fio --name=slo-gate --ioengine=libaio --direct=1 --bs=1M \
              --iodepth=64 --rw=read --size=10G \
              --filename=/dev/nvme0n1 --output-format=json \
              --output=fio-result.json

      - name: Check SLO
        run: |
          python3 -c "
          import json, sys
          r = json.load(open('fio-result.json'))
          p99 = r['jobs'][0]['read']['clat_ns']['percentile']['99.000000']
          bw_mbs = r['jobs'][0]['read']['bw'] / 1024
          if p99 > 500000 or bw_mbs < 10000:
              print(f'SLO FAIL: p99={p99}ns, bw={bw_mbs:.0f}MB/s')
              sys.exit(1)
          print(f'SLO PASS: p99={p99}ns, bw={bw_mbs:.0f}MB/s')
          "

      - name: Rollback on failure
        if: failure()
        run: terraform apply -auto-approve infra/storage/rollback/

SLO из таблицы метрик тут не декорация, а контрольный шлюз: p99 > 500 us или пропускная способность < 10 GB/s - конвейер красный, откат автоматический. Без такого шлюза изменения в конфигурации хранилища - слепая зона в CI/CD.


Риски: что может пойти не так

Автоматизация ускоряет не только полезную работу, но и ошибки. Прежде чем расширять периметр автономности, стоит разобрать, что именно может пойти не так.

Риски интеграции ИИ в инфраструктуру приземлённые, и именно поэтому их нужно проговаривать заранее. Каждый новый слой логики - это новые режимы отказа. Модель, принимающая решения о перемещении данных, добавляет класс ошибок, которого раньше не существовало. Плюс сама модель или агент - поверхность атаки: утечки через логи, ошибочная автоматизация, и всё это на критическом пути к данным.

Объяснимость. Чем сложнее решение, тем дороже расследование. Инфраструктура без трассировки решений после инцидента - чёрный ящик. А заглядывать придётся.

Дрейф. Система начинает вести себя иначе, потому что среда и входные паттерны поменялись. Без мониторинга дрейфа вы узнаёте о проблеме по симптомам, а не по причине. И зависимость: не только от вендора, но от конкретной модели и её обновлений. По сути, привязка к вендору на уровне управленческой логики. [12, 14, 26]


Что меняется для системного инженера

Эти риски означают, что роль инженера не упрощается, а меняет фокус.

ИИ ускоряет рутину: генерацию, поиск, рефакторинг. Но ответственность за архитектуру никуда не девается. Системщик становится меньше "писателем кода ради кода" и больше инженером ограничений и последствий. На мой взгляд, это правильный сдвиг. [10]

И вырастает роль дисциплины. Когда есть слой автоматизации, ошибаться можно быстрее и массовее - вот и вся инновация. Нужны измерения, профилирование, контроль изменений, тесты на регресс по задержке, полосе и стоимости. Правило "не тестировали - считаем сломанным" - не цинизм, а экономия на инцидентах. [8]


Вместо заключения

Это и эволюция, и перелом одновременно. ИИ изменил паттерны доступа к данным, поэтому от хранения нужны новые требования и форматы. Одновременно надежность смещается к пользователю и краю, туда, где данные рождаются и потребляются. Цели те же: хранить надёжно, быстро, дёшево. Но СХД перестаёт быть пассивной коробкой и становится активным участником жизненного цикла данных. А от активной системы мы вправе требовать: объяснять свои действия, откатываться и быть безопасной по умолчанию.

Инструменты есть. Вопрос - дисциплина, измерения и готовность честно сказать: "мы это не протестировали, значит считаем сломанным". Звучит скучно. Но именно поэтому работает.


Источники