Giới thiệu — Tại Sao Bạn Cần分布式AI推理?
Xin chào, mình là Minh — một kỹ sư backend đã làm việc với AI inference hơn 3 năm. Hồi đầu, mình từng gặp cảnh một request GPT-4 mất 45 giây để xử lý, timeout liên tục khiến khách hàng chửi thẳng vào mặt. Sau khi tìm hiểu và triển khai distributed AI inference, thời gian phản hồi giảm xuống còn 800ms. Bài viết này sẽ chia sẻ toàn bộ kiến thức mình đã đúc kết được, từ khái niệm cơ bản đến code production-ready.
Distributed AI Inference Là Gì? Giải Thích Đơn Giản Cho Người Mới
Trước khi đi sâu, hãy hiểu đơn giản thế này:
- GPU đơn lẻ: Một đầu bếp làm một món ăn lớn → chậm, quá tải
- Nhiều GPU (Distributed): Nhiều đầu bếp chia việc, mỗi người làm một phần → nhanh, hiệu quả
Trong AI inference, distributed inference nghĩa là chia nhỏ model lớn (như 70B tham số) ra nhiều GPU để xử lý song song. Một GPU có 24GB VRAM không đủ chứa GPT-4 (cần ~350GB), nhưng 8 GPU × 24GB = 192GB có thể làm được.
Kiến Trúc Distributed Inference: 3 Phương Pháp Phổ Biến
1. Pipeline Parallelism — Chia theo "Dây Chuyền"
Mỗi GPU xử lý một phần của model theo thứ tự. GPU 1 xử lý layers 1-10, GPU 2 xử lý layers 11-20...
# Pipeline Parallelism - Minh giải thích đơn giản:
GPU 1: Layers 1-10 → Output: tensor[batch, seq, hidden]
GPU 2: Layers 11-20 → Output: tensor[batch, seq, hidden]
GPU 3: Layers 21-30 → Output: tensor[batch, seq, hidden]
...tiếp tục cho đến layer cuối
class PipelineParallelModel(nn.Module):
def __init__(self, num_gpus):
self.stages = []
total_layers = 80 # Giả sử model có 80 layers
layers_per_gpu = total_layers // num_gpus
for i in range(num_gpus):
# Mỗi GPU chỉ chứa một phần layers
stage_layers = layers[layers_per_gpu*i : layers_per_gpu*(i+1)]
self.stages.append(TransformerStage(stage_layers).cuda(i))
def forward(self, x):
for stage in self.stages:
x = stage(x) # Lan truyền tuần tự qua các GPU
return x
2. Tensor Parallelism — Chia Theo "Ma Trận"
Mỗi GPU xử lý một phần của ma trận trọng số. Matrix multiplication được chia làm nhiều phần, tính toán song song.
# Tensor Parallelism - Chia ma trận
Original: Y = X @ W (W có shape [hidden, hidden])
Với 2 GPU:
GPU 1: Y1 = X @ W1 → tính half của output
GPU 2: Y2 = X @ W2 → tính half còn lại
Y = [Y1, Y2] (concatenate)
class TensorParallelLinear(nn.Module):
def __init__(self, in_features, out_features, num_gpus):
self.world_size = num_gpus
self.weight_shards = []
# Chia weight matrix thành num_gpus phần
shard_size = out_features // num_gpus
for i in range(num_gpus):
shard = nn.Parameter(
torch.randn(shard_size, in_features).cuda(i)
)
self.weight_shards.append(shard)
def forward(self, x):
outputs = []
for i, shard in enumerate(self.weight_shards):
out = F.linear(x, shard) # Tính trên GPU i
outputs.append(out)
# All-gather: ghép kết quả từ tất cả GPU
return torch.cat(outputs, dim=-1)
3. Data Parallelism — Chia Theo "Dữ Liệu"
Mỗi GPU có bản sao đầy đủ của model, xử lý batch data khác nhau. Đây là cách đơn giản nhất và được dùng nhiều nhất.
# Data Parallelism - Cách đơn giản nhất
Mỗi GPU có full model, xử lý batch khác nhau
Dùng DistributedDataParallel (DDP) của PyTorch
import torch.distributed as dist
from torch.nn.parallel import DistributedDataParallel as DDP
def setup_distributed():
dist.init_process_group(backend="nccl")
local_rank = int(os.environ["LOCAL_RANK"])
torch.cuda.set_device(local_rank)
return local_rank
def train_with_ddp(model, train_loader):
local_rank = setup_distributed()
# Clone model lên GPU hiện tại
model = model.cuda(local_rank)
# Wrap với DDP - tự động sync gradients
model = DDP(model, device_ids=[local_rank])
optimizer = torch.optim.Adam(model.parameters())
for batch in train_loader:
batch = batch.cuda(local_rank)
output = model(batch)
loss = output.loss
loss.backward() # DDP tự động all-reduce gradients
optimizer.step()
optimizer.zero_grad()
So Sánh 3 Phương Pháp Distributed Inference
| Tiêu Chí | Pipeline Parallel | Tensor Parallel | Data Parallel |
|---|---|---|---|
Tài nguyên liên quanBài viết liên quan🔥 Thử HolySheep AICổng AI API trực tiếp. Hỗ trợ Claude, GPT-5, Gemini, DeepSeek — một khóa, không cần VPN. |