Решения
Данные и хранение на GPU: чекпоинты, кэш и пайплайны
Задача страницы. Помочь выстроить поток данных под GPU‑задачи: где хранить датасеты и чекпоинты, как быстро переносить большие объёмы, чем кэшировать, как избежать простоя GPU из‑за I/O и не потерять прогресс при прерывании инстанса.
Принципы, которые экономят часы и деньги
- Локальность и «горячие» данные. Датасеты и модели, которые активно читаются, держите на локальном NVMe (внутри инстанса). Всё остальное — в объектном хранилище.
- Мало крупных файлов лучше, чем много мелких. Пакуйте датасеты в tar‑шарды/партиции; тысячам мелких файлов всегда проигрывать по IOPS.
- Потоковый конвейер вместо «ждать пока скачается всё». Стриминг и префетч позволяют считать уже первые батчи, пока хвост догружается.
- Идемпотентность и автосейвы. Любой шаг должен безопасно перезапускаться; чекпоинты и артефакты — с версионированием и атомарной записью.
- Отделяйте вычисления от хранения. Инстанс можно удалить, данные — нет; чекпоинты и артефакты дублируйте в долговременное хранилище.
Быстрый выбор стратегии (по размеру и типу задачи)
- До ~50 ГБ (прототип, инференс): копируйте прямо на NVMe инстанса; кэш моделей/эмбеддингов тоже туда.
- 50–500 ГБ (тренировка, CV): храните в объектном хранилище, при старте — быстрая синхронизация «горячих» шардов на NVMe + фоновая докачка.
- 500 ГБ–10 ТБ (LLM, видео): храните в объектном хранилище; используйте тар‑шарды/WebDataset, стриминг и агрессивный префетч; чекпоинты — сразу в удалённое хранилище.
- Multi‑node: на каждый узел — локальный кэш под свой shard‑диапазон; не тяните одни и те же файлы по сети на все узлы одновременно.

Чекпоинты: никакой потери прогресса

Как часто?
- Обучение: по времени (например, каждые 15–30 мин.) и по шагам/эпохам.
- Инференс/батчи: по чанкам (N образцов/клипов/документов).
Структура и атомарность:
- Пишите во временный файл и атомарно переименовывайте в целевое имя: checkpoint.tmp → checkpoint.pt.
- Держите ротацию: …/ckpt-000100, …/ckpt-000200 и latest как симлинк/манифест.
- Сразу после записи — дублирование в удалённое хранилище (объектное/S3‑совместимое).
Пример (PyTorch, атомарная запись + дублирование)
import os, json, torch, fsspec, tempfile
def atomic_save(obj, path_local):
d = os.path.dirname(path_local); os.makedirs(d, exist_ok=True)
with tempfile.NamedTemporaryFile(dir=d, delete=False) as t:
torch.save(obj, t.name)
tmp = t.name
os.replace(tmp, path_local) # атомарно
def save_and_upload(state, local_path, remote_url):
atomic_save(state, local_path)
with fsspec.open(local_path, "rb") as fsrc, fsspec.open(remote_url, "wb") as fdst:
fdst.write(fsrc.read())
# пример: save_and_upload(state, "/data/ckpts/ckpt-000200.pt", "s3://bucket/exp1/ckpt-000200.pt")
Перенос и подготовка датасетов
Быстрый параллельный HTTP/HTTPS:
# urls.txt — список прямых ссылок; aria2 параллелит загрузку
aria2c -i urls.txt -x16 -s16 -j8 -d /data/datasets
Объектное хранилище / S3‑совместимое (пример rclone):
# копируем с высокой параллельностью, проверками и резюме
rclone copy s3:mybucket/path /data/datasets/path \
--transfers=32 --checkers=64 --fast-list --copy-links --progress
Синхронизация из другого сервера (rsync):
rsync -ah --info=progress2 --partial --inplace --chmod=ugo=r \
--exclude='*.tmp' source:/datasets/imagenet/ /data/datasets/imagenet/
Архивы и тар‑шарды:
- Разбивайте датасет на шарды по 512 МБ–2 ГБ в формате tar (или parquet‑партиции) — это резко снижает накладные расходы при чтении.
- Для картинок/видео используйте WebDataset (tar‑шарды + индекс).
Синхронизация из другого сервера (rsync):
import webdataset as wds
dataset = (wds.WebDataset("/data/datasets/myset/{000000..000255}.tar")
.decode("pil")
.to_tuple("jpg;png", "json"))
loader = wds.WebLoader(dataset, batch_size=64, num_workers=8)


Кэширование: модели, датасеты, артефакты
Стандартизируйте пути к кэшу (переопределите их на NVMe инстанса):
export HF_HOME=/data/.cache/hf
export TRANSFORMERS_CACHE=$HF_HOME/transformers
export HF_DATASETS_CACHE=$HF_HOME/datasets
export TORCH_HOME=/data/.cache/torch
mkdir -p $TRANSFORMERS_CACHE $HF_DATASETS_CACHE $TORCH_HOME
Предпрогрев (pre‑warm):
- На этапе «подготовки» один раз скачайте веса/токенайзеры/вспомогательные артефакты в кэш, затем снимайте образ/шаблон или закрепляйте диск.
- Для инференс‑сервисов держите отдельный слой кэша (например, общий том), чтобы деплои не перекачивали веса заново.
Дата‑пайплайны для обучения/инференса
Обучение:
- Префетч и pinned memory в DataLoader.
- Аугментации на GPU, где уместно, чтобы CPU не стал бутылочным горлышком.
- Шардирование по эпохам — распределяйте список шардов между воркерами/узлами, чтобы избежать «драки» за одинаковые файлы.
Инференс/батчи:
- Читайте из источника чанками (N документов/клипов), сохраняйте промежуточные результаты каждые M чанков.
- Параллельно выгружайте результаты в хранилище; не накапливайте гигабайты в /tmp.
Видеопотоки/рендер:
- Храните исходники на объектном хранилище; формируйте рабочие очереди ссылок и вытягивайте в локальный кэш непосредственно перед обработкой.
- Используйте NVENC/AV1 профили и фиксированные пресеты (см. раздел рендеринга).
Multi‑node и распределённый I/O
- Своя доля для каждого узла. Раздавайте каждому узлу собственный набор шардов; избегайте общей сетевой директории с «горячими» чтениями.
- Локальный кэш → чистка по LRU. Ограничьте размер кэша; вычищайте неиспользуемые шарды по LRU, чтобы NVMe не забивался.
- Параллельные менеджеры загрузки. Разделите пул «скачивателей» и «читателей», чтобы обучение не ждало сеть/диск.
Безопасность и управление доступом
- Секреты только через переменные окружения/секрет‑менеджер. Не коммитьте токены в репозиторий; ограничьте объём выведенных логов.
- Шифруйте архивы и чувствительные артефакты. При необходимости — шифрование на стороне клиента перед загрузкой в объектное хранилище.
- Маскируйте пути/имена в публичных артефактах; для датасетов с PII используйте анонимизацию/псевдонимизацию.
Стоимость и жизненный цикл данных
- Хранение тарифицируется даже у остановленных инстансов. Планируйте объёмы дисков и своевременную чистку.
- Стейджинг‑диск ≠ архив. После завершения — выгрузка артефактов в долговременное хранилище, удаление инстанса/тома.
- Сжимайте и дедуплицируйте. Zstd для больших логов/JSON; избегайте gzip для потокового чтения (zstd быстрее и эффективнее).
Траблшутинг
- GPU простаивает (<70%): проверьте num_workers, pin_memory, префетч, скорость диска/сети, наличие шардов локально.
- OOM на диске: включите LRU‑чистку кэша и ротацию временных файлов; не держите несколько копий одного и того же датасета.
- Повреждённые файлы: проверяйте контрольные суммы; включите повторные попытки/резервные зеркала в загрузчиках.
- Прерываемые инстансы: проверяйте, что чекпоинт пишется «часто и атомарно», и немедленно выгружается наружу.
Полезные сниппеты
PyTorch DataLoader (параметры I/O):
loader = DataLoader(dataset,
batch_size=64,
shuffle=True,
num_workers=8,
pin_memory=True,
persistent_workers=True,
prefetch_factor=4)
Загрузка из объектного хранилища по списку ключей:
import fsspec
fs = fsspec.filesystem("s3", anon=False)
for key in keys:
with fs.open(f"s3://bucket/{key}", "rb") as fsrc, open(f"/data/{key}", "wb") as fdst:
fdst.write(fsrc.read())