| 规模 | 参数量 | 显存需求(FP16) | 典型代表 | 适用场景 |
|---|---|---|---|---|
| 小模型 | 1B - 7B | 2 - 14 GB | LLaMA-2-7B, Qwen-7B | 边缘设备、单卡推理、实时对话 |
| 中模型 | 13B - 30B | 26 - 60 GB | LLaMA-2-13B, Baichuan-13B | 企业级应用、复杂推理 |
| 大模型 | 65B - 72B | 130 - 144 GB | LLaMA-2-70B, DeepSeek-67B | 高精度任务、研究探索 |
| 超大模型 | 100B+ | 200 GB+ | GPT-4(估计 1.8T), PaLM-540B | 通用人工智能、多模态 |
关键认知:
展开代码# 决策框架:在满足质量的前提下,选最小的模型 def select_model(requirements): if latency < 100ms and device == "mobile": return "1B-4B INT4量化" # 端侧优先 if concurrency > 1000 and task == "简单分类": return "7B FP16" # 吞吐优先 if task in ["代码生成", "数学推理", "长文档分析"]: return "13B-72B" # 质量优先 if budget == "unlimited" and research == True: return "72B+ 或 MoE" # 探索性任务 return "7B-13B 性价比最优" # 默认选择
| 精度 | 每参数字节 | 相对速度 | 相对显存 | 质量损失 | 适用场景 |
|---|---|---|---|---|---|
| FP32 | 4 bytes | 1×(基准) | 100% | 0% | 训练阶段、精度敏感研究 |
| FP16/BF16 | 2 bytes | 2× | 50% | <1% | 推理默认标准 |
| INT8 | 1 byte | 3-4× | 25% | 2-5% | 消费级 GPU、边缘部署 |
| INT4/GPTQ | 0.5 bytes | 4-8× | 12.5% | 5-10% | 手机、嵌入式、高并发 |
| NF4/QLoRA | ~0.5 bytes | - | 12.5% | 3-7% | 单卡微调大模型 |
为什么 INT8/INT4 能工作?
展开代码# 核心思想:把浮点权重映射到整数范围 # FP16 权重范围: [-0.5, 0.5, 1.2, -1.5, ...] # 量化后 INT8: [-64, 64, 154, -192, ...] # 缩放因子 scale = 128/1.5 ≈ 85.3 # 推理时反量化:INT8 × scale ≈ 原始 FP16 # 损失来源:小数部分被四舍五入,极端值被截断
主流量化方案:
| 方案 | 特点 | 命令示例 |
|---|---|---|
| GPTQ | 逐层量化,校准数据少,4bit 主流 | python -m gptq.llama --wbits 4 |
| AWQ | 激活感知,保护重要权重,精度更高 | python -m awq.entry --w_bit 4 |
| GGUF/llama.cpp | CPU 友好,支持多种量化组合 | ./quantize model.gguf Q4_K_M |
| SmoothQuant | 激活-权重联合量化,INT8 推理最优 | 集成于 vLLM、TensorRT-LLM |
展开代码def estimate_memory(params_b, precision="fp16", batch=1, seq_len=2048, kv_cache=True): """ 快速估算模型推理显存需求 """ bytes_per_param = { "fp32": 4, "fp16": 2, "bf16": 2, "int8": 1, "int4": 0.5 }[precision] # 权重显存 model_memory = params_b * 1e9 * bytes_per_param / (1024**3) # GB # KV-Cache 显存(每 token 每头需要 2×hidden_dim×bytes) # 简化估算:约 2 × seq_len × batch × hidden_dim × layers × bytes kv_memory = 0 if kv_cache: # 以 LLaMA-7B 为例: hidden=4096, layers=32, heads=32 hidden, layers, heads = 4096, 32, 32 kv_per_token = 2 * hidden * bytes_per_param # K + V kv_memory = seq_len * batch * layers * kv_per_token / (1024**3) # 激活值、临时缓冲(约 10-20% 额外) overhead = model_memory * 0.2 total = model_memory + kv_memory + overhead return { "model_weights": round(model_memory, 2), "kv_cache": round(kv_memory, 2), "overhead": round(overhead, 2), "total_gb": round(total, 2), "recommend_gpu": f"A100-{80 if total > 40 else 40}GB" if total > 20 else "RTX-4090-24GB" } # 使用示例 print(estimate_memory(7, "fp16", batch=16, seq_len=4096)) # {'model_weights': 13.0, 'kv_cache': 16.0, 'overhead': 2.6, 'total_gb': 31.6, 'recommend_gpu': 'A100-40GB'}
展开代码数据:互联网公开文本(Common Crawl、Books、Wiki、Code) 规模:1T - 10T tokens(1 token ≈ 0.75 英文单词) 目标:预测下一个词(Next Token Prediction) 输出:基础模型(Base Model),会说人话但不懂指令
关键工程挑战:
展开代码数据:人工编写的高质量(指令,回答)对,通常 10万 - 100万条 目标:最大化回答质量(而非预测下一个词) 输出:指令模型(Instruct Model),能按格式回答问题
典型数据集:
展开代码数据:人对多个回答的排序偏好(A > B > C) 方法: 1. 训练奖励模型(Reward Model):学会打分 2. PPO 强化学习:让策略模型生成高分回答 输出:对齐模型(Aligned Model),有用、无害、诚实
替代方案:DPO(Direct Preference Optimization)
展开代码# 伪代码:Scaled Dot-Product Attention def attention(Q, K, V, mask=None): """ Q: Query (batch, seq, dim) - "我要查什么" K: Key (batch, seq, dim) - "我有什么信息" V: Value (batch, seq, dim) - "信息的内容" """ scores = Q @ K.T / sqrt(dim) # 相似度打分 if mask: scores = scores.masked_fill(mask, -inf) # 因果掩码(只看前面) weights = softmax(scores, dim=-1) # 归一化为概率 output = weights @ V # 加权求和 return output, weights # 输出 + 注意力权重(可可视化)
直观理解:
| 特性 | GPT(生成式) | BERT(理解式) |
|---|---|---|
| 结构 | Decoder-only(因果掩码) | Encoder-only(双向 attention) |
| 训练目标 | 预测下一个词 | 掩码语言模型(MLM) |
| 代表 | GPT-4, LLaMA, ChatGLM | BERT, RoBERTa, ERNIE |
| 擅长 | 文本生成、对话、代码 | 分类、NER、语义搜索 |
| 输入输出 | 前缀 → 续写 | 完整句子 → 向量表示 |
现代趋势:GPT 架构一统江湖,BERT 类模型逐渐边缘化。
问题:生成第 N 个 token 时,前 N-1 个 token 的 K/V 被重复计算
解法:把算过的 K/V 存起来,只算新的
展开代码# 推理时的优化 past_kvs = [] # 缓存列表 for i in range(max_length): # 只输入最新的 1 个 token,但 K/V 是完整的 logits, new_kvs = model.forward( input_ids=[new_token], past_key_values=past_kvs # 传入缓存 ) past_kvs.append(new_kvs) # 更新缓存 # 计算量从 O(N²) 降到 O(N)
显存代价:缓存随序列长度线性增长,长文本需小心 OOM。
| 策略 | 原理 | 吞吐提升 | 延迟 | 适用 |
|---|---|---|---|---|
| 静态批(Static Batching) | 等够 N 条一起发 | 3-5× | 高(等凑齐) | 离线任务 |
| 动态批(Dynamic Batching) | 有就来,超时未满也发 | 2-4× | 中 | 通用 API |
| 连续批(Continuous Batching / In-flight Batching) | 每完成一条立即补新,流水线不停 | 5-10× | 低 | 高并发在线服务 |
vLLM 的 PagedAttention:把 KV-Cache 分页管理,像操作系统管理内存,支持高效的连续批。
展开代码小模型(草稿模型):快速生成 3-5 个 token 候选 大模型(目标模型):一次验证,接受或回滚 效果:小模型算 5 步 ≈ 大模型算 1 步,整体提速 30-50% 条件:小模型质量不能太差(通常用 7B 草拟,70B 验证)
| 技术 | 原理 | 收益 |
|---|---|---|
| FlashAttention | IO 感知的 attention 算法,减少 HBM 读写 | 2-4× 速度,省显存 |
| Tensor Parallel (TP) | 单层网络切开,多卡同时算 | 单节点线性扩展 |
| Pipeline Parallel (PP) | 不同层放不同卡,流水线接力 | 跨节点扩展 |
| 量化推理 | INT8/INT4 kernel 优化 | 2-4× 吞吐 |
展开代码# 原始权重 W (d×d),冻结不动 # 只训练两个小子矩阵 A (d×r), B (r×d),r << d(通常 r=8,16,64) h = W @ x + (B @ A) @ x # 前向:原始输出 + LoRA 分支 # 训练参数:2×d×r vs 原始 d×d,节省 99.9%(当 r=16, d=4096)
优势:
展开代码4-bit Normal Float 量化基座模型 + Paged Optimizer(分页优化器,避免梯度 checkpoint 碎片) + LoRA 微调 = 单张 RTX-4090-24GB 微调 70B 模型
关键参数:
展开代码python qlora.py \ --model_name_or_path meta-llama/Llama-2-70b \ --bits 4 \ --lora_r 64 \ --lora_alpha 16 \ --max_memory 24GB \ --per_device_train_batch_size 1
| 指标 | 定义 | 测什么 | 好模型的值 |
|---|---|---|---|
| Perplexity (PPL) | 模型预测下一个词的困惑度 | 语言建模能力 | 越低越好(7B 模型 ~ 10-15) |
| BLEU/ROUGE | n-gram 重叠度 | 翻译、摘要 | 越高越好 |
| HumanEval | 代码通过率 | 编程能力 | GPT-4 ~ 67%, CodeLlama-34B ~ 48% |
| MMLU | 多学科选择题 | 知识广度 | GPT-4 ~ 86%, LLaMA-2-70B ~ 69% |
| 首 Token 延迟 (TTFT) | 用户输入 → 首个输出 token | 响应速度 | < 100ms(实时交互) |
| Time Per Output Token (TPOT) | 每生成一个 token 的时间 | 流畅度 | < 50ms(人类阅读速度) |
| 吞吐 (Throughput) | 每秒输出 token 数 | 并发能力 | 越高越好,决定成本 |
展开代码# 一行代码下载模型 from transformers import AutoModelForCausalLM, AutoTokenizer model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-chat-hf") tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-chat-hf") # 推理 inputs = tokenizer("The future of AI is", return_tensors="pt") outputs = model.generate(**inputs, max_new_tokens=50) print(tokenizer.decode(outputs[0]))
关键服务:
展开代码# 启动服务 python -m vllm.entrypoints.openai.api_server \ --model meta-llama/Llama-2-7b \ --tensor-parallel-size 2 \ --dtype half # 客户端调用(OpenAI 兼容 API) curl http://localhost:8000/v1/completions \ -H "Content-Type: application/json" \ -d '{ "model": "meta-llama/Llama-2-7b", "prompt": "San Francisco is a", "max_tokens": 7 }'
核心特性:
展开代码# ZeRO-3:把优化器状态、梯度、参数都切分到多卡 deepspeed --num_gpus=8 train.py \ --deepspeed_config ds_config_zero3.json # 关键配置 { "zero_optimization": { "stage": 3, # ZeRO-3:全分片 "offload_optimizer": { # CPU/NVMe 卸载 "device": "cpu", "pin_memory": true } }, "train_batch_size": "auto", "train_micro_batch_size_per_gpu": "auto" }
能力:
展开代码开始 │ ▼ 需要训练新模型? ──Y──→ 数据量 > 1B tokens? │ │ N Y ──→ DeepSpeed + 千卡集群 │ │ ▼ N ──→ LoRA/QLoRA 微调 需要推理服务? │ Y ──→ 并发 > 1000 QPS? │ │ │ Y ──→ vLLM + TensorRT-LLM + 连续批 │ │ │ N ──→ HuggingFace TGI / 简单 transformers │ ▼ 端侧部署(手机/边缘)? │ Y ──→ llama.cpp (GGUF) / MLC-LLM / 高通 QNN │ ▼ 结束
| 术语 | 一句话解释 |
|---|---|
| Token | 模型处理的最小单位,1 token ≈ 0.75 英文词 / 0.5 汉字 |
| Context Length | 模型能"记住"的上下文长度,如 4K, 32K, 128K |
| Temperature | 采样随机性,0=确定,1=创意,>1=混乱 |
| Top-p / Nucleus Sampling | 只从累积概率前 p% 的 token 中采样 |
| Repetition Penalty | 惩罚重复 token,防止车轱辘话 |
| System Prompt | 全局指令,设定模型角色和行为准则 |
| Few-shot Prompting | 给几个例子,让模型模仿 |
| Chain-of-Thought (CoT) | "让我们一步步想",提升推理能力 |
| RAG (Retrieval-Augmented Generation) | 外挂知识库,解决幻觉和时效性 |
本文作者:zzz
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!