Перейти к содержанию

Шпаргалка: обучение ML и распределенные системы

~8 минут чтения

Предварительно: Оптимизаторы и SGD | Архитектура трансформера

Справочная карточка по распределенному обучению и fine-tuning LLM. Обучение модели на 70B параметров требует ~1120 GB памяти (параметры + градиенты + optimizer states AdamW), что в 14 раз превышает объем одного H100 (80 GB). FSDP2/ZeRO-3 шардируют все три компонента по N GPU, снижая потребление до M/N на каждый. LoRA тренирует лишь 0.1-1% параметров с 95-99% качества full fine-tuning. Эта шпаргалка покрывает DDP, FSDP2, DeepSpeed ZeRO, LoRA/QLoRA, mixed precision, activation checkpointing и multi-node training -- ключевые темы для system design интервью.

Тип: synthesis / interview cheat sheet Дата: Февраль 2026 Synthesis of: Distributed training, FSDP, DeepSpeed, fine-tuning


Quick Reference: Key Numbers

Metric Value Context
GPU memory (H100) 80 GB Standard for LLM training
GPU memory (H200) 141 GB Enhanced for large models
Communication overhead 10-40% Multi-GPU/multi-node
FSDP memory reduction 2-4× vs DDP with full shards
ZeRO-3 memory ~1/N of params N = number of GPUs
Gradient accumulation Linear scaling Batch = micro_batch × accum

1. Distributed Training Frameworks

Comparison Table

Framework Strength Memory Best For
DDP Simple Full model per GPU Small models
FSDP2 Native PyTorch Sharded Large models
DeepSpeed ZeRO-3 Enterprise Minimal 100B+ models
Megatron-LM Model parallel Efficient Transformer-specific
FSDP2 + TP Combined Optimal 70B+ models

Decision Framework

Model < 7B?                 → DDP (simplest)
Model 7B-70B?               → FSDP2
Model > 70B?                → FSDP2 + Tensor Parallel or ZeRO-3
H100 cluster?               → FSDP2 (native PyTorch 2.0+)
Need fastest iteration?     → Megatron-LM + 3D parallel
Constrained memory?         → DeepSpeed ZeRO-3 + CPU offload

Memory Scaling

Parallelism Memory per GPU Communication
DDP O(M) All-reduce gradients
FSDP (FULL_SHARD) O(M/N) All-gather + reduce-scatter
ZeRO-3 O(M/N) + optimizer Heavy communication
Tensor Parallel O(M/N_tp) All-reduce per layer

2. FSDP2 (Fully Sharded Data Parallel)

Key Concepts

DDP:     Each GPU has FULL model copy
FSDP:    Each GPU has SHARD of parameters, gradients, optimizer states

Sharding levels:
- SHARD_GRAD_OP: Shard gradients + optimizer (default)
- FULL_SHARD: Shard params + grads + optimizer (most memory efficient)
- NO_SHARD: Like DDP (for debugging)

FSDP2 Configuration

from torch.distributed.fsdp import FullyShardedDataParallel as FSDP
from torch.distributed.fsdp import ShardingStrategy

# Full sharding (most memory efficient)
model = FSDP(
    model,
    sharding_strategy=ShardingStrategy.FULL_SHARD,
    device_id=torch.cuda.current_device(),
    mixed_precision=mp_policy,
)

# Wrap individual layers for efficiency
from torch.distributed.fsdp.wrap import transformer_auto_wrap_policy
policy = transformer_auto_wrap_policy(
    transformer_layer_cls={TransformerBlock}
)
model = FSDP(model, auto_wrap_policy=policy)

FSDP2 vs DeepSpeed ZeRO

Feature FSDP2 DeepSpeed ZeRO-3
Native PyTorch 2.0+ Separate library
Memory O(M/N) O(M/N)
Activation checkpointing Built-in Built-in
CPU offload Supported Supported
Pipeline parallel Via other libs Native
Mixed precision Native Native

3. DeepSpeed ZeRO Stages

ZeRO Stages

Stage Sharded Memory Reduction
ZeRO-1 Optimizer states
ZeRO-2 + Gradients
ZeRO-3 + Parameters N× (N = GPUs)

ZeRO-3 Configuration

deepspeed_config = {
    "zero_optimization": {
        "stage": 3,
        "offload_optimizer": {
            "device": "cpu",
            "pin_memory": True
        },
        "offload_param": {
            "device": "cpu",
            "pin_memory": True
        },
        "overlap_comm": True,
        "contiguous_gradients": True,
    },
    "gradient_accumulation_steps": 4,
    "train_micro_batch_size_per_gpu": 1,
}

Memory Calculation (70B model)

Parameters (BF16):          140 GB
Gradients (BF16):           140 GB
Optimizer states (AdamW):   840 GB (560 + 280)
────────────────────────────────────
Total:                      1120 GB

With ZeRO-3 on 8 GPUs:      140 GB per GPU
With ZeRO-3 + CPU offload:  ~20 GB GPU memory

4. Fine-Tuning Methods

Methods Comparison

Method Trainable Params Memory Quality Speed
Full fine-tuning 100% Full Best Slow
LoRA 0.1-1% 30-50% 95-99% Fast
QLoRA 0.1-1% 15-25% 93-98% Faster
Prefix tuning 0.1% 20% 90-95% Fast
Adapter 1-5% 35% 92-97% Fast

LoRA Formula

\[W = W_0 + \Delta W = W_0 + BA\]

Where: - \(W_0\): Frozen pretrained weights (\(d \times k\)) - \(B\): Low-rank matrix (\(d \times r\)) - \(A\): Low-rank matrix (\(r \times k\)) - \(r\): Rank (typically 8-64)

LoRA Configuration

from peft import LoraConfig, get_peft_model

config = LoraConfig(
    r=16,                    # Low rank
    lora_alpha=32,           # Scaling factor
    target_modules=["q_proj", "v_proj", "k_proj", "o_proj"],
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM",
)

model = get_peft_model(model, config)
# Trainable params: ~0.5% of original

QLoRA (Quantized LoRA)

from transformers import BitsAndBytesConfig

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16,
    bnb_4bit_use_double_quant=True,
)

model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-3.1-70B",
    quantization_config=bnb_config,
    device_map="auto",
)
# Then apply LoRA on top

5. Gradient Accumulation & Mixed Precision

Effective Batch Size

\[\text{Batch}_{\text{effective}} = \text{Batch}_{\text{micro}} \times \text{Accum} \times N_{\text{GPUs}}\]

Example: - Micro batch: 1 - Accumulation: 8 - 8 GPUs - Effective batch: 64

Mixed Precision Training

Precision Memory Speed Stability
FP32 100% Baseline Best
FP16 50% 2-3× Needs loss scaling
BF16 50% 2-3× Good (Ampere+)
FP8 25% 3-4× Needs care (H100)

BF16 Configuration

from torch.amp import autocast, GradScaler

scaler = GradScaler()  # For FP16, not needed for BF16

with autocast(device_type="cuda", dtype=torch.bfloat16):
    output = model(input)
    loss = criterion(output, target)

loss.backward()
optimizer.step()

6. Activation Checkpointing

Memory vs Compute Trade-off

Without checkpointing:  Store all activations (high memory)
With checkpointing:     Recompute during backward (low memory, +30% compute)

Memory Reduction

Checkpointing Memory Compute Overhead
None 100% 0%
Selective 50-70% 10-20%
Full 30-50% 25-35%

Implementation

from torch.utils.checkpoint import checkpoint

class CheckpointedBlock(nn.Module):
    def forward(self, x):
        if self.training:
            return checkpoint(self._forward, x, use_reentrant=False)
        return self._forward(x)

    def _forward(self, x):
        # Actual forward logic
        return self.layers(x)

# FSDP native activation checkpointing
from torch.distributed.fsdp import FullyShardedDataParallel as FSDP
from torch.distributed.algorithms._checkpoint.checkpoint_wrapper import (
    checkpoint_wrapper,
)

layer = checkpoint_wrapper(TransformerBlock(), use_reentrant=False)

7. Multi-Node Training

Network Topology

graph TB
    subgraph Node0["Node 0"]
        G0["GPU 0"] ---|NVLink| G1["GPU 1"]
        G0 --- NIC0["NIC"]
        G1 --- NIC0
    end
    subgraph Node1["Node 1"]
        G2["GPU 0"] ---|NVLink| G3["GPU 1"]
        G2 --- NIC1["NIC"]
        G3 --- NIC1
    end
    NIC0 ---|"InfiniBand / RoCE"| NIC1

    style G0 fill:#e8eaf6,stroke:#3f51b5
    style G1 fill:#e8eaf6,stroke:#3f51b5
    style G2 fill:#e8eaf6,stroke:#3f51b5
    style G3 fill:#e8eaf6,stroke:#3f51b5
    style NIC0 fill:#fff3e0,stroke:#ef6c00
    style NIC1 fill:#fff3e0,stroke:#ef6c00

Communication Patterns

Pattern Use Case Bandwidth
All-Reduce Gradient sync 2(N-1)/N × P per GPU
All-Gather FSDP params (N-1)/N × P per GPU
Reduce-Scatter FSDP grads (N-1)/N × P per GPU
P2P Pipeline parallel Model dependent

Launch Commands

# Single node, 8 GPUs
torchrun --nproc_per_node=8 train.py

# Multi-node (2 nodes, 8 GPUs each)
# Node 0:
torchrun --nproc_per_node=8 --nnodes=2 \
    --node_rank=0 --master_addr=10.0.0.1 train.py

# Node 1:
torchrun --nproc_per_node=8 --nnodes=2 \
    --node_rank=1 --master_addr=10.0.0.1 train.py

8. Training Optimization Checklist

Memory Optimization

□ Use BF16 mixed precision
□ Enable activation checkpointing
□ Use FSDP2 with FULL_SHARD
□ Apply gradient accumulation
□ Consider CPU offloading for large models
□ Use gradient clipping to prevent overflow

Speed Optimization

□ Use torch.compile() for fusion
□ Enable CUDA graphs where possible
□ Overlap computation and communication
□ Use efficient attention (FlashAttention)
□ Pin memory for dataloader
□ Pre-fetch next batch

Stability

□ Gradient clipping (norm 1.0)
□ Learning rate warmup
□ Weight decay (0.01-0.1)
□ Checkpoint regularly
□ Monitor loss spikes
□ Validate on held-out data

9. Типичные заблуждения

Заблуждение: FSDP и DDP -- это одно и то же, только FSDP новее

DDP хранит полную копию модели на каждом GPU и синхронизирует только градиенты (all-reduce). FSDP шардирует параметры, градиенты И optimizer states по GPU, снижая потребление в N раз. Для 70B модели: DDP требует 1120 GB на КАЖДЫЙ GPU (невозможно), FSDP с FULL_SHARD -- 140 GB/GPU на 8 GPU. DDP подходит только для моделей, помещающихся в 1 GPU (<7B на H100).

Заблуждение: LoRA rank=64 всегда лучше rank=8

Больший rank не всегда дает лучшее качество. При r=64 LoRA обучает в 8 раз больше параметров, что может привести к overfitting на маленьких датасетах. Для domain adaptation (10K-100K примеров) r=8-16 часто оптимален. r=64 оправдан при instruction tuning на больших датасетах (100K+). Рекомендация: начинать с r=16, увеличивать только если validation loss улучшается.

Заблуждение: gradient accumulation=16 эквивалентно batch_size*16

Математически градиенты усредняются одинаково, но на практике BatchNorm (если есть) видит маленькие micro-batch, а не большой batch. Для трансформеров без BatchNorm -- действительно эквивалентно. Но: gradient accumulation не дает speedup -- те же FLOPs, только меньше памяти. Communication overhead при DDP снижается (sync раз в N шагов), но при FSDP это менее значимо.


10. Интервью-вопросы

Базовые

В: Объясните data parallelism vs model parallelism

❌ "Data parallelism -- данные на разных GPU, model parallelism -- модель на разных GPU"

✅ "Data Parallelism (DDP): каждый GPU хранит полную копию модели, обрабатывает свою порцию данных, затем синхронизирует градиенты через all-reduce. Model Parallelism: модель разрезается между GPU -- Tensor Parallel (разрезка внутри слоя, all-reduce после каждого слоя) или Pipeline Parallel (разные слои на разных GPU, micro-batch pipelining). FSDP -- гибрид: шардирует параметры как model parallel, но обрабатывает данные как data parallel"


В: Что такое gradient accumulation?

❌ "Накапливаем градиенты вместо одного шага"

✅ "Gradient accumulation: forward/backward на micro-batch, но optimizer.step() вызывается через N micro-batches. Effective batch = micro_batch * N * num_GPUs. Пример: micro=1, accum=8, 8 GPU -> effective batch 64. Это позволяет симулировать большие батчи на ограниченной памяти. Критично: loss нужно делить на N, а не суммировать. Для FSDP: no_sync() context manager предотвращает лишнюю коммуникацию между accumulation steps"


В: Зачем mixed precision?

❌ "BF16 быстрее FP32"

✅ "Mixed precision: forward/backward в BF16 (2x меньше памяти, 2-3x ускорение на Tensor Cores), но master weights и optimizer states в FP32 для стабильности. BF16 vs FP16: BF16 имеет тот же range (8 exponent bits), что и FP32, поэтому не нужен loss scaling -- стабильнее. FP8 на H100/Blackwell дает 3-4x ускорение, но требует аккуратной калибровки. AMP (autocast) делает это автоматически"

Продвинутые

В: Сравните FSDP и DeepSpeed ZeRO-3

❌ "FSDP -- из PyTorch, DeepSpeed -- из Microsoft, оба делают одно и то же"

✅ "Оба шардируют параметры, градиенты и optimizer states, давая O(M/N) памяти на GPU. Различия: FSDP2 -- нативный PyTorch 2.0+ (меньше зависимостей, лучшая интеграция с torch.compile), DeepSpeed ZeRO-3 -- pipeline parallel из коробки, продвинутый CPU/NVMe offload, ZeRO++ с quantized communication. Для 7B-70B на одном узле -- FSDP2 (проще). Для 100B+ multi-node с pipeline parallel -- DeepSpeed. TorchTitan объединяет оба подхода"


В: Когда LoRA vs full fine-tuning?

❌ "LoRA когда мало GPU"

✅ "LoRA (rank decomposition W = W0 + BA) тренирует 0.1-1% параметров, давая 95-99% качества full FT. Выбор LoRA: (1) ограниченный бюджет GPU (QLoRA на одном GPU для 70B), (2) domain adaptation на малых данных (10K-100K), (3) нужно быстро переключать adapters (multi-task). Full FT: (1) максимальное качество критично, (2) достаточно compute, (3) значительный domain shift. lora_alpha = 2 * rank -- стандартная эвристика. Target modules: q, k, v, o projections + gate/up/down для FFN"


В: Как activation checkpointing экономит память?

❌ "Не хранит активации"

✅ "Без checkpointing все промежуточные активации хранятся для backward pass -- для 70B это сотни GB. С checkpointing: хранятся только входы checkpoint-boundary, остальные пересчитываются при backward. Trade-off: 50-70% экономии памяти за 25-35% дополнительного compute. Selective checkpointing (только attention layers) дает 50% экономии за 10-20% overhead. В FSDP: checkpoint_wrapper оборачивает каждый TransformerBlock"

System Design

В: Спроектируйте обучение 70B модели на 8xH100

❌ Перечисление технологий без расчетов

✅ "Расчет памяти: 70B * 16 bytes/param (BF16 + AdamW) = 1120 GB. На 8 GPU FSDP FULL_SHARD: 140 GB/GPU, что превышает H100 80 GB. Решение: (1) FSDP2 FULL_SHARD + activation checkpointing -> ~80-90 GB/GPU, (2) gradient accumulation 4-8 для effective batch 32-64, (3) BF16 mixed precision + FlashAttention-3, (4) gradient clipping norm=1.0. Если не хватает: ZeRO-3 + CPU offload снижает GPU memory до ~20 GB, но training на 3-5x медленнее из-за PCIe bottleneck"


10. Formulas Quick Reference

Effective Batch Size

\[B_{\text{eff}} = B_{\text{micro}} \times A \times N\]

Where \(A\) = accumulation steps, \(N\) = number of GPUs

LoRA Trainable Parameters

\[P_{\text{LoRA}} = 2 \times r \times (d + k) \times n_{\text{layers}}\]

Where \(r\) = rank, \(d\) = hidden dim, \(k\) = output dim

Memory per GPU (FSDP)

\[M_{\text{GPU}} = \frac{P \times 16}{N} + M_{\text{activation}}\]

Where 16 bytes/param = 2 (param BF16) + 2 (grad BF16) + 12 (AdamW FP32: master weights + first/second moments)

Communication Volume (All-Reduce)

\[V = 2 \times P \times (N-1) / N\]

11. Sources Synthesized

  1. distributed-training-comparison.md — FSDP vs DeepSpeed
  2. lora-qlora-implementation-2025.md — PEFT methods
  3. llm-quantization-2025-2026.md — QLoRA
  4. moe-advances-2025-2026.md — MoE training
  5. normalization-comparison-2025-2026.md — Training stability
  6. distributed-training-fsdp-deepspeed-2026.md — FSDP2, DeepSpeed ZeRO++ updates (ФАЗА 5)
  7. llm-alignment-peft-2026.md — GRPO, LoRA for alignment (ФАЗА 5)
  8. llm-compression-distillation-2026.md — Knowledge distillation, P-KD-Q (ФАЗА 5)