diff --git a/app/docs/ai/MoE/MOE-intro.assets/img-20250920112106486.png b/app/docs/ai/MoE/MOE-intro.assets/img-20250920112106486.png new file mode 100644 index 0000000..140bd2f Binary files /dev/null and b/app/docs/ai/MoE/MOE-intro.assets/img-20250920112106486.png differ diff --git a/app/docs/ai/MoE/MOE-intro.assets/img-20250920112106518.png b/app/docs/ai/MoE/MOE-intro.assets/img-20250920112106518.png new file mode 100644 index 0000000..7243c98 Binary files /dev/null and b/app/docs/ai/MoE/MOE-intro.assets/img-20250920112106518.png differ diff --git a/app/docs/ai/MoE/MOE-intro.assets/img-20250920112106554.png b/app/docs/ai/MoE/MOE-intro.assets/img-20250920112106554.png new file mode 100644 index 0000000..c80092b Binary files /dev/null and b/app/docs/ai/MoE/MOE-intro.assets/img-20250920112106554.png differ diff --git a/app/docs/ai/MoE/MOE-intro.assets/img-20250920112106588.png b/app/docs/ai/MoE/MOE-intro.assets/img-20250920112106588.png new file mode 100644 index 0000000..a0e6948 Binary files /dev/null and b/app/docs/ai/MoE/MOE-intro.assets/img-20250920112106588.png differ diff --git a/app/docs/ai/MoE/MOE-intro.md b/app/docs/ai/MoE/MOE-intro.md new file mode 100644 index 0000000..0d04e21 --- /dev/null +++ b/app/docs/ai/MoE/MOE-intro.md @@ -0,0 +1,140 @@ +--- +title: "MOE 浅谈" +description: "混合专家(Mixture of Experts, MoE)架构的简要介绍" +tags: ["MoE", "AI"] +--- + +# 混合专家(Mixture of Experts, MoE)架构 + +为了在不显著增加计算需求的情况下有效扩展模型参数规模,MoE 架构已经成为一种可行的解决方案。MoE 利用一组专门化的子模型和一个门控机制,动态地选择合适的“专家网络”来处理给定输入。这使得模型能够根据需求分配计算资源,这一概念被称为 **条件计算(conditional computation)**。 + +MoE 架构已经被广泛应用到大语言模型(LLMs)中,使这些模型能够在参数规模显著扩大的同时,获得相应的能力提升。 +例如,Mixtral AI 提出的 **Mixtral-8x7B** 管实际激活的参数量仅有 130 亿,**在多个基准测试上表现优于或相当于 Llama-2-70B 和 GPT-3.5**。 + +--- + +## 传统 MoE 架构 + +自 MoE 最早被引入 Transformer 架构以来,MoE 主要作为 **前馈网络 (FFN)** 的替代模块使用。通常情况下,MoE 层中的每个专家都直接复制了其所替换的 FFN 结构。然后配备有一个 Router 来训练具体交给哪个专家处理。 + +![](./MOE-intro.assets/img-20250920112106486.png) + +MoE 主要应用于 FFN 层,而不是自注意力层,原因在于: + +- **注意力层**:稀疏性较低,更适用于全局交互。 +- **FFN 层**:稀疏性较高,更具有领域特性。 + 其中 DS-MoE 使用 Wikitext 作为任务时,发现:FFN 层的专家仅有 **20%** 被激活 + 而注意力层激活率高达 **80%**。这种高利用率表明注意力层的核心通讯机制不适用于特异化的专家。反之具有稀疏特性的 FFN 层,具有完整多专家特异化的潜力。 + +![](./MOE-intro.assets/img-20250920112106518.png) + +--- + +## Routing 机制:Dense MoE 与 Sparse MoE + +![](./MOE-intro.assets/img-20250920112106554.png) + +- **Dense MoE** + - gate 对于输入 token 使用 **softmax** 路由机制,传递给每个专家一定权重。 + - 优点:训练稳定。 + - 缺点:每次都要计算所有专家,计算成本高。 + +- **Sparse MoE** + - 使用 **Top-K** 路由机制,仅激活前 K 个权重最大的专家。 + - 优点:极大减少计算量,这是目前主流模型(如 GShard、Switch Transformer、Mixtral、DeepSeek-MoE)的策略。 + - 缺点:Router 训练变复杂,容易出现「热门专家被频繁使用,冷门专家学不到东西」的问题 → **路由坍塌**。 + - 解决办法:训练中需要引入额外的 **负载均衡损失**。 + +--- + +## 专家个数选择 + +**GLaM (Google, 2021)** 在实验中探索了不同专家数量与 gating 策略的组合: +发现 **64 个专家(per layer)+ Top-2 gating** 在性能和计算效率之间达到了最佳平衡。 +Top-2 gating 能显著提升效果,相比单一专家更稳定。并且 64 专家的配置在 **zero-shot、one-shot、few-shot** 场景下均表现优异。 所以后续的很多 MoE 工作(如 Mixtral, DBRX, DeepSeekMoE)也基本采用 ≤64 专家的规模,这个设计在实际应用中也具有参考价值。 + +--- + +## MoE 与 PEFT + +近期仍有不少工作专注于 PEFT(参数高效微调)。 +论文 [_Pushing Mixture of Experts to the Limit: Extremely Parameter Efficient MoE for Instruction Tuning_](https://arxiv.org/abs/2309.05444) 首次提出将 **LoRA 类型的 PEFT 方法和 MoE 框架结合**。 +其主要理念为,不直接在整个大模型上加 LoRA,而是专门在 MoE 的 expert 模块里应用 LoRA。因为 MoE 的每个专家就是 FFN(MLP),它们是知识写入的关键位置。这样每次只动一小部分 LoRA experts,并且大大增强了这种架构的易扩展性。 + +![](./MOE-intro.assets/img-20250920112106588.png) + +该方法的核心思想是利用 **低秩近似更新** 来避免高级算力的微调。 + +1. **输入 (Input → Embedding)** + - 输入 token(字或子词)先经过 Embedding。 + - 这部分和普通 Transformer 一样。 + +2. **Multi-Head Attention** + - 输入 embedding 进入多头注意力模块。 + - 在这里,Q、K、V 一切正常,完全没被 LoRAMoE 改动。 + - 输出再走 **Add & Norm**,结果传给 FFN。 + +3. **FFN → MoE (Expert 路由)** + - 普通 Transformer 的 FFN 被换成 **LoRA + MoE 专家网络**。 + - Router 根据输入选择若干专家,每个专家是 **LoRA 化(低秩适配)的模块**,而不是全量可训练的 FFN。 + - 冻结的部分(❄️)是预训练的大模型主干。 + - 火花(🔥)表示 LoRA Adapter(可训练参数,低秩矩阵)。 + - Router 输出的加权组合: + + $$ + y = \sum_i \alpha_i \cdot Expert_i(x) + $$ + + 其中 $\alpha_i$ 是 Router 根据输入算出来的权重。 + +4. **输出 (Add & Norm → Residual)** + - Router 混合后的专家输出,和残差连接一起进入 Add & Norm,继续往后层传。 + +--- + +#### LoRA 拆解 + +LoRA(Low-Rank Adaptation)的核心思想: + +对一个大的线性层权重 $W \in \mathbb{R}^{d_{out} \times d_{in}}$,不去训练整个矩阵,而是加上一个低秩近似更新: + +$$ +W' = W + \Delta W, \quad \Delta W = BA +$$ + +- $A \in \mathbb{R}^{r \times d_{in}}, B \in \mathbb{R}^{d_{out} \times r}$ +- 秩 $r \ll d_{in}, d_{out}$,通常只取个位数到几十 +- $W$:冻结(❄️,预训练参数) +- $A, B$:可训练(🔥,参数量大幅减少) + +这样,一个输入向量 $x$ 经过 LoRA 线性层时: + +$$ +Wx + BAx +$$ + +等于 **原始主干输出 + 一个小的低秩修正**。 + +回到该图,我们可以发现每个专家 $Expert_i$ 不是全新的大 FFN,而是 **一个 FFN 的 LoRA adapter 组合**: + +$$ +Expert_i(x) = B_i A_i x +$$ + +- Router 对输入 hidden state 计算一个分布 $\alpha$,然后加权组合: + +$$ +y = \sum_i \alpha_i \cdot Expert_i(x) +$$ + +- 最终结果再加上主干(冻结的 FFN 权重输出): + +$$ +y_{final} = W_{FFN}x + \sum_i \alpha_i \cdot B_i A_i x +$$ + +--- + +作者:**Yang Lewis** +非商业转载请标明出处。 +商业转载请联系作者:**840691168ly@gmail.com** diff --git a/app/docs/ai/compute-platforms/model-compuational-resource-demand.md b/app/docs/ai/compute-platforms/model-compuational-resource-demand.md new file mode 100644 index 0000000..7935dc9 --- /dev/null +++ b/app/docs/ai/compute-platforms/model-compuational-resource-demand.md @@ -0,0 +1,193 @@ +--- +title: "算力需求指南" +description: "如何计算训练大模型所需显存大小" +date: "2025-09-20" +tags: + - compute-platforms +--- + +# 大模型多卡训练笔记 + +## 1. 单位说明 + +1 GB = 1024 MB = 1024×1024 KB = 1024×1024×1024 Byte(字节) = 1024×1024×1024×8 Bit + +**参数类型与大小:** + +| 参数类型 | 字节数 (Byte) | +| ----------- | ------------- | +| FP32 | 4 | +| FP16 / BF16 | 2 | +| INT8 | 1 | +| INT4 | 0.5 | + +--- + +## 2. 大模型训练显存计算 + +单卡哪怕有 80 GB 显存,也扛不住数十亿、上百亿参数的大模型全量训练。 +权重只是一部分,梯度、优化器状态、激活都需要显存。 + +假设模型有 **N 参数量**(例如 2B = 20 亿): + +1. **权重 W** + - 存储方式:BF16 (2 Byte) + - 显存:$W = N \times 2$ Byte + - 例:2B 参数 → ≈ 4 GB + +2. **梯度 G** + - 存储方式:BF16 (2 Byte) + - 显存:$G = N \times 2$ Byte + - 例:2B 参数 → ≈ 4 GB + +3. **优化器状态(Adam)** + - 包含动量项 V、平方梯度 S,各自 FP32 (4 Byte) + - 每份 ≈ 8 GB,合计 ≈ 16 GB + 其中:优化器显存还需要的开销(权重梯度在训练中可能会复制很多份儿) + 1. **权重 W** + - 模型本身的参数,BF16/FP16 存 2 Byte。 + + 2. **梯度 G** + - 反向传播临时存储,BF16/FP16 2 Byte。 + + 3. **优化器状态**(不同优化器差别大): + - **SGD**:通常只需要梯度本身,**0份复制**。 + - **SGDM(带动量的 SGD)**:需要一个动量向量(FP32,4 Byte)。**一份复制** + - **Adam/AdamW**: + - **一阶动量 (V)**:FP32(4 Byte)。 + - **二阶动量 (S)**:FP32(4 Byte)。 + - 所以是 **2 份状态**。 + + 4. **Master 权重 ($W^A$)** + - 混合精度训练时常见:虽然前向/反向用 BF16,但优化器更新需要 FP32 精度 → 所以再存一份 FP32 权重。 + +4. **Activations** + - 依赖 batch size、seq_len、实现细节 + - 粗略估计:≈ 0.7–1.0 × 权重大小 + +--- + +## 3. 公式总表 + +- **普通 Adam 模式:** + + $W + G + W^A + V + S + 0.7W ≈ 24.8$ GB (以 2B 参数为例) + +- **DeepSpeed ZeRO-3 模式:** + + $W + G + W^A + G^A + V + S + 0.7W ≈ 32.8$ GB + +说明:ZeRO-3 显存更省,但通信和 I/O 开销更大。 + +--- + +## 4. 实际案例:Mixtral-8×7B + +### 设定与常数 + +- 架构:`d_model ≈ 4096`,`ffn_dim ≈ 14336`,每层 **8 个专家**,**32 层**,SwiGLU(gate/up/down 三个线性层)。 +- 单个专家参数量: + $4096×14336×2 + 14336×4096 = 176,160,768$ ≈ **1.76×10^8** + → BF16 权重 ≈ **352 MB/专家**。 +- 一层 8 专家 ≈ **2.82 GB/层** +- 32 层合计 ≈ **90 GB(仅专家权重)** + → 全专家全参训练在 **44 GB 显存**上不可能。 + +--- + +### 案例 A:Router-only + +- 路由器参数:`d_model × n_experts ≈ 4k × 8 = 32k` +- 全 32 层 ≈ **百万级参数** +- 开销极小(MB 级),显存主要花在 **激活** +- 在 44 GB 上完全可行,但改进有限 + +--- + +### 案例 B:部分层 × 部分专家 + +例:只训底部 **6 层**,每层 **2 专家**,同时训路由。 + +- 可训练参数数: + $6 × 2 × 176,160,768 = 2.114B$ +- 权重(BF16):≈ 4.23 GB +- 梯度(BF16):≈ 4.23 GB +- Adam 状态(V+S,FP32):≈ 16.9 GB +- Master 权重(FP32):≈ 8.46 GB +- **合计(持久内存 + 梯度)**:≈ 33.8 GB +- 再加冻结权重占位、激活开销,44 GB 卡上需: + - `batch=1–2` + - `seq_len ≤ 1024` + - `use_cache=False` + - `gradient_checkpointing=True` +- 可行,但需要严格控制。 + +--- + +### 案例 C:4-bit 全模型 + LoRA + +在专家 / 路由上挂 LoRA(r=16)。 + +- 单专家 LoRA 参数: + $r × (4096+14336 + 4096+14336 + 14336+4096) = r × 55296$ + → r=16 → 0.885M/专家 +- 每层 8 专家:7.08M +- 32 层:226.6M LoRA 参数 +- 显存开销: + - 权重 ≈ 0.45 GB + - 梯度 ≈ 0.45 GB + - Adam + Master ≈ 2.72 GB + - 合计 ≈ 3.6 GB +- 远低于 44 GB 显存 + +--- + +## 5. 并行方式 + +### 数据并行 (DP) + +- 各 GPU 拷贝全模型,喂不同 batch,梯度汇总 +- 优点:简单 +- 缺点:显存浪费大 + +### 分布式数据并行 (DDP) + +- 一卡一进程,梯度分桶同步 +- 优点:主流、稳定 +- 缺点:依然每卡全模型 + +### ZeRO 优化 (DeepSpeed) + +- ZeRO-1:拆优化器状态 +- ZeRO-2:再拆梯度 +- ZeRO-3:连参数也拆 +- 优点:显存省 +- 缺点:通信复杂 + +### 模型并行 + +- **张量并行 (TP)**:矩阵切块 +- **流水并行 (PP)**:层切片,像传送带 +- **MoE 并行**:专家分散在不同卡,token 激活部分专家 + +--- + +## 6. 踩坑经验 + +- 显存碎片化: + `PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True` + (需在 `import torch` 前设置) +- 通信库: + NCCL > Gloo > MPI(除非特殊环境) +- DDP:必须同步 random seed +- eval: + - eval_mb_size 可大 + - 训练 batch 小 + 梯度累积 + - 关掉 `model.config.use_cache` +- device = "auto": HF 会自动根据你机器的显存大小,把模型的不同部分切片分布,对于大模型,比如 7B,在单卡 44 GB 上:通常 attention + embedding + 部分 FFN 会放 GPU,冻结的模块、或者用不到的专家 (MoE inactive experts) 可以被放到 CPU。这个参数对推理来说自动分配还是很好的,但是训练的话**需要梯度的参数**必须常驻 GPU,否则每次 forward/backward 都要把参数搬上来,通信成本爆炸。所以,**device_map=auto 对训练不总是安全**,因为它可能把你要训练的层塞到 CPU 去,导致速度慢甚至无法训练。 + +--- + +作者:**Yang Lewis** +非商业转载请标明出处。 +商业转载请联系作者:**840691168ly@gmail.com**