deepspeed/vllm底层原理
DeepSpeed 聚焦于大模型高效训练(同时支持推理优化),通过分布式技术突破训练的显存、算力瓶颈;
vLLM 专注于大模型高吞吐、低延迟推理,核心解决推理阶段的显存利用率和请求处理效率问题。
一、DeepSpeed 底层原理
DeepSpeed 是微软推出的分布式训练 / 推理框架,核心目标是让超大模型(千亿、万亿参数)的训练变得可行,其底层核心围绕分布式训练技术和显存优化技术。
1. 核心:分布式训练技术(模型并行 + 数据并行)
2. 关键显存优化技术
3. 其他核心能力
二、vLLM 底层原理
1. 核心创新:PagedAttention(分页注意力机制)
2. 关键支撑:Continuous Batching(连续批处理)
3. 其他优化技术
三、总结
四、deepspeed运行
1.deepspeed启动
deepspeed 启动器(CLI 前端)是 DeepSpeed 框架提供的分布式训练入口,负责统筹分布式环境的初始化和资源调度。
# 多节点运行 deepspeed --num_nodes 2 --num_gpus 8 --master_addr 192.168.1.100 --master_port 29500 train_qwen_32b.py
1) --num_gpus:指定单节点 GPU 数量
2) --num_nodes:指定分布式训练的总节点数
3)--master_addr:指定主节点(master node)的 IP 地址
4) --master_port:指定主节点的通信端口
2. 底层工作流程
1)启动器解析参数:
deepspeed 启动器首先解析 num_nodes、num_gpus、master_addr、master_port,计算总进程数,确认节点角色(主 / 从);
2)启动节点进程:
在每个节点上,启动器为 num_gpus 个 GPU 分别启动一个 train_qwen_32b.py 进程,并为每个进程分配唯一的 rank(全局进程编号)和 local_rank(节点内进程编号);
3)传递参数给 PyTorch 后端:
启动器将 master_addr、master_port、rank、world_size(总进程数,即 num_nodes×num_gpus)传递给 torch.distributed.init_process_group() 函数(该函数是 PyTorch 分布式初始化的核心,你的训练脚本中无需手动调用,DeepSpeed 已自动集成);
4)建立分布式通信:
torch.distributed 基于上述参数,通过 NCCL(GPU 分布式首选后端)建立跨节点、多 GPU 的进程通信组,后续训练中的梯度同步、模型参数并行等操作均基于该通信组完成;
5)DeepSpeed 利用配置:
DeepSpeed 框架内部会读取这些分布式参数,结合 deepspeed_config.json 中的 ZeRO 配置,完成模型参数、优化器状态的分布式拆分与调度。
3.补充说明
import torch.distributed as dist # 初始化后(DeepSpeed 已自动完成初始化) rank = dist.get_rank() # 全局进程编号 world_size = dist.get_world_size() # 总进程数 local_rank = int(os.environ.get("LOCAL_RANK", 0)) # 节点内 GPU 编号
五、deepspeed示例
lora训练train_qwen_32b模型 ,train_qwen_32b.py
# # 1. 安装 PyTorch(推荐对应 CUDA 版本,示例为 CUDA 11.8) # pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # # # 2. 安装 DeepSpeed(最新稳定版) # pip install deepspeed # # # 3. 安装模型相关依赖(Hugging Face 生态) # pip install transformers==4.36.2 datasets==2.14.6 accelerate==0.25.0 sentencepiece==0.1.99 protobuf==4.25.1 # pip install tokenizers==0.14.1 peft==0.7.1 # peft 用于高效微调(可选,如 LoRA) import os import torch from datasets import load_dataset from transformers import ( AutoTokenizer, AutoModelForCausalLM, TrainingArguments, Trainer, DataCollatorForLanguageModeling, default_data_collator ) import deepspeed from peft import LoraConfig, get_peft_model, PeftModel # LoRA 相关(可选) # ====================== 1. 基础配置(可根据需求修改) ====================== class Config: # 模型路径(Hugging Face 本地路径或远程仓库,如 Qwen/Qwen-32B) model_name_or_path = "/path/to/local/Qwen-32B" # 数据路径(本地json文件或huggingface数据集名称) data_path = "/path/to/train_data.json" # 输出路径(模型、日志、checkpoint 保存目录) output_dir = "./qwen-32b-deepspeed-training" # 训练参数 per_device_train_batch_size = 1 # 单卡批次大小(根据显存调整) gradient_accumulation_steps = 16 # 梯度累积步数(弥补单卡批次小的问题) num_train_epochs = 3 # 训练轮数 learning_rate = 2e-5 # 学习率 weight_decay = 0.01 # 权重衰减 logging_steps = 10 # 日志打印步数 save_steps = 100 # 模型保存步数 fp16 = True # 开启混合精度训练(降低显存占用) # DeepSpeed 配置文件路径 deepspeed_config_path = "./deepspeed_config.json" # LoRA 配置(启用后为 LoRA 微调,关闭则为全参数微调) use_lora = True lora_rank = 8 lora_alpha = 16 lora_dropout = 0.05 # ====================== 2. 数据预处理 ====================== def preprocess_data(tokenizer, config): # 加载数据集(支持本地json,格式为 [{"text": "训练文本1"}, {"text": "训练文本2"}, ...]) dataset = load_dataset("json", data_files=config.data_path)["train"] # 文本编码函数 def encode_function(examples): # 对文本进行编码,截断最长序列(Qwen 最大序列长度通常为 2048/4096) inputs = tokenizer( examples["text"], truncation=True, max_length=2048, padding=False, return_tensors="pt" ) # 因果语言模型的标签与输入一致 inputs["labels"] = inputs["input_ids"].clone() return inputs # 批量处理数据集(num_proc 为进程数,根据CPU核心数调整) encoded_dataset = dataset.map( encode_function, batched=True, num_proc=8, remove_columns=dataset.column_names, # 删除原始文本列,只保留编码后的列 load_from_cache_file=False ) # 划分训练集和验证集(按 9:1 划分) encoded_dataset = encoded_dataset.train_test_split(test_size=0.1, seed=42) return encoded_dataset["train"], encoded_dataset["test"] # ====================== 3. 模型与Tokenizer加载 ====================== def load_model_and_tokenizer(config): # 加载 Tokenizer(Qwen 使用 sentencepiece 分词,需开启 padding_side) tokenizer = AutoTokenizer.from_pretrained( config.model_name_or_path, trust_remote_code=True, # Qwen 需开启该参数 padding_side="right" # 右填充,适配因果语言模型 ) # 设置 pad_token(若未设置,默认使用 eos_token) if tokenizer.pad_token is None: tokenizer.pad_token = tokenizer.eos_token # 加载 Qwen-32B 模型 model = AutoModelForCausalLM.from_pretrained( config.model_name_or_path, trust_remote_code=True, torch_dtype=torch.float16, # 使用 FP16 精度加载模型,降低显存 device_map="auto", # 自动分配模型到 GPU/CPU low_cpu_mem_usage=True # 降低 CPU 内存占用 ) # 启用 LoRA 微调(可选,大幅降低显存占用) if config.use_lora: lora_config = LoraConfig( r=config.lora_rank, lora_alpha=config.lora_alpha, target_modules=["q_proj", "k_proj", "v_proj", "o_proj"], # Qwen 注意力层目标模块 lora_dropout=config.lora_dropout, bias="none", task_type="CAUSAL_LM" ) model = get_peft_model(model, lora_config) # 打印 LoRA 可训练参数占比 model.print_trainable_parameters() return model, tokenizer # ====================== 4. 训练主函数 ====================== def main(): # 加载配置 config = Config() # 创建输出目录 os.makedirs(config.output_dir, exist_ok=True) # 加载模型和 Tokenizer model, tokenizer = load_model_and_tokenizer(config) # 数据预处理 train_dataset, val_dataset = preprocess_data(tokenizer, config) # 数据拼接器(用于批量拼接数据,填充到批次最大长度) if config.use_lora: data_collator = default_data_collator else: data_collator = DataCollatorForLanguageModeling( tokenizer=tokenizer, mlm=False, # 因果语言模型关闭 MLM(掩码语言模型) ) # 定义训练参数 training_args = TrainingArguments( output_dir=config.output_dir, per_device_train_batch_size=config.per_device_train_batch_size, gradient_accumulation_steps=config.gradient_accumulation_steps, num_train_epochs=config.num_train_epochs, learning_rate=config.learning_rate, weight_decay=config.weight_decay, logging_steps=config.logging_steps, save_steps=config.save_steps, fp16=config.fp16, save_total_limit=3, # 最多保存 3 个 checkpoint evaluation_strategy="steps", # 按步数进行验证 eval_steps=config.save_steps, # 每 save_steps 步验证一次 load_best_model_at_end=True, # 训练结束后加载最优模型 deepspeed=config.deepspeed_config_path, # 指定 DeepSpeed 配置文件 remove_unused_columns=False, report_to="none", # 关闭 wandb 日志(如需开启,可改为 "wandb") seed=42, ) # 初始化 Trainer trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=val_dataset, data_collator=data_collator, tokenizer=tokenizer, ) # 开始训练 print("===== 开始训练 Qwen-32B 模型 =====") trainer.train() # 保存最终模型 print("===== 训练完成,保存最终模型 =====") trainer.save_model(os.path.join(config.output_dir, "final_model")) tokenizer.save_pretrained(os.path.join(config.output_dir, "final_model")) if __name__ == "__main__": main()
deepspeed_config.json文件
{ "train_batch_size": 16, "train_micro_batch_size_per_gpu": 1, "gradient_accumulation_steps": 16, "fp16": { "enabled": true, "loss_scale": 0, "loss_scale_window": 1000, "initial_scale_power": 16, "hysteresis": 2, "min_loss_scale": 1 }, "zero_optimization": { "stage": 2, "allgather_partitions": true, "allgather_bucket_size": 5e8, "overlap_comm": true, "reduce_scatter": true, "reduce_bucket_size": 5e8, "contiguous_gradients": true }, "optimizer": { "type": "AdamW", "params": { "lr": 2e-5, "betas": [0.9, 0.999], "eps": 1e-8, "weight_decay": 0.01 } }, "scheduler": { "type": "WarmupLR", "params": { "warmup_min_lr": 0, "warmup_max_lr": 2e-5, "warmup_num_steps": 1000 } }, "gradient_clipping": 1.0, "steps_per_print": 10, "wall_clock_breakdown": false }
六、deepspeed和llama factory相辅相成
实际生产和科研中,LLaMA Factory 常作为上层调参入口,DeepSpeed 作为底层硬件优化引擎,二者协同使用
比如LLaMA-Factory中的 Chat Template:
不同大模型在官方预训练或微调阶段,使用了各自固定的对话文本格式(即原生 Chat Template),这种格式是模型 “熟悉” 的输入输出范式。
Chat Template 针对不同模型差异化设计的核心作用,是让训练数据的格式与模型原生预训练 / 微调格式保持一致。
LLaMA Factory 作为一站式微调工具,LLaMA Factory 已经预先内置了主流大模型与其专属 Chat Template 的对应关系,用户无需手动编写模板。当用户选择某个模型(如通过命令行 --model_name_or_path Qwen/Qwen-7B-Chat 或 Web UI 选择模型)时,LLaMA Factory 会自动识别模型类型,并加载对应的预设 Chat Template。LLaMA Factory 也支持用户根据需求自定义 Chat Template(适配小众模型或特殊训练场景)。用户可以通过配置文件或命令行参数,指定自定义的模板格式,覆盖内置模板的默认行为。
LLaMA 3 原生模板(Meta 官方定义,包含特殊标记 <|begin_of_text|>、<|user|>、<|assistant|>):
<|begin_of_text|><|user|>你好<|end_of_text|><|assistant|>您好,请问有什么可以帮到您?<|end_of_text|>
Qwen 原生模板(通义千问官方定义,标记更简洁):
用户:你好
助手:您好,请问有什么可以帮到您?
ChatGLM 原生模板(智谱 AI 定义,适配中文对话场景):
<|user|>你好<|assistant|>您好,请问有什么可以帮到您?

浙公网安备 33010602011771号