首页 运维干货单张 GPU 放不下模型时,如何部署多 GPU 推理

单张 GPU 放不下模型时,如何部署多 GPU 推理

运维派隶属马哥教育旗下专业运维社区,是国内成立最早的IT运维技术社区,欢迎关注公众号:yunweipai
领取学习更多免费Linux云计算、Python、Docker、K8s教程关注公众号:马哥linux运维

问题背景

大模型参数量越来越大,从 GPT-3 的 175B 到 LLaMA 70B、Qwen 72B,单张 GPU 显存(24GB/48GB/80GB)往往无法容纳完整模型。多 GPU 推理成为必然选择。

本文适用于以下角色:

  • 需要部署大模型的算法工程师
  • 负责 GPU 资源管理的运维工程师
  • 需要优化推理性能的 MLOps 工程师
  • 研究多 GPU 并行的研发工程师

多 GPU 推理的特点:

  • 模型参数分布在多张 GPU 上
  • 需要跨 GPU 通信
  • 显存和计算资源成倍增加
  • 推理延迟可能增加
  • 配置复杂度提高

适用场景

本文适用于以下场景:

  • 单张 GPU 显存不足以加载完整模型
  • 需要提高推理吞吐量
  • 需要降低单次推理延迟
  • 多用户并发请求场景
  • 批量数据处理场景

不适用于以下场景:

  • 模型可以放入单张 GPU(优先使用单 GPU)
  • 对延迟要求极高(多 GPU 会增加通信开销)
  • GPU 之间带宽低(如 PCIe 3.0 x8)

核心知识点

大模型显存占用估算

模型显存占用主要包括:

  1. 模型参数:参数量 × 精度字节数
  2. 激活值(Activations):前向传播中间结果
  3. KV Cache:自回归生成时的缓存
  4. 梯度和优化器状态:训练时需要,推理时不需要

显存估算公式(推理):

   总显存 ≈ 模型参数显存 + KV Cache 显存 + 激活值显存 + 框架开销

模型参数显存

   模型参数显存 = 参数量 × 精度字节数

精度字节数:
- FP32: 4 字节
- FP16/BF16: 2 字节
- INT8: 1 字节
- INT4: 0.5 字节

示例:

  • LLaMA 70B FP16:70B × 2 = 140GB
  • LLaMA 70B INT8:70B × 1 = 70GB
  • LLaMA 70B INT4:70B × 0.5 = 35GB

KV Cache 显存

   KV Cache 显存 = 2 × 层数 × 隐藏维度 × 序列长度 × batch_size × 精度字节数

2:K 和 V 两个矩阵

示例:

  • LLaMA 70B(80 层,8192 隐藏维度)
  • 序列长度 2048,batch_size 1,FP16
  • KV Cache = 2 × 80 × 8192 × 2048 × 1 × 2 ≈ 5GB

多 GPU 并行策略

数据并行(Data Parallelism, DP)

  • 每张 GPU 加载完整模型
  • 不同 GPU 处理不同数据
  • 适用于模型可以放入单张 GPU 的情况
  • 推理场景使用较少

张量并行(Tensor Parallelism, TP)

  • 将模型的每一层切分到多张 GPU
  • 层内并行,通信频繁
  • 适合 GPU 间带宽高的场景(NVLink、NVSwitch)
  • 典型框架:Megatron-LM、vLLM

流水线并行(Pipeline Parallelism, PP)

  • 将模型按层切分到多张 GPU
  • 层间并行,通信较少
  • 存在 pipeline bubble(空闲时间)
  • 典型框架:GPipe、PipeDream

混合并行

  • 结合 TP 和 PP
  • 适合超大模型和多机多卡
  • 配置复杂,但性能最优

GPU 互连拓扑

NVLink

  • NVIDIA GPU 专有高速互连
  • 带宽:300-900 GB/s(根据代数)
  • 延迟:低
  • 适合 TP

PCIe

  • 通用接口
  • 带宽:PCIe 4.0 x16 = 32 GB/s,PCIe 3.0 x16 = 16 GB/s
  • 延迟:较高
  • 适合 PP 或不频繁通信的 TP

NVSwitch

  • NVIDIA 高速交换机
  • 所有 GPU 全互连
  • 适合大规模 TP

查看 GPU 拓扑:

   bashnvidia-smi topo -m

预期输出:

           GPU0    GPU1    GPU2    GPU3    mlx5_0  CPU Affinity    NUMA Affinity
GPU0     X      NV12    NV12    NV12    SYS     0-31            0
GPU1    NV12     X      NV12    NV12    SYS     0-31            0
GPU2    NV12    NV12     X      NV12    SYS     0-31            0
GPU3    NV12    NV12    NV12     X      SYS     0-31            0

Legend:
  X    = Self
  SYS  = Connection traversing PCIe as well as the SMP interconnect between NUMA nodes (e.g., QPI/UPI)
  NODE = Connection traversing PCIe as well as the interconnect between PCIe Host Bridges within a NUMA node
  PHB  = Connection traversing PCIe as well as a PCIe Host Bridge (typically the CPU)
  PXB  = Connection traversing multiple PCIe bridges (without traversing the PCIe Host Bridge)
  PIX  = Connection traversing at most a single PCIe bridge
  NV#  = Connection traversing a bonded set of # NVLinks

判断:

  • NV12:NVLink 连接,12 条 NVLink 链路,带宽高
  • SYS:PCIe + CPU 互连,带宽低
  • PHB:PCIe 主桥,带宽中等

推理框架选择

Transformers(HuggingFace)

  • 优点:简单易用,模型丰富
  • 缺点:推理性能一般,多 GPU 支持有限
  • 适合:快速验证、小模型

vLLM

  • 优点:推理性能高,PagedAttention 优化,支持 TP
  • 缺点:模型支持有限
  • 适合:生产环境、大模型、多用户并发

TensorRT-LLM

  • 优点:推理性能最高,支持 TP 和 PP
  • 缺点:配置复杂,编译耗时
  • 适合:性能要求极高、NVIDIA GPU

DeepSpeed-Inference

  • 优点:支持 TP 和 PP,配置灵活
  • 缺点:配置复杂
  • 适合:大模型、混合并行

Megatron-LM

  • 优点:TP 性能好
  • 缺点:主要用于训练,推理支持有限
  • 适合:研究、自定义推理

实战步骤

第一步:环境准备

目的:准备多 GPU 推理环境。

1.1 检查 GPU 信息

   bash# 查看 GPU 数量和型号
nvidia-smi

# 查看 GPU 拓扑
nvidia-smi topo -m

# 查看 CUDA 版本
nvcc --version

# 查看驱动版本
nvidia-smi | grep "Driver Version"

预期输出(4 卡示例):

   +-----------------------------------------------------------------------------+
| NVIDIA-SMI 535.104.05   Driver Version: 535.104.05   CUDA Version: 12.2    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA A100-SXM...  On   | 00000000:00:04.0 Off |                    0 |
| N/A   30C    P0    53W / 400W |      0MiB / 81920MiB |      0%      Default |
|                               |                      |             Disabled |
+-------------------------------+----------------------+----------------------+
|   1  NVIDIA A100-SXM...  On   | 00000000:00:05.0 Off |                    0 |
| N/A   31C    P0    54W / 400W |      0MiB / 81920MiB |      0%      Default |
|                               |                      |             Disabled |
+-------------------------------+----------------------+----------------------+
|   2  NVIDIA A100-SXM...  On   | 00000000:00:06.0 Off |                    0 |
| N/A   30C    P0    53W / 400W |      0MiB / 81920MiB |      0%      Default |
|                               |                      |             Disabled |
+-------------------------------+----------------------+----------------------+
|   3  NVIDIA A100-SXM...  On   | 00000000:00:07.0 Off |                    0 |
| N/A   31C    P0    54W / 400W |      0MiB / 81920MiB |      0%      Default |
|                               |                      |             Disabled |
+-------------------------------+----------------------+----------------------+

1.2 安装依赖

   bash# 创建虚拟环境
conda create -n llm python=3.10
conda activate llm

# 安装 PyTorch(根据 CUDA 版本选择)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

# 验证 PyTorch 和 CUDA
python -c "import torch; print(torch.__version__); print(torch.cuda.is_available()); print(torch.cuda.device_count())"

# 应该输出:
# 2.1.0+cu121
# True
# 4

1.3 下载模型

   bash# 使用 HuggingFace CLI 下载
pip install huggingface_hub

# 下载模型(以 LLaMA 70B 为例)
huggingface-cli download meta-llama/Llama-2-70b-hf --local-dir ./models/llama-2-70b

# 或使用 git clone
git lfs install
git clone https://huggingface.co/meta-llama/Llama-2-70b-hf ./models/llama-2-70b

第二步:使用 Transformers + Accelerate

目的:使用 Accelerate 实现简单的多 GPU 推理。

2.1 安装 Accelerate

   bashpip install transformers accelerate

2.2 编写推理代码

   python# multi_gpu_inference.py

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from accelerate import init_empty_weights, load_checkpoint_and_dispatch

# 模型路径
model_path = "./models/llama-2-70b"

# 加载 tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_path)

# 使用 accelerate 加载模型到多 GPU
# device_map="auto" 会自动分配模型到多张 GPU
model = AutoModelForCausalLM.from_pretrained(
    model_path,
    torch_dtype=torch.float16,  # 使用 FP16 减少显存
    device_map="auto",          # 自动分配到多 GPU
    low_cpu_mem_usage=True,     # 减少 CPU 内存占用
)

print(f"模型已加载到设备: {model.hf_device_map}")

# 推理
prompt = "What is the capital of France?"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda:0")

with torch.no_grad():
    outputs = model.generate(
        **inputs,
        max_new_tokens=100,
        temperature=0.7,
        top_p=0.9,
        do_sample=True,
    )

response = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(f"Response: {response}")

2.3 运行推理

   bashpython multi_gpu_inference.py

预期输出:

   模型已加载到设备: {'model.embed_tokens': 0, 'model.layers.0': 0, 'model.layers.1': 0, ..., 'model.layers.79': 3, 'model.norm': 3, 'lm_head': 3}
Response: What is the capital of France? The capital of France is Paris...

2.4 查看显存占用

   bash# 运行推理时,在另一个终端执行
nvidia-smi

# 应该看到模型分布在多张 GPU 上
# 每张 GPU 的显存占用大致相同

2.5 自定义设备分配

如果自动分配不理想,可以手动指定:

   python# 手动指定 device_map
device_map = {
    "model.embed_tokens": 0,
    "model.layers.0": 0,
    "model.layers.1": 0,
    # ... 前 20 层放在 GPU 0
    "model.layers.20": 1,
    "model.layers.21": 1,
    # ... 21-40 层放在 GPU 1
    "model.layers.40": 2,
    "model.layers.41": 2,
    # ... 41-60 层放在 GPU 2
    "model.layers.60": 3,
    "model.layers.61": 3,
    # ... 61-79 层放在 GPU 3
    "model.norm": 3,
    "lm_head": 3,
}

model = AutoModelForCausalLM.from_pretrained(
    model_path,
    torch_dtype=torch.float16,
    device_map=device_map,
    low_cpu_mem_usage=True,
)

第三步:使用 vLLM

目的:使用 vLLM 实现高性能多 GPU 推理。

3.1 安装 vLLM

   bash# 从 PyPI 安装
pip install vllm

# 或从源码安装(支持更多特性)
git clone https://github.com/vllm-project/vllm.git
cd vllm
pip install -e .

3.2 启动 vLLM 服务(TP 模式)

   bash# 使用张量并行(TP)启动 vLLM
# --tensor-parallel-size 指定 TP 并行度

python -m vllm.entrypoints.openai.api_server \
    --model ./models/llama-2-70b \
    --tensor-parallel-size 4 \
    --dtype float16 \
    --max-model-len 4096 \
    --port 8000

参数说明:

  • --model:模型路径
  • --tensor-parallel-size:TP 并行度(GPU 数量)
  • --dtype:数据类型(float16、bfloat16)
  • --max-model-len:最大序列长度
  • --port:服务端口

预期输出:

   INFO:     Started server process [12345]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000

3.3 测试 vLLM 服务

   bash# 使用 curl 测试
curl http://localhost:8000/v1/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "./models/llama-2-70b",
        "prompt": "What is the capital of France?",
        "max_tokens": 100,
        "temperature": 0.7
    }'

或使用 Python 客户端:

   pythonimport requests

url = "http://localhost:8000/v1/completions"
data = {
    "model": "./models/llama-2-70b",
    "prompt": "What is the capital of France?",
    "max_tokens": 100,
    "temperature": 0.7,
}

response = requests.post(url, json=data)
print(response.json()["choices"][0]["text"])

3.4 使用 OpenAI 客户端

vLLM 兼容 OpenAI API,可以直接使用 OpenAI 客户端:

   pythonfrom openai import OpenAI

client = OpenAI(
    base_url="http://localhost:8000/v1",
    api_key="dummy",  # vLLM 不需要真实 API key
)

response = client.completions.create(
    model="./models/llama-2-70b",
    prompt="What is the capital of France?",
    max_tokens=100,
    temperature=0.7,
)

print(response.choices[0].text)

3.5 性能优化

vLLM 支持多种优化:

   bash# 启用 PagedAttention(默认启用)
python -m vllm.entrypoints.openai.api_server \
    --model ./models/llama-2-70b \
    --tensor-parallel-size 4 \
    --dtype float16 \
    --max-model-len 4096 \
    --gpu-memory-utilization 0.9 \
    --max-num-seqs 256 \
    --port 8000

参数说明:

  • --gpu-memory-utilization:GPU 显存利用率(0-1),默认 0.9
  • --max-num-seqs:最大并发序列数,影响吞吐量

第四步:使用 DeepSpeed-Inference

目的:使用 DeepSpeed 实现灵活的多 GPU 推理。

4.1 安装 DeepSpeed

   bashpip install deepspeed

4.2 编写推理代码

   python# deepspeed_inference.py

import torch
import deepspeed
from transformers import AutoModelForCausalLM, AutoTokenizer

# 模型路径
model_path = "./models/llama-2-70b"

# 加载 tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_path)

# 加载模型
model = AutoModelForCausalLM.from_pretrained(
    model_path,
    torch_dtype=torch.float16,
)

# 使用 DeepSpeed 初始化推理引擎
ds_engine = deepspeed.init_inference(
    model,
    mp_size=4,              # 模型并行大小(GPU 数量)
    dtype=torch.float16,    # 数据类型
    replace_with_kernel_inject=True,  # 使用 DeepSpeed 优化 kernel
)

model = ds_engine.module

# 推理
prompt = "What is the capital of France?"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")

with torch.no_grad():
    outputs = model.generate(
        **inputs,
        max_new_tokens=100,
        temperature=0.7,
        top_p=0.9,
        do_sample=True,
    )

response = tokenizer.decode(outputs[0], skip_special_tokens=True)
print(f"Response: {response}")

4.3 运行推理

   bash# 使用 deepspeed 启动
deepspeed --num_gpus 4 deepspeed_inference.py

第五步:量化优化

目的:使用量化减少显存占用。

5.1 使用 GPTQ 量化

   bash# 安装 GPTQ
pip install auto-gptq

# 下载量化后的模型
huggingface-cli download TheBloke/Llama-2-70B-GPTQ --local-dir ./models/llama-2-70b-gptq

使用量化模型:

   pythonfrom transformers import AutoModelForCausalLM, AutoTokenizer

model_path = "./models/llama-2-70b-gptq"

tokenizer = AutoTokenizer.from_pretrained(model_path)

model = AutoModelForCausalLM.from_pretrained(
    model_path,
    device_map="auto",
    trust_remote_code=False,
    revision="main"
)

# 推理代码同前

5.2 使用 AWQ 量化

   bash# 安装 AWQ
pip install autoawq

# 下载量化后的模型
huggingface-cli download TheBloke/Llama-2-70B-AWQ --local-dir ./models/llama-2-70b-awq

使用量化模型:

   pythonfrom awq import AutoAWQForCausalLM
from transformers import AutoTokenizer

model_path = "./models/llama-2-70b-awq"

tokenizer = AutoTokenizer.from_pretrained(model_path)

model = AutoAWQForCausalLM.from_quantized(
    model_path,
    fuse_layers=True,
    device_map="auto",
)

# 推理代码同前

5.3 使用 bitsandbytes 量化

   bashpip install bitsandbytes
   pythonfrom transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig

model_path = "./models/llama-2-70b"

tokenizer = AutoTokenizer.from_pretrained(model_path)

# 4-bit 量化配置
quantization_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_compute_dtype=torch.float16,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4"
)

model = AutoModelForCausalLM.from_pretrained(
    model_path,
    quantization_config=quantization_config,
    device_map="auto",
)

# 推理代码同前

量化效果对比:

量化方式精度显存占用性能准确性
FP1616-bit100%基准100%
INT88-bit50%略慢99%+
INT4 (GPTQ)4-bit25%较慢95%+
INT4 (AWQ)4-bit25%较快97%+

第六步:性能测试和优化

目的:测试多 GPU 推理性能,找到瓶颈。

6.1 测试吞吐量

   python# benchmark_throughput.py

import time
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

model_path = "./models/llama-2-70b"

tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(
    model_path,
    torch_dtype=torch.float16,
    device_map="auto",
)

# 准备测试数据
prompts = ["What is the capital of France?"] * 100

# 预热
for _ in range(5):
    inputs = tokenizer(prompts[0], return_tensors="pt").to("cuda")
    model.generate(**inputs, max_new_tokens=50)

# 测试吞吐量
start_time = time.time()
total_tokens = 0

for prompt in prompts:
    inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
    with torch.no_grad():
        outputs = model.generate(**inputs, max_new_tokens=50)
    total_tokens += outputs.shape[1]

end_time = time.time()
elapsed_time = end_time - start_time

throughput = total_tokens / elapsed_time
print(f"吞吐量: {throughput:.2f} tokens/second")
print(f"总时间: {elapsed_time:.2f} seconds")

6.2 测试延迟

   python# benchmark_latency.py

import time
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

model_path = "./models/llama-2-70b"

tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(
    model_path,
    torch_dtype=torch.float16,
    device_map="auto",
)

prompt = "What is the capital of France?"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")

# 预热
for _ in range(5):
    model.generate(**inputs, max_new_tokens=50)

# 测试延迟
latencies = []
for _ in range(100):
    start_time = time.time()
    with torch.no_grad():
        outputs = model.generate(**inputs, max_new_tokens=50)
    end_time = time.time()
    latencies.append((end_time - start_time) * 1000)  # 转换为毫秒

print(f"平均延迟: {sum(latencies) / len(latencies):.2f} ms")
print(f"P50 延迟: {sorted(latencies)[len(latencies) // 2]:.2f} ms")
print(f"P95 延迟: {sorted(latencies)[int(len(latencies) * 0.95)]:.2f} ms")
print(f"P99 延迟: {sorted(latencies)[int(len(latencies) * 0.99)]:.2f} ms")

6.3 监控 GPU 使用率

   bash# 实时监控 GPU 使用率
nvidia-smi dmon -s u -d 1

# 或使用 nvtop
nvtop

# 或使用 gpustat
pip install gpustat
watch -n 1 gpustat

6.4 分析瓶颈

常见瓶颈:

显存瓶颈

  • 现象:OOM(Out of Memory)错误
  • 解决:降低 batch size、使用量化、增加 GPU 数量

计算瓶颈

  • 现象:GPU 利用率高(>90%)
  • 解决:优化模型结构、使用更强的 GPU

通信瓶颈

  • 现象:GPU 利用率低,但多 GPU 推理比单 GPU 慢
  • 解决:优化 TP 配置、使用 NVLink、减少通信

I/O 瓶颈

  • 现象:GPU 利用率低,CPU 利用率高
  • 解决:增加数据预处理线程、使用更快的存储

第七步:生产环境部署

目的:将多 GPU 推理服务部署到生产环境。

7.1 使用 Docker 部署

   dockerfile# Dockerfile

FROM nvidia/cuda:12.1.0-cudnn8-runtime-ubuntu22.04

# 安装依赖
RUN apt-get update && apt-get install -y \
    python3.10 \
    python3-pip \
    git \
    && rm -rf /var/lib/apt/lists/*

# 安装 Python 依赖
RUN pip3 install --no-cache-dir \
    torch \
    transformers \
    accelerate \
    vllm

# 复制模型和代码
WORKDIR /app
COPY models/ /app/models/
COPY inference.py /app/

# 暴露端口
EXPOSE 8000

# 启动命令
CMD ["python3", "-m", "vllm.entrypoints.openai.api_server", \
     "--model", "/app/models/llama-2-70b", \
     "--tensor-parallel-size", "4", \
     "--dtype", "float16", \
     "--port", "8000"]

构建和运行:

   bash# 构建镜像
docker build -t llm-inference:latest .

# 运行容器
docker run --gpus all \
    -p 8000:8000 \
    llm-inference:latest

7.2 使用 Kubernetes 部署

   yaml# llm-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: llm-inference
spec:
  replicas: 1
  selector:
    matchLabels:
      app: llm-inference
  template:
    metadata:
      labels:
        app: llm-inference
    spec:
      containers:
      - name: llm
        image: llm-inference:latest
        ports:
        - containerPort: 8000
        resources:
          limits:
            nvidia.com/gpu: 4  # 请求 4 张 GPU
        env:
        - name: CUDA_VISIBLE_DEVICES
          value: "0,1,2,3"
---
apiVersion: v1
kind: Service
metadata:
  name: llm-inference
spec:
  selector:
    app: llm-inference
  ports:
  - protocol: TCP
    port: 8000
    targetPort: 8000
  type: LoadBalancer

部署:

   bashkubectl apply -f llm-deployment.yaml

7.3 负载均衡和自动扩缩容

   yaml# hpa.yaml(Horizontal Pod Autoscaler)

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: llm-inference-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: llm-inference
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 80

7.4 监控和日志

使用 Prometheus 和 Grafana 监控:

   yaml# prometheus-config.yaml

scrape_configs:
  - job_name: 'llm-inference'
    static_configs:
    - targets: ['llm-inference:8000']

使用 ELK 或 Loki 收集日志。

常用命令

GPU 管理

   bash# 查看 GPU 信息
nvidia-smi

# 查看 GPU 拓扑
nvidia-smi topo -m

# 实时监控 GPU
nvidia-smi dmon -s u -d 1

# 查看 GPU 进程
nvidia-smi pmon

# 设置可见 GPU
export CUDA_VISIBLE_DEVICES=0,1,2,3

模型管理

   bash# 下载模型
huggingface-cli download model_name --local-dir ./models/model_name

# 查看模型信息
python -c "from transformers import AutoConfig; print(AutoConfig.from_pretrained('./models/model_name'))"

# 查看模型大小
du -sh ./models/model_name

性能测试

   bash# 测试吞吐量
python benchmark_throughput.py

# 测试延迟
python benchmark_latency.py

# 使用 vLLM benchmark
python -m vllm.entrypoints.openai.api_server \
    --model ./models/llama-2-70b \
    --tensor-parallel-size 4 \
    --benchmark

配置示例

完整配置示例已在实战步骤中给出。

风险提醒

高风险操作

OOM(显存溢出)

  • 风险:进程崩溃
  • 原因:模型太大、batch size 太大、KV cache 太大
  • 解决:降低 batch size、使用量化、增加 GPU 数量

多进程冲突

  • 风险:GPU 资源竞争
  • 原因:多个进程同时使用同一张 GPU
  • 解决:设置 CUDA_VISIBLE_DEVICES,确保进程隔离

通信开销过大

  • 风险:推理延迟增加
  • 原因:GPU 间带宽低、TP 并行度过高
  • 解决:使用 NVLink、降低 TP 并行度、使用 PP

模型损坏

  • 风险:推理结果错误
  • 原因:模型文件下载不完整、权重加载错误
  • 解决:验证模型 checksum、重新下载模型

常见误区

误区 1:GPU 数量越多越好

多 GPU 会增加通信开销,不一定更快。需要根据模型大小和 GPU 拓扑选择合适的并行度。

误区 2:TP 并行度等于 GPU 数量

TP 并行度应该是 GPU 数量的约数,且优先选择 2、4、8 等 2 的幂次。

误区 3:量化没有精度损失

量化会有一定精度损失,需要在显存和精度之间权衡。

误区 4:batch size 越大越好

batch size 过大会占用过多显存,导致 OOM。需要根据显存和性能需求调整。

验证方式

验证模型加载

   pythonimport torch
from transformers import AutoModelForCausalLM

model = AutoModelForCausalLM.from_pretrained(
    "./models/llama-2-70b",
    torch_dtype=torch.float16,
    device_map="auto",
)

print(f"模型设备分布: {model.hf_device_map}")

验证推理结果

   python# 使用已知输入测试
prompt = "1 + 1 ="
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens=5)
response = tokenizer.decode(outputs[0], skip_special_tokens=True)

print(f"Response: {response}")
# 应该输出: 1 + 1 = 2

验证性能

   bash# 测试吞吐量
python benchmark_throughput.py

# 应该达到预期吞吐量(根据模型和 GPU)

回滚方案

回滚到单 GPU

   python# 设置使用单张 GPU
export CUDA_VISIBLE_DEVICES=0

# 或在代码中设置
model = AutoModelForCausalLM.from_pretrained(
    model_path,
    torch_dtype=torch.float16,
    device_map={"": 0},  # 强制使用 GPU 0
)

回滚量化

   python# 使用 FP16 模型
model = AutoModelForCausalLM.from_pretrained(
    model_path,
    torch_dtype=torch.float16,
    device_map="auto",
)

生产环境注意事项

资源规划

  • 根据模型大小和 QPS 规划 GPU 数量
  • 预留显存空间用于 KV cache
  • 监控 GPU 利用率,避免资源浪费

高可用

  • 部署多个副本
  • 使用负载均衡
  • 配置健康检查和自动重启

监控告警

  • 监控 GPU 使用率、显存使用率
  • 监控推理延迟、吞吐量
  • 监控错误率、OOM 次数

成本优化

  • 使用 Spot 实例(云服务器)
  • 使用量化减少 GPU 数量
  • 使用批处理提高吞吐量

总结

单张 GPU 显存不足时,多 GPU 推理是唯一选择。

关键技术:

  • 张量并行(TP):层内并行,通信频繁,适合 NVLink
  • 流水线并行(PP):层间并行,通信较少,适合 PCIe
  • 混合并行:结合 TP 和 PP,适合超大模型

框架选择:

  • Transformers + Accelerate:简单易用,适合快速验证
  • vLLM:高性能,适合生产环境
  • DeepSpeed-Inference:灵活配置,适合大模型
  • TensorRT-LLM:极致性能,适合 NVIDIA GPU

优化方向:

  • 量化(INT8、INT4)减少显存
  • PagedAttention 优化 KV cache
  • Flash Attention 优化注意力计算
  • Continuous Batching 提高吞吐量

多 GPU 推理不是简单的资源叠加,需要根据模型特点、GPU 拓扑、业务需求选择合适的并行策略和框架,才能实现最优性能。

文末福利

2026 年 AI 大模型已经成为IT人求职核心加分项,不管传统后端、前端,还是其它IT岗,掌握 AI大模型都能大幅拓宽求职赛道、拉高薪资上限。今天分享一份特别详细的AI大模型学习路线图,供你学习参考。

图片

想获取高清大图,可以扫下方二维码,备注:AI大模型学习路线图。

单张 GPU 放不下模型时,如何部署多 GPU 推理插图1

本文链接:https://www.yunweipai.com/archives/49377

网友评论comments

发表回复

您的电子邮箱地址不会被公开。

暂无评论

Copyright © 2012-2022 YUNWEIPAI.COM - 运维派 京ICP备16064699号-6
扫二维码
扫二维码
返回顶部