mirror of
https://github.com/handsomezhuzhu/handsomezhuzhu.github.io.git
synced 2026-02-20 20:00:14 +00:00
一些奇怪的更改
This commit is contained in:
@@ -1,431 +1,431 @@
|
||||
---
|
||||
title: 数字电路笔记
|
||||
date: 2025-01-20 15:00:00
|
||||
descriptionHTML: '<span style="color:var(--description-font-color);">纯情男大自用数字电路基础笔记</span>'
|
||||
tags:
|
||||
- 笔记
|
||||
- 数字电路
|
||||
sidebar: true
|
||||
readingTime: true
|
||||
hidden: false
|
||||
recommend: true
|
||||
---
|
||||
|
||||
|
||||
# 数字电路笔记
|
||||
|
||||
|
||||
## 资料下载
|
||||
|
||||
|
||||
#### Markdown源码版本
|
||||
- **文件名**:数字电路基础.md
|
||||
- **下载链接**:[点击下载源码版本](https://github.com/handsomezhuzhu/other_note/raw/main/数字电路/数字电路基础.md)
|
||||
|
||||
#### PDF版本
|
||||
- **文件名**:数字电路基础.pdf
|
||||
- **下载链接**:[点击下载PDF版本](https://github.com/handsomezhuzhu/other_note/raw/main/数字电路/数字电路基础.pdf)
|
||||
|
||||
|
||||
|
||||
## 完整笔记
|
||||
|
||||
|
||||
## 一、逻辑代数定律和计算规则
|
||||
|
||||
| 定律/规则名称 | 表达式 | 解释 |
|
||||
| --------- | ----------------------------------------------------------------------------------- | ------------------- |
|
||||
| 恒等律 | $A + 0 = A$<br>$A \cdot 1 = A$ | 任何变量与0相加或与1相乘等于自身 |
|
||||
| 零律 | $A + 1 = 1$<br>$A \cdot 0 = 0$ | 任何变量与1相加或与0相乘等于1或0 |
|
||||
| 幂等律 | $A + A = A$<br>$A \cdot A = A$ | 任何变量与自身相加或相乘等于自身 |
|
||||
| 互补律 | $A + \overline{A} = 1$<br>$A \cdot \overline{A} = 0$ | 任何变量与其补码相加等于1,相乘等于0 |
|
||||
| **交换律** | | |
|
||||
| 加法交换律 | $A + B = B + A$ | 加法运算的交换律 |
|
||||
| 乘法交换律 | $A \cdot B = B \cdot A$ | 乘法运算的交换律 |
|
||||
| **结合律** | | |
|
||||
| 加法结合律 | $(A + B) + C = A + (B + C)$ | 加法运算的结合律 |
|
||||
| 乘法结合律 | $(A \cdot B) \cdot C = A \cdot (B \cdot C)$ | 乘法运算的结合律 |
|
||||
| **分配律** | | |
|
||||
| 乘法分配律 | $A \cdot (B + C) = A \cdot B + A \cdot C$ | 乘法对加法的分配律 |
|
||||
| 加法分配律 | $A + (B \cdot C) = (A + B) \cdot (A + C)$ | 加法对乘法的分配律 |
|
||||
| **吸收律** | | |
|
||||
| 吸收律1 | $A + A \cdot B = A$ | 吸收律的第一种形式 |
|
||||
| 吸收律2 | $A \cdot (A + B) = A$ | 吸收律的第二种形式 |
|
||||
| **德摩根定律** | | |
|
||||
| 德摩根定律1 | $\overline{A + B} = \overline{A} \cdot \overline{B}$ | 逻辑加法的德摩根定律 |
|
||||
| 德摩根定律2 | $\overline{A \cdot B} = \overline{A} + \overline{B}$ | 逻辑乘法的德摩根定律 |
|
||||
| **简化定律** | | |
|
||||
| 简化定律1 | $A + \overline{A} \cdot B = A + B$ | 简化逻辑表达式 |
|
||||
| 简化定律2 | $A \cdot (\overline{A} + B) = A \cdot B$ | 简化逻辑表达式 |
|
||||
| **共识定律** | | |
|
||||
| 共识定律 (积之和形式) | $AB + \overline{A}C + BC = AB + \overline{A}C$ | 较难,常用于逻辑化简。项 `BC` 是 `AB` 和 `A`C 的共识项,是冗余的。 |
|
||||
| 共识定律 (和之积形式) | $(A+B)(\overline{A}+C)(B+C) = (A+B)(\overline{A}+C)$ | 较难,常用于逻辑化简。项 `(B+C)` 是 `(A+B)` 和 `(A`+C) 的共识项,是冗余的。|
|
||||
| **反演定律** | | |
|
||||
| 反演定律 | $A = \overline{\overline{A}}$ | 变量的双重否定等于自身 |
|
||||
|
||||
### 推导过程
|
||||
|
||||
1. **基本定律**
|
||||
- **恒等律**:$A + 0 = A$ 和 $A \cdot 1 = A$ 是逻辑代数的基本定义。
|
||||
- **零律**:$A + 1 = 1$ 和 $A \cdot 0 = 0$ 也是逻辑代数的基本定义。
|
||||
- **幂等律**:$A + A = A$ 和 $A \cdot A = A$ 是因为逻辑加法和乘法运算的特性。
|
||||
- **互补律**:$A + \overline{A} = 1$ 和 $A \cdot \overline{A} = 0$ 是逻辑变量和其补码的定义。
|
||||
|
||||
2. **交换律**
|
||||
- **加法交换律**:$A + B = B + A$ 是逻辑加法的交换特性。
|
||||
- **乘法交换律**:$A \cdot B = B \cdot A$ 是逻辑乘法的交换特性。
|
||||
|
||||
3. **结合律**
|
||||
- **加法结合律**:$(A + B) + C = A + (B + C)$ 是逻辑加法的结合特性。
|
||||
- **乘法结合律**:$(A \cdot B) \cdot C = A \cdot (B \cdot C)$ 是逻辑乘法的结合特性。
|
||||
|
||||
4. **分配律**
|
||||
- **乘法分配律**:$A \cdot (B + C) = A \cdot B + A \cdot C$ 是逻辑乘法对加法的分配特性。
|
||||
- **加法分配律**:$A + (B \cdot C) = (A + B) \cdot (A + C)$ 是逻辑加法对乘法的分配特性。
|
||||
|
||||
5. **吸收律**
|
||||
- **吸收律1**:$A + A \cdot B = A$ 可以从 $A + A \cdot B = A \cdot (1 + B) = A \cdot 1 = A$ 推导得出。
|
||||
- **吸收律2**:$A \cdot (A + B) = A$ 可以从 $A \cdot (A + B) = A \cdot A + A \cdot B = A + A \cdot B = A$ 推导得出。
|
||||
|
||||
6. **德摩根定律**
|
||||
- **德摩根定律1**:$\overline{A + B} = \overline{A} \cdot \overline{B}$ 是逻辑加法的德摩根定律。
|
||||
- **德摩根定律2**:$\overline{A \cdot B} = \overline{A} + \overline{B}$ 是逻辑乘法的德摩根定律。
|
||||
|
||||
7. **简化定律**
|
||||
- **简化定律1**:$A + \overline{A} \cdot B = A + B$ 可以从 $A + \overline{A} \cdot B = (A + \overline{A}) \cdot (A + B) = 1 \cdot (A + B) = A + B$ 推导得出。
|
||||
- **简化定律2**:$A \cdot (\overline{A} + B) = A \cdot B$ 可以从 $A \cdot (\overline{A} + B) = A \cdot \overline{A} + A \cdot B = 0 + A \cdot B = A \cdot B$ 推导得出。
|
||||
|
||||
8. **共识定律**
|
||||
- **共识定律**:$(A + B) \cdot (\overline{A} + C) = (A + B) \cdot (\overline{A} + C) \cdot (B + C)$ 可以从 $(A + B) \cdot (\overline{A} + C) = (A + B) \cdot (\overline{A} + C) \cdot (B + C)$ 推导得出,因为 $(A + B) \cdot (\overline{A} + C) \leq (B + C)$。
|
||||
|
||||
9. **反演定律**
|
||||
- **反演定律**:$A = \overline{\overline{A}}$ 是逻辑变量的双重否定特性。
|
||||
|
||||
---
|
||||
## 二、基本门电路
|
||||
|
||||
### 1. 非门
|
||||
|
||||
$$
|
||||
Y = \overline{A}
|
||||
$$
|
||||
|
||||
|
||||
|
||||
### 2. 与门
|
||||
|
||||
$$
|
||||
Y = A \cdot B
|
||||
$$
|
||||
|
||||
**真值表:**
|
||||
|
||||
| 输入 A | 输入 B | 输出 Y |
|
||||
| --- | --- | --- |
|
||||
| 0 | 0 | 0 |
|
||||
| 0 | 1 | 0 |
|
||||
| 1 | 0 | 0 |
|
||||
| 1 | 1 | 1 |
|
||||
|
||||
|
||||
|
||||
### 3. 或门
|
||||
|
||||
$$
|
||||
Y = A + B
|
||||
$$
|
||||
|
||||
**真值表:**
|
||||
|
||||
| 输入 A | 输入 B | 输出 Y |
|
||||
| --- | --- | --- |
|
||||
| 0 | 0 | 0 |
|
||||
| 0 | 1 | 1 |
|
||||
| 1 | 0 | 1 |
|
||||
| 1 | 1 | 1 |
|
||||
|
||||
|
||||
|
||||
### 4. 与非门
|
||||
与非门是“与门”和“非门”的结合。
|
||||
$$
|
||||
Y = \overline{A \cdot B}
|
||||
$$
|
||||
|
||||
**真值表:**
|
||||
|
||||
| 输入 A | 输入 B | 输出 Y |
|
||||
|:---:|:---:|:---:|
|
||||
| 0 | 0 | 1 |
|
||||
| 0 | 1 | 1 |
|
||||
| 1 | 0 | 1 |
|
||||
| 1 | 1 | 0 |
|
||||
|
||||
|
||||
|
||||
### 5. 或非门
|
||||
或非门是“或门”和“非门”的结合。
|
||||
$$
|
||||
Y = \overline{A + B}
|
||||
$$
|
||||
|
||||
**真值表:**
|
||||
|
||||
| 输入 A | 输入 B | 输出 Y |
|
||||
|:---:|:---:|:---:|
|
||||
| 0 | 0 | 1 |
|
||||
| 0 | 1 | 0 |
|
||||
| 1 | 0 | 0 |
|
||||
| 1 | 1 | 0 |
|
||||
|
||||
|
||||
|
||||
### 6. 异或门
|
||||
当两个输入不相同时,输出为高电平(1);当两个输入相同时,输出为低电平(0)。这也被称为“半加器”的求和逻辑。
|
||||
|
||||
**逻辑表达式:**
|
||||
$$
|
||||
Y = A \oplus B
|
||||
$$
|
||||
|
||||
**真值表:**
|
||||
|
||||
| 输入 A | 输入 B | 输出 Y |
|
||||
|:---:|:---:|:---:|
|
||||
| 0 | 0 | 0 |
|
||||
| 0 | 1 | 1 |
|
||||
| 1 | 0 | 1 |
|
||||
| 1 | 1 | 0 |
|
||||
|
||||
---
|
||||
## 三、编码
|
||||
|
||||
### 1. 原码、反码和补码
|
||||
为了在二进制系统中表示正负数,我们通常会使用最高位作为**符号位**。
|
||||
* 符号位为 **0** 代表**正数**。
|
||||
* 符号位为 **1** 代表**负数**。
|
||||
|
||||
|
||||
|
||||
#### **原码**
|
||||
|
||||
|
||||
* **规则**: 符号位 + 数值的绝对值的二进制表示。
|
||||
* **正数**: 符号位为0,其余位表示数值。
|
||||
* 例如,$+12$ 的原码是 **00001100**。
|
||||
* **负数**: 符号位为1,其余位表示数值。
|
||||
* 例如,$-12$ 的原码是 **10001100**。
|
||||
* **缺点**:
|
||||
1. 零的表示不唯一:$+0$ 是 **00000000**,$-0$ 是 **10000000**。
|
||||
2. 进行加减法运算时,需要单独处理符号位,硬件实现复杂。
|
||||
|
||||
#### **反码**
|
||||
|
||||
反码的出现是为了简化减法运算。
|
||||
|
||||
* **规则**:
|
||||
* **正数**的反码与其原码**相同**。
|
||||
* **负数**的反码是在其**原码**的基础上,**符号位不变**,其余各位**按位取反**。
|
||||
* **示例**:
|
||||
* $+12$ 的原码是 `00001100`,其反码也是 **00001100**。
|
||||
* $-12$ 的原码是 `10001100`,其反码是 **11110011** (符号位1不变,后面7位 `0001100` 按位取反得到 `1110011`)。
|
||||
* **缺点**:
|
||||
* 仍然存在“双零”问题:$+0$ 的反码是 **00000000**,$-0$ 的反码是 **11111111**。
|
||||
* 跨零运算会产生循环进位问题。
|
||||
|
||||
#### **补码**
|
||||
|
||||
补码是现代计算机系统中最常用的有符号数表示法,它解决了原码和反码的缺点。
|
||||
|
||||
* **规则**:
|
||||
* **正数**的补码与其原码**相同**。
|
||||
* **负数**的补码是其**反码加 1**。
|
||||
* **求负数补码的方式**:
|
||||
* 从其原码的**最低位(最右边)**向左找,找到的**第一个 1** 保持不变,这个 1 **左边**的所有位(不含符号位)按位取反,符号位仍为1。
|
||||
* **示例**:
|
||||
* $+12$ 的补码是 **00001100**。
|
||||
* $-12$ 的补码求法:
|
||||
1. 原码: `10001100`
|
||||
2. 反码: `11110011`
|
||||
3. 加 1: `11110011 + 1` = **11110100**。
|
||||
* **优点**:
|
||||
1. **零的表示唯一**: **00000000**。
|
||||
2. **简化运算**: 可以将减法运算转换为加法运算。例如,计算 $A - B$ 等同于计算 $A + (-B)$ 的补码。
|
||||
3. 对于一个 $n$ 位的补码系统,其表示范围为 $[-2^{n-1}, 2^{n-1}-1]$。例如,8位补码的范围是 $[-128, 127]$。
|
||||
|
||||
**总结表格 (以 ±12 为例)**
|
||||
|
||||
| 值 | 原码 | 反码 | 补码 |
|
||||
|:---:|:---:|:---:|:---:|
|
||||
| +12 | 00001100 | 00001100 | 00001100 |
|
||||
| -12 | 10001100 | 11110011 | 11110100 |
|
||||
|
||||
|
||||
|
||||
### 2. BCD 码
|
||||
|
||||
BCD码是用**二进制**来表示**十进制**数的一种编码方式。它与直接将十进制数转换为二进制数不同。
|
||||
|
||||
* **规则**: 用 **4 位二进制数**来表示一位十进制数(0-9)。最常用的是 **8421 BCD 码**,其中各位的权值从高到低分别是 8、4、2、1。
|
||||
* **特点**:
|
||||
* 它介于二进制和十进制之间,便于人机交互(如数码管显示、计算器)。
|
||||
* 运算比纯二进制复杂,但比直接处理十进制字符简单。
|
||||
* 由于用4位二进制表示一位十进制数,所以 `1010` 到 `1111` 这 6 个码是无效或非法的。
|
||||
|
||||
**BCD 码对照表**
|
||||
|
||||
| 十进制 | BCD 码 |
|
||||
|:---:|:---:|
|
||||
| 0 | 0000 |
|
||||
| 1 | 0001 |
|
||||
| 2 | 0010 |
|
||||
| 3 | 0011 |
|
||||
| 4 | 0100 |
|
||||
| 5 | 0101 |
|
||||
| 6 | 0110 |
|
||||
| 7 | 0111 |
|
||||
| 8 | 1000 |
|
||||
| 9 | 1001 |
|
||||
|
||||
**示例**:
|
||||
将十进制数 **129** 转换为 BCD 码。
|
||||
|
||||
1. 将每一位十进制数分开:`1`、`2`、`9`。
|
||||
2. 将每一位分别转换为对应的4位BCD码:
|
||||
* $1 \rightarrow 0001$
|
||||
* $2 \rightarrow 0010$
|
||||
* $9 \rightarrow 1001$
|
||||
3. 将它们组合起来:
|
||||
$$
|
||||
(129)_{10} = (0001 \ 0010 \ 1001)_{\text{BCD}}
|
||||
$$
|
||||
**对比**: 如果将 (129)₁₀ 直接转换为纯二进制,结果是 **10000001**。这与它的 BCD 码是完全不同的。
|
||||
---
|
||||
## 四、加法器、编码器、译码器、选择器、比较器
|
||||
---
|
||||
## 五、触发器
|
||||
|
||||
### 1. RS 触发器
|
||||
|
||||
最基本的触发器,但存在一个不确定状态,在实际应用中较少直接使用。
|
||||
|
||||
* **输入**: $S$ (Set, 置位), $R$ (Reset, 复位)
|
||||
* **输出**: $Q$ (状态输出), $\overline{Q}$ (反向输出)
|
||||
|
||||
#### **功能表**
|
||||
这张表描述了在不同输入下,下一个状态 $Q_{n+1}$ 是什么。
|
||||
|
||||
| $S$ | $R$ | $Q_{n+1}$ | 功能 |
|
||||
|:---:|:---:|:---:|:---|
|
||||
| 0 | 0 | $Q_n$ | 保持 |
|
||||
| 0 | 1 | 0 | 复位/置0 |
|
||||
| 1 | 0 | 1 | 置位/置1|
|
||||
| 1 | 1 | **?** | **禁止/不定** |
|
||||
|
||||
#### **特性方程**
|
||||
$$
|
||||
Q_{n+1} = S + \overline{R}Q_n \quad (\text{约束条件: } S \cdot R = 0)
|
||||
$$
|
||||
|
||||
#### **激励表**
|
||||
这张表在电路设计时非常有用,它回答了“为了让状态从 $Q_n$ 变为 $Q_{n+1}$,输入 $S$ 和 $R$ 应该是什么?”。(X表示Don't Care,即0或1均可)
|
||||
|
||||
| $Q_n$ | $Q_{n+1}$ | $S$ | $R$ |
|
||||
|:---:|:---:|:---:|:---:|
|
||||
| 0 | 0 | 0 | X |
|
||||
| 0 | 1 | 1 | 0 |
|
||||
| 1 | 0 | 0 | 1 |
|
||||
| 1 | 1 | X | 0 |
|
||||
|
||||
|
||||
### 2. JK 触发器
|
||||
|
||||
JK 触发器是 RS 触发器的改进版,它解决了 RS 触发器的“禁止”状态问题,是最通用的触发器。
|
||||
|
||||
* **输入**: $J$ (功能类似 $S$), $K$ (功能类似 $R$)
|
||||
* **输出**: $Q$, $\overline{Q}$
|
||||
|
||||
#### **功能表**
|
||||
|
||||
| $J$ | $K$ | $Q_{n+1}$ | 功能 |
|
||||
|:---:|:---:|:---:|:---|
|
||||
| 0 | 0 | $Q_n$ | 保持 |
|
||||
| 0 | 1 | 0 | 复0 |
|
||||
| 1 | 0 | 1 | 置1 |
|
||||
| 1 | 1 | $\overline{Q_n}$ | **翻转 ** |
|
||||
|
||||
*JK触发器将RS触发器的禁止状态(1,1输入)变成了一个非常有用的**翻转**功能。*
|
||||
|
||||
#### **特性方程**
|
||||
$$
|
||||
Q_{n+1} = J\overline{Q_n} + \overline{K}Q_n
|
||||
$$
|
||||
|
||||
#### **激励表**
|
||||
|
||||
| $Q_n$ | $Q_{n+1}$ | $J$ | $K$ |
|
||||
|:---:|:---:|:---:|:---:|
|
||||
| 0 | 0 | 0 | X |
|
||||
| 0 | 1 | 1 | X |
|
||||
| 1 | 0 | X | 1 |
|
||||
| 1 | 1 | X | 0 |
|
||||
|
||||
|
||||
### 3. D 触发器
|
||||
D 触发器的功能非常直接:在时钟脉冲到来时,将输入 $D$ 的值传递给输出 $Q$。它常被用作数据锁存器或移位寄存器的基本单元。
|
||||
|
||||
* **输入**: $D$ (Data)
|
||||
* **输出**: $Q$, $\overline{Q}$
|
||||
|
||||
#### **功能表**
|
||||
|
||||
| $D$ | $Q_{n+1}$ | 功能 |
|
||||
|:---:|:---:|:---|
|
||||
| 0 | 0 | 置0 |
|
||||
| 1 | 1 | 置1 |
|
||||
|
||||
*无论当前状态 $Q_n$ 是什么,下一个状态 $Q_{n+1}$ 都等于时钟边沿到来时的 $D$ 输入值。*
|
||||
|
||||
#### **特性方程 **
|
||||
$$
|
||||
Q_{n+1} = D
|
||||
$$
|
||||
|
||||
#### **激励表 **
|
||||
|
||||
| $Q_n$ | $Q_{n+1}$ | $D$ |
|
||||
|:---:|:---:|:---:|
|
||||
| 0 | 0 | 0 |
|
||||
| 0 | 1 | 1 |
|
||||
| 1 | 0 | 0 |
|
||||
| 1 | 1 | 1 |
|
||||
|
||||
|
||||
|
||||
### 4. T 触发器
|
||||
|
||||
T 触发器是一个翻转触发器。当输入 $T=1$ 时,状态翻转;当 $T=0$ 时,状态保持不变。它常用于构建计数器。
|
||||
|
||||
* **输入**: $T$
|
||||
* **输出**: $Q$, $\overline{Q}$
|
||||
|
||||
#### **功能表**
|
||||
|
||||
| $T$ | $Q_{n+1}$ | 功能 |
|
||||
|:---:|:---:|:---|
|
||||
| 0 | $Q_n$ | 保持 |
|
||||
| 1 | $\overline{Q_n}$ | 翻转 |
|
||||
|
||||
#### **特性方程**
|
||||
$$
|
||||
Q_{n+1} = T \oplus Q_n = T\overline{Q_n} + \overline{T}Q_n
|
||||
$$
|
||||
|
||||
#### **激励表**
|
||||
|
||||
| $Q_n$ | $Q_{n+1}$ | $T$ |
|
||||
|:---:|:---:|:---:|
|
||||
| 0 | 0 | 0 |
|
||||
| 0 | 1 | 1 |
|
||||
| 1 | 0 | 1 |
|
||||
| 1 | 1 | 0 |
|
||||
---
|
||||
title: 数字电路笔记
|
||||
date: 2025-01-20 15:00:00
|
||||
descriptionHTML: '<span style="color:var(--description-font-color);">纯情男大自用数字电路基础笔记</span>'
|
||||
tags:
|
||||
- 笔记
|
||||
- 数字电路
|
||||
sidebar: true
|
||||
readingTime: true
|
||||
hidden: false
|
||||
recommend: true
|
||||
---
|
||||
|
||||
|
||||
# 数字电路笔记
|
||||
|
||||
|
||||
## 资料下载
|
||||
|
||||
|
||||
#### Markdown源码版本
|
||||
- **文件名**:数字电路基础.md
|
||||
- **下载链接**:[点击下载源码版本](https://github.com/handsomezhuzhu/other_note/raw/main/数字电路/数字电路基础.md)
|
||||
|
||||
#### PDF版本
|
||||
- **文件名**:数字电路基础.pdf
|
||||
- **下载链接**:[点击下载PDF版本](https://github.com/handsomezhuzhu/other_note/raw/main/数字电路/数字电路基础.pdf)
|
||||
|
||||
|
||||
|
||||
## 完整笔记
|
||||
|
||||
|
||||
## 一、逻辑代数定律和计算规则
|
||||
|
||||
| 定律/规则名称 | 表达式 | 解释 |
|
||||
| --------- | ----------------------------------------------------------------------------------- | ------------------- |
|
||||
| 恒等律 | $A + 0 = A$<br>$A \cdot 1 = A$ | 任何变量与0相加或与1相乘等于自身 |
|
||||
| 零律 | $A + 1 = 1$<br>$A \cdot 0 = 0$ | 任何变量与1相加或与0相乘等于1或0 |
|
||||
| 幂等律 | $A + A = A$<br>$A \cdot A = A$ | 任何变量与自身相加或相乘等于自身 |
|
||||
| 互补律 | $A + \overline{A} = 1$<br>$A \cdot \overline{A} = 0$ | 任何变量与其补码相加等于1,相乘等于0 |
|
||||
| **交换律** | | |
|
||||
| 加法交换律 | $A + B = B + A$ | 加法运算的交换律 |
|
||||
| 乘法交换律 | $A \cdot B = B \cdot A$ | 乘法运算的交换律 |
|
||||
| **结合律** | | |
|
||||
| 加法结合律 | $(A + B) + C = A + (B + C)$ | 加法运算的结合律 |
|
||||
| 乘法结合律 | $(A \cdot B) \cdot C = A \cdot (B \cdot C)$ | 乘法运算的结合律 |
|
||||
| **分配律** | | |
|
||||
| 乘法分配律 | $A \cdot (B + C) = A \cdot B + A \cdot C$ | 乘法对加法的分配律 |
|
||||
| 加法分配律 | $A + (B \cdot C) = (A + B) \cdot (A + C)$ | 加法对乘法的分配律 |
|
||||
| **吸收律** | | |
|
||||
| 吸收律1 | $A + A \cdot B = A$ | 吸收律的第一种形式 |
|
||||
| 吸收律2 | $A \cdot (A + B) = A$ | 吸收律的第二种形式 |
|
||||
| **德摩根定律** | | |
|
||||
| 德摩根定律1 | $\overline{A + B} = \overline{A} \cdot \overline{B}$ | 逻辑加法的德摩根定律 |
|
||||
| 德摩根定律2 | $\overline{A \cdot B} = \overline{A} + \overline{B}$ | 逻辑乘法的德摩根定律 |
|
||||
| **简化定律** | | |
|
||||
| 简化定律1 | $A + \overline{A} \cdot B = A + B$ | 简化逻辑表达式 |
|
||||
| 简化定律2 | $A \cdot (\overline{A} + B) = A \cdot B$ | 简化逻辑表达式 |
|
||||
| **共识定律** | | |
|
||||
| 共识定律 (积之和形式) | $AB + \overline{A}C + BC = AB + \overline{A}C$ | 较难,常用于逻辑化简。项 `BC` 是 `AB` 和 `A`C 的共识项,是冗余的。 |
|
||||
| 共识定律 (和之积形式) | $(A+B)(\overline{A}+C)(B+C) = (A+B)(\overline{A}+C)$ | 较难,常用于逻辑化简。项 `(B+C)` 是 `(A+B)` 和 `(A`+C) 的共识项,是冗余的。|
|
||||
| **反演定律** | | |
|
||||
| 反演定律 | $A = \overline{\overline{A}}$ | 变量的双重否定等于自身 |
|
||||
|
||||
### 推导过程
|
||||
|
||||
1. **基本定律**
|
||||
- **恒等律**:$A + 0 = A$ 和 $A \cdot 1 = A$ 是逻辑代数的基本定义。
|
||||
- **零律**:$A + 1 = 1$ 和 $A \cdot 0 = 0$ 也是逻辑代数的基本定义。
|
||||
- **幂等律**:$A + A = A$ 和 $A \cdot A = A$ 是因为逻辑加法和乘法运算的特性。
|
||||
- **互补律**:$A + \overline{A} = 1$ 和 $A \cdot \overline{A} = 0$ 是逻辑变量和其补码的定义。
|
||||
|
||||
2. **交换律**
|
||||
- **加法交换律**:$A + B = B + A$ 是逻辑加法的交换特性。
|
||||
- **乘法交换律**:$A \cdot B = B \cdot A$ 是逻辑乘法的交换特性。
|
||||
|
||||
3. **结合律**
|
||||
- **加法结合律**:$(A + B) + C = A + (B + C)$ 是逻辑加法的结合特性。
|
||||
- **乘法结合律**:$(A \cdot B) \cdot C = A \cdot (B \cdot C)$ 是逻辑乘法的结合特性。
|
||||
|
||||
4. **分配律**
|
||||
- **乘法分配律**:$A \cdot (B + C) = A \cdot B + A \cdot C$ 是逻辑乘法对加法的分配特性。
|
||||
- **加法分配律**:$A + (B \cdot C) = (A + B) \cdot (A + C)$ 是逻辑加法对乘法的分配特性。
|
||||
|
||||
5. **吸收律**
|
||||
- **吸收律1**:$A + A \cdot B = A$ 可以从 $A + A \cdot B = A \cdot (1 + B) = A \cdot 1 = A$ 推导得出。
|
||||
- **吸收律2**:$A \cdot (A + B) = A$ 可以从 $A \cdot (A + B) = A \cdot A + A \cdot B = A + A \cdot B = A$ 推导得出。
|
||||
|
||||
6. **德摩根定律**
|
||||
- **德摩根定律1**:$\overline{A + B} = \overline{A} \cdot \overline{B}$ 是逻辑加法的德摩根定律。
|
||||
- **德摩根定律2**:$\overline{A \cdot B} = \overline{A} + \overline{B}$ 是逻辑乘法的德摩根定律。
|
||||
|
||||
7. **简化定律**
|
||||
- **简化定律1**:$A + \overline{A} \cdot B = A + B$ 可以从 $A + \overline{A} \cdot B = (A + \overline{A}) \cdot (A + B) = 1 \cdot (A + B) = A + B$ 推导得出。
|
||||
- **简化定律2**:$A \cdot (\overline{A} + B) = A \cdot B$ 可以从 $A \cdot (\overline{A} + B) = A \cdot \overline{A} + A \cdot B = 0 + A \cdot B = A \cdot B$ 推导得出。
|
||||
|
||||
8. **共识定律**
|
||||
- **共识定律**:$(A + B) \cdot (\overline{A} + C) = (A + B) \cdot (\overline{A} + C) \cdot (B + C)$ 可以从 $(A + B) \cdot (\overline{A} + C) = (A + B) \cdot (\overline{A} + C) \cdot (B + C)$ 推导得出,因为 $(A + B) \cdot (\overline{A} + C) \leq (B + C)$。
|
||||
|
||||
9. **反演定律**
|
||||
- **反演定律**:$A = \overline{\overline{A}}$ 是逻辑变量的双重否定特性。
|
||||
|
||||
---
|
||||
## 二、基本门电路
|
||||
|
||||
### 1. 非门
|
||||
|
||||
$$
|
||||
Y = \overline{A}
|
||||
$$
|
||||
|
||||
|
||||
|
||||
### 2. 与门
|
||||
|
||||
$$
|
||||
Y = A \cdot B
|
||||
$$
|
||||
|
||||
**真值表:**
|
||||
|
||||
| 输入 A | 输入 B | 输出 Y |
|
||||
| --- | --- | --- |
|
||||
| 0 | 0 | 0 |
|
||||
| 0 | 1 | 0 |
|
||||
| 1 | 0 | 0 |
|
||||
| 1 | 1 | 1 |
|
||||
|
||||
|
||||
|
||||
### 3. 或门
|
||||
|
||||
$$
|
||||
Y = A + B
|
||||
$$
|
||||
|
||||
**真值表:**
|
||||
|
||||
| 输入 A | 输入 B | 输出 Y |
|
||||
| --- | --- | --- |
|
||||
| 0 | 0 | 0 |
|
||||
| 0 | 1 | 1 |
|
||||
| 1 | 0 | 1 |
|
||||
| 1 | 1 | 1 |
|
||||
|
||||
|
||||
|
||||
### 4. 与非门
|
||||
与非门是“与门”和“非门”的结合。
|
||||
$$
|
||||
Y = \overline{A \cdot B}
|
||||
$$
|
||||
|
||||
**真值表:**
|
||||
|
||||
| 输入 A | 输入 B | 输出 Y |
|
||||
|:---:|:---:|:---:|
|
||||
| 0 | 0 | 1 |
|
||||
| 0 | 1 | 1 |
|
||||
| 1 | 0 | 1 |
|
||||
| 1 | 1 | 0 |
|
||||
|
||||
|
||||
|
||||
### 5. 或非门
|
||||
或非门是“或门”和“非门”的结合。
|
||||
$$
|
||||
Y = \overline{A + B}
|
||||
$$
|
||||
|
||||
**真值表:**
|
||||
|
||||
| 输入 A | 输入 B | 输出 Y |
|
||||
|:---:|:---:|:---:|
|
||||
| 0 | 0 | 1 |
|
||||
| 0 | 1 | 0 |
|
||||
| 1 | 0 | 0 |
|
||||
| 1 | 1 | 0 |
|
||||
|
||||
|
||||
|
||||
### 6. 异或门
|
||||
当两个输入不相同时,输出为高电平(1);当两个输入相同时,输出为低电平(0)。这也被称为“半加器”的求和逻辑。
|
||||
|
||||
**逻辑表达式:**
|
||||
$$
|
||||
Y = A \oplus B
|
||||
$$
|
||||
|
||||
**真值表:**
|
||||
|
||||
| 输入 A | 输入 B | 输出 Y |
|
||||
|:---:|:---:|:---:|
|
||||
| 0 | 0 | 0 |
|
||||
| 0 | 1 | 1 |
|
||||
| 1 | 0 | 1 |
|
||||
| 1 | 1 | 0 |
|
||||
|
||||
---
|
||||
## 三、编码
|
||||
|
||||
### 1. 原码、反码和补码
|
||||
为了在二进制系统中表示正负数,我们通常会使用最高位作为**符号位**。
|
||||
* 符号位为 **0** 代表**正数**。
|
||||
* 符号位为 **1** 代表**负数**。
|
||||
|
||||
|
||||
|
||||
#### **原码**
|
||||
|
||||
|
||||
* **规则**: 符号位 + 数值的绝对值的二进制表示。
|
||||
* **正数**: 符号位为0,其余位表示数值。
|
||||
* 例如,$+12$ 的原码是 **00001100**。
|
||||
* **负数**: 符号位为1,其余位表示数值。
|
||||
* 例如,$-12$ 的原码是 **10001100**。
|
||||
* **缺点**:
|
||||
1. 零的表示不唯一:$+0$ 是 **00000000**,$-0$ 是 **10000000**。
|
||||
2. 进行加减法运算时,需要单独处理符号位,硬件实现复杂。
|
||||
|
||||
#### **反码**
|
||||
|
||||
反码的出现是为了简化减法运算。
|
||||
|
||||
* **规则**:
|
||||
* **正数**的反码与其原码**相同**。
|
||||
* **负数**的反码是在其**原码**的基础上,**符号位不变**,其余各位**按位取反**。
|
||||
* **示例**:
|
||||
* $+12$ 的原码是 `00001100`,其反码也是 **00001100**。
|
||||
* $-12$ 的原码是 `10001100`,其反码是 **11110011** (符号位1不变,后面7位 `0001100` 按位取反得到 `1110011`)。
|
||||
* **缺点**:
|
||||
* 仍然存在“双零”问题:$+0$ 的反码是 **00000000**,$-0$ 的反码是 **11111111**。
|
||||
* 跨零运算会产生循环进位问题。
|
||||
|
||||
#### **补码**
|
||||
|
||||
补码是现代计算机系统中最常用的有符号数表示法,它解决了原码和反码的缺点。
|
||||
|
||||
* **规则**:
|
||||
* **正数**的补码与其原码**相同**。
|
||||
* **负数**的补码是其**反码加 1**。
|
||||
* **求负数补码的方式**:
|
||||
* 从其原码的**最低位(最右边)**向左找,找到的**第一个 1** 保持不变,这个 1 **左边**的所有位(不含符号位)按位取反,符号位仍为1。
|
||||
* **示例**:
|
||||
* $+12$ 的补码是 **00001100**。
|
||||
* $-12$ 的补码求法:
|
||||
1. 原码: `10001100`
|
||||
2. 反码: `11110011`
|
||||
3. 加 1: `11110011 + 1` = **11110100**。
|
||||
* **优点**:
|
||||
1. **零的表示唯一**: **00000000**。
|
||||
2. **简化运算**: 可以将减法运算转换为加法运算。例如,计算 $A - B$ 等同于计算 $A + (-B)$ 的补码。
|
||||
3. 对于一个 $n$ 位的补码系统,其表示范围为 $[-2^{n-1}, 2^{n-1}-1]$。例如,8位补码的范围是 $[-128, 127]$。
|
||||
|
||||
**总结表格 (以 ±12 为例)**
|
||||
|
||||
| 值 | 原码 | 反码 | 补码 |
|
||||
|:---:|:---:|:---:|:---:|
|
||||
| +12 | 00001100 | 00001100 | 00001100 |
|
||||
| -12 | 10001100 | 11110011 | 11110100 |
|
||||
|
||||
|
||||
|
||||
### 2. BCD 码
|
||||
|
||||
BCD码是用**二进制**来表示**十进制**数的一种编码方式。它与直接将十进制数转换为二进制数不同。
|
||||
|
||||
* **规则**: 用 **4 位二进制数**来表示一位十进制数(0-9)。最常用的是 **8421 BCD 码**,其中各位的权值从高到低分别是 8、4、2、1。
|
||||
* **特点**:
|
||||
* 它介于二进制和十进制之间,便于人机交互(如数码管显示、计算器)。
|
||||
* 运算比纯二进制复杂,但比直接处理十进制字符简单。
|
||||
* 由于用4位二进制表示一位十进制数,所以 `1010` 到 `1111` 这 6 个码是无效或非法的。
|
||||
|
||||
**BCD 码对照表**
|
||||
|
||||
| 十进制 | BCD 码 |
|
||||
|:---:|:---:|
|
||||
| 0 | 0000 |
|
||||
| 1 | 0001 |
|
||||
| 2 | 0010 |
|
||||
| 3 | 0011 |
|
||||
| 4 | 0100 |
|
||||
| 5 | 0101 |
|
||||
| 6 | 0110 |
|
||||
| 7 | 0111 |
|
||||
| 8 | 1000 |
|
||||
| 9 | 1001 |
|
||||
|
||||
**示例**:
|
||||
将十进制数 **129** 转换为 BCD 码。
|
||||
|
||||
1. 将每一位十进制数分开:`1`、`2`、`9`。
|
||||
2. 将每一位分别转换为对应的4位BCD码:
|
||||
* $1 \rightarrow 0001$
|
||||
* $2 \rightarrow 0010$
|
||||
* $9 \rightarrow 1001$
|
||||
3. 将它们组合起来:
|
||||
$$
|
||||
(129)_{10} = (0001 \ 0010 \ 1001)_{\text{BCD}}
|
||||
$$
|
||||
**对比**: 如果将 (129)₁₀ 直接转换为纯二进制,结果是 **10000001**。这与它的 BCD 码是完全不同的。
|
||||
---
|
||||
## 四、加法器、编码器、译码器、选择器、比较器
|
||||
---
|
||||
## 五、触发器
|
||||
|
||||
### 1. RS 触发器
|
||||
|
||||
最基本的触发器,但存在一个不确定状态,在实际应用中较少直接使用。
|
||||
|
||||
* **输入**: $S$ (Set, 置位), $R$ (Reset, 复位)
|
||||
* **输出**: $Q$ (状态输出), $\overline{Q}$ (反向输出)
|
||||
|
||||
#### **功能表**
|
||||
这张表描述了在不同输入下,下一个状态 $Q_{n+1}$ 是什么。
|
||||
|
||||
| $S$ | $R$ | $Q_{n+1}$ | 功能 |
|
||||
|:---:|:---:|:---:|:---|
|
||||
| 0 | 0 | $Q_n$ | 保持 |
|
||||
| 0 | 1 | 0 | 复位/置0 |
|
||||
| 1 | 0 | 1 | 置位/置1|
|
||||
| 1 | 1 | **?** | **禁止/不定** |
|
||||
|
||||
#### **特性方程**
|
||||
$$
|
||||
Q_{n+1} = S + \overline{R}Q_n \quad (\text{约束条件: } S \cdot R = 0)
|
||||
$$
|
||||
|
||||
#### **激励表**
|
||||
这张表在电路设计时非常有用,它回答了“为了让状态从 $Q_n$ 变为 $Q_{n+1}$,输入 $S$ 和 $R$ 应该是什么?”。(X表示Don't Care,即0或1均可)
|
||||
|
||||
| $Q_n$ | $Q_{n+1}$ | $S$ | $R$ |
|
||||
|:---:|:---:|:---:|:---:|
|
||||
| 0 | 0 | 0 | X |
|
||||
| 0 | 1 | 1 | 0 |
|
||||
| 1 | 0 | 0 | 1 |
|
||||
| 1 | 1 | X | 0 |
|
||||
|
||||
|
||||
### 2. JK 触发器
|
||||
|
||||
JK 触发器是 RS 触发器的改进版,它解决了 RS 触发器的“禁止”状态问题,是最通用的触发器。
|
||||
|
||||
* **输入**: $J$ (功能类似 $S$), $K$ (功能类似 $R$)
|
||||
* **输出**: $Q$, $\overline{Q}$
|
||||
|
||||
#### **功能表**
|
||||
|
||||
| $J$ | $K$ | $Q_{n+1}$ | 功能 |
|
||||
|:---:|:---:|:---:|:---|
|
||||
| 0 | 0 | $Q_n$ | 保持 |
|
||||
| 0 | 1 | 0 | 复0 |
|
||||
| 1 | 0 | 1 | 置1 |
|
||||
| 1 | 1 | $\overline{Q_n}$ | **翻转 ** |
|
||||
|
||||
*JK触发器将RS触发器的禁止状态(1,1输入)变成了一个非常有用的**翻转**功能。*
|
||||
|
||||
#### **特性方程**
|
||||
$$
|
||||
Q_{n+1} = J\overline{Q_n} + \overline{K}Q_n
|
||||
$$
|
||||
|
||||
#### **激励表**
|
||||
|
||||
| $Q_n$ | $Q_{n+1}$ | $J$ | $K$ |
|
||||
|:---:|:---:|:---:|:---:|
|
||||
| 0 | 0 | 0 | X |
|
||||
| 0 | 1 | 1 | X |
|
||||
| 1 | 0 | X | 1 |
|
||||
| 1 | 1 | X | 0 |
|
||||
|
||||
|
||||
### 3. D 触发器
|
||||
D 触发器的功能非常直接:在时钟脉冲到来时,将输入 $D$ 的值传递给输出 $Q$。它常被用作数据锁存器或移位寄存器的基本单元。
|
||||
|
||||
* **输入**: $D$ (Data)
|
||||
* **输出**: $Q$, $\overline{Q}$
|
||||
|
||||
#### **功能表**
|
||||
|
||||
| $D$ | $Q_{n+1}$ | 功能 |
|
||||
|:---:|:---:|:---|
|
||||
| 0 | 0 | 置0 |
|
||||
| 1 | 1 | 置1 |
|
||||
|
||||
*无论当前状态 $Q_n$ 是什么,下一个状态 $Q_{n+1}$ 都等于时钟边沿到来时的 $D$ 输入值。*
|
||||
|
||||
#### **特性方程 **
|
||||
$$
|
||||
Q_{n+1} = D
|
||||
$$
|
||||
|
||||
#### **激励表 **
|
||||
|
||||
| $Q_n$ | $Q_{n+1}$ | $D$ |
|
||||
|:---:|:---:|:---:|
|
||||
| 0 | 0 | 0 |
|
||||
| 0 | 1 | 1 |
|
||||
| 1 | 0 | 0 |
|
||||
| 1 | 1 | 1 |
|
||||
|
||||
|
||||
|
||||
### 4. T 触发器
|
||||
|
||||
T 触发器是一个翻转触发器。当输入 $T=1$ 时,状态翻转;当 $T=0$ 时,状态保持不变。它常用于构建计数器。
|
||||
|
||||
* **输入**: $T$
|
||||
* **输出**: $Q$, $\overline{Q}$
|
||||
|
||||
#### **功能表**
|
||||
|
||||
| $T$ | $Q_{n+1}$ | 功能 |
|
||||
|:---:|:---:|:---|
|
||||
| 0 | $Q_n$ | 保持 |
|
||||
| 1 | $\overline{Q_n}$ | 翻转 |
|
||||
|
||||
#### **特性方程**
|
||||
$$
|
||||
Q_{n+1} = T \oplus Q_n = T\overline{Q_n} + \overline{T}Q_n
|
||||
$$
|
||||
|
||||
#### **激励表**
|
||||
|
||||
| $Q_n$ | $Q_{n+1}$ | $T$ |
|
||||
|:---:|:---:|:---:|
|
||||
| 0 | 0 | 0 |
|
||||
| 0 | 1 | 1 |
|
||||
| 1 | 0 | 1 |
|
||||
| 1 | 1 | 0 |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,268 +1,268 @@
|
||||
---
|
||||
title: vllm学习笔记(壹)
|
||||
date: 2025-09-06 23:00:00 # 发布日期和时间,格式:YYYY-MM-DD HH:MM:SS
|
||||
descriptionHTML: '<span style="color:var(--description-font-color);">学习笔记:ray介绍,vllm的作用和主要运行方式</span>'
|
||||
tags: # 文章标签列表,用于分类和搜索
|
||||
- AI
|
||||
- 笔记
|
||||
sidebar: true # 是否显示侧边栏:true显示,false隐藏
|
||||
readingTime: true # 是否显示阅读时间:true显示,false隐藏
|
||||
sticky: 0 # 精选文章设置:值越大在首页展示越靠前,0表示不精选
|
||||
recommend: true
|
||||
---
|
||||
|
||||
# vLLM学习笔记(壹)
|
||||
|
||||
> **版本说明**: 本文基于 vLLM 0.2.7 版本进行分析
|
||||
> **源码位置**: 相关代码主要位于 `vllm/engine/` 和 `vllm/worker/` 目录下
|
||||
|
||||
## Ray框架介绍
|
||||
|
||||
### Ray是什么
|
||||
|
||||
Ray是一个开源的分布式计算框架,专门为机器学习和AI工作负载设计。它提供了简单的API来构建和运行分布式应用程序。
|
||||
|
||||
### Ray中的有状态和无状态
|
||||
|
||||
#### 无状态服务
|
||||
- **特点**: 每次请求都是独立的,不依赖之前的状态
|
||||
- **示例**: HTTP API服务,每个请求处理完就结束
|
||||
|
||||
#### 有状态(Worker)服务
|
||||
- **特点**: 需要维护内部状态,请求之间有依赖关系
|
||||
- **优势**: 可以缓存数据,避免重复计算
|
||||
- **示例**: 数据库连接池,模型推理服务(需要保持模型在内存中)
|
||||
|
||||
在vLLM中,Worker节点就是典型的**有状态服务**,因为它们需要:
|
||||
- 在内存中保持加载的模型
|
||||
- 维护KV Cache状态
|
||||
- 跟踪正在处理的请求状态
|
||||
|
||||
## vLLM的作用与价值
|
||||
|
||||
### 主要作用
|
||||
1. 专门优化大语言模型的推理速度
|
||||
2. 通过PagedAttention技术显著减少内存占用
|
||||
3. 支持动态批处理,提高GPU利用率
|
||||
4. 支持多GPU和多节点部署
|
||||
|
||||
### 核心优势
|
||||
- **PagedAttention**: 将注意力机制的KV Cache分页管理,类似操作系统的虚拟内存
|
||||
- **连续批处理**: 动态调整批大小,无需等待整个批次完成
|
||||
- **零拷贝**: 减少不必要的数据复制操作
|
||||
|
||||
### KV Cache显存分配机制
|
||||
|
||||
在传统的Transformer推理中,KV Cache需要预先分配连续的显存空间,这会造成大量的内存浪费。vLLM通过PagedAttention技术,将KV Cache分割成固定大小的block块进行管理。
|
||||
|
||||
#### Block分配原理
|
||||
####
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "GPU显存空间"
|
||||
subgraph "KV Cache Pool"
|
||||
B1["Block 1<br/>16 tokens<br/>状态: 已分配"]
|
||||
B2["Block 2<br/>16 tokens<br/>状态: 已分配"]
|
||||
B3["Block 3<br/>16 tokens<br/>状态: 空闲"]
|
||||
B4["Block 4<br/>16 tokens<br/>状态: 空闲"]
|
||||
B5["Block 5<br/>16 tokens<br/>状态: 已分配"]
|
||||
B6["Block 6<br/>16 tokens<br/>状态: 空闲"]
|
||||
end
|
||||
|
||||
subgraph "模型权重"
|
||||
MW["Model Weights<br/>固定占用"]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph "请求管理"
|
||||
R1["Request 1<br/>Seq ID: 001<br/>长度: 25 tokens"]
|
||||
R2["Request 2<br/>Seq ID: 002<br/>长度: 18 tokens"]
|
||||
end
|
||||
|
||||
subgraph "Block映射表"
|
||||
BT["Block Table<br/>Seq 001: [Block1, Block2]<br/>Seq 002: [Block5]<br/>Free: [Block3, Block4, Block6]"]
|
||||
end
|
||||
|
||||
R1 --> B1
|
||||
R1 --> B2
|
||||
R2 --> B5
|
||||
|
||||
BT --> B1
|
||||
BT --> B2
|
||||
BT --> B5
|
||||
|
||||
style B1 fill:#ff9999,stroke:#333,stroke-width:2px,color:#000
|
||||
style B2 fill:#ff9999,stroke:#333,stroke-width:2px,color:#000
|
||||
style B5 fill:#ff9999,stroke:#333,stroke-width:2px,color:#000
|
||||
style B3 fill:#99ff99,stroke:#333,stroke-width:2px,color:#000
|
||||
style B4 fill:#99ff99,stroke:#333,stroke-width:2px,color:#000
|
||||
style B6 fill:#99ff99,stroke:#333,stroke-width:2px,color:#000
|
||||
style MW fill:#cce5ff,stroke:#333,stroke-width:2px,color:#000
|
||||
style R1 fill:#fff2cc,stroke:#333,stroke-width:2px,color:#000
|
||||
style R2 fill:#fff2cc,stroke:#333,stroke-width:2px,color:#000
|
||||
style BT fill:#f0f0f0,stroke:#333,stroke-width:2px,color:#000
|
||||
```
|
||||
|
||||
#### 关键特性说明
|
||||
|
||||
1. **固定Block大小**: 每个Block通常包含16个token的KV Cache
|
||||
2. **动态分配**: 根据序列长度动态分配所需的Block数量
|
||||
3. **非连续存储**: Block在物理内存中可以不连续,通过映射表管理
|
||||
4. **高效回收**: 请求完成后立即回收Block,供其他请求使用
|
||||
|
||||
#### 内存利用率对比
|
||||
|
||||
| 方案 | 内存预分配 | 实际使用率 | 浪费率 |
|
||||
|------|------------|------------|--------|
|
||||
| 传统方案 | 最大序列长度 | 20-30% | 70-80% |
|
||||
| PagedAttention | 按需分配 | 90-95% | 5-10% |
|
||||
|
||||
#### Block管理的具体流程
|
||||
|
||||
```python
|
||||
# 位置: vllm/core/block_manager.py
|
||||
class BlockManager:
|
||||
def allocate_blocks(self, sequence_length):
|
||||
"""为序列分配所需的Block"""
|
||||
blocks_needed = math.ceil(sequence_length / self.block_size)
|
||||
allocated_blocks = []
|
||||
|
||||
for _ in range(blocks_needed):
|
||||
if self.free_blocks:
|
||||
block = self.free_blocks.pop()
|
||||
allocated_blocks.append(block)
|
||||
else:
|
||||
# 内存不足,触发抢占机制
|
||||
self.preempt_sequences()
|
||||
|
||||
return allocated_blocks
|
||||
|
||||
def free_blocks(self, sequence_id):
|
||||
"""释放序列占用的Block"""
|
||||
blocks = self.sequence_to_blocks[sequence_id]
|
||||
self.free_blocks.extend(blocks)
|
||||
del self.sequence_to_blocks[sequence_id]
|
||||
```
|
||||
|
||||
这种设计的优势:
|
||||
- **内存碎片化最小**: 固定大小的Block避免了内存碎片
|
||||
- **动态扩展**: 序列可以根据需要动态申请更多Block
|
||||
- **共享机制**: 多个序列可以共享相同的prefix Block(如系统提示词)
|
||||
|
||||
## vLLM运作方式详解
|
||||
|
||||
### 整体架构流程
|
||||
|
||||
```
|
||||
用户请求 → LLMEngine → Scheduler → Workers → GPU推理 → 结果返回
|
||||
```
|
||||
|
||||
### 详细运作步骤
|
||||
|
||||
1. `LLMEngine`接收用户的文本生成请求
|
||||
2. `Scheduler`决定哪些请求可以被处理
|
||||
3. 为请求分配GPU内存和计算资源
|
||||
4. 多个`Worker`并行执行推理任务
|
||||
5. 收集各Worker的输出并返回给用户
|
||||
|
||||
## 调度器(Scheduler)详解
|
||||
|
||||
### 调度器的核心职责
|
||||
|
||||
调度器是vLLM的"大脑",主要负责:
|
||||
|
||||
#### 1. 请求管理
|
||||
```python
|
||||
# 位置: vllm/engine/llm_engine.py
|
||||
class LLMEngine:
|
||||
def __init__(self):
|
||||
self.scheduler = Scheduler(...)
|
||||
```
|
||||
|
||||
#### 2. 资源调度策略
|
||||
1. 跟踪可用的GPU内存
|
||||
2. 决定哪些请求可以组成一个批次
|
||||
3. 根据请求的优先级和到达时间排序
|
||||
|
||||
|
||||
### 调度算法核心逻辑
|
||||
|
||||
```python
|
||||
# 简化的调度逻辑示例
|
||||
def schedule_requests(self):
|
||||
# 1. 检查可用资源
|
||||
available_memory = self.get_available_memory()
|
||||
|
||||
# 2. 选择可执行的请求
|
||||
executable_requests = []
|
||||
for request in self.waiting_requests:
|
||||
if self.can_allocate(request, available_memory):
|
||||
executable_requests.append(request)
|
||||
|
||||
# 3. 返回调度结果
|
||||
return executable_requests
|
||||
```
|
||||
|
||||
## Worker的作用与机制
|
||||
|
||||
### Worker的核心功能
|
||||
|
||||
Worker是vLLM的"执行者",每个Worker负责:
|
||||
|
||||
#### 1. 模型加载与管理
|
||||
```python
|
||||
# 位置: vllm/worker/worker.py
|
||||
class Worker:
|
||||
def __init__(self):
|
||||
self.model_runner = ModelRunner(...)
|
||||
self.cache_engine = CacheEngine(...)
|
||||
```
|
||||
|
||||
#### 2. 推理执行
|
||||
- **前向传播**: 执行模型的前向计算
|
||||
- **KV缓存管理**: 管理注意力机制的键值缓存
|
||||
- **内存分配**: 为每个请求分配必要的内存空间
|
||||
|
||||
#### 3. 状态维护
|
||||
- **请求状态跟踪**: 记录每个请求的处理进度
|
||||
- **缓存状态管理**: 维护PagedAttention的页面状态
|
||||
- **错误处理**: 处理推理过程中的异常情况
|
||||
|
||||
### Worker的工作流程
|
||||
|
||||
1. **初始化**: 加载模型权重,初始化缓存引擎
|
||||
2. **接收任务**: 从调度器接收批处理任务
|
||||
3. **执行推理**: 并行处理批次中的所有请求
|
||||
4. **返回结果**: 将推理结果返回给引擎
|
||||
|
||||
## 关键代码文件位置
|
||||
|
||||
### 主要源码文件结构
|
||||
|
||||
```
|
||||
vllm/
|
||||
├── engine/
|
||||
│ ├── llm_engine.py # 主引擎,协调整个推理流程
|
||||
│ └── async_llm_engine.py # 异步版本的引擎
|
||||
├── core/
|
||||
│ ├── scheduler.py # 调度器核心逻辑
|
||||
│ └── block_manager.py # 内存块管理器
|
||||
├── worker/
|
||||
│ ├── worker.py # Worker基类实现
|
||||
│ └── model_runner.py # 模型运行器
|
||||
└── attention/
|
||||
└── backends/ # PagedAttention实现
|
||||
```
|
||||
|
||||
### 重要文件说明
|
||||
|
||||
- **`vllm/engine/llm_engine.py`**: 整个系统的入口点和协调中心
|
||||
- **`vllm/core/scheduler.py`**: 实现了复杂的请求调度算法
|
||||
- **`vllm/worker/worker.py`**: Worker的具体实现逻辑
|
||||
- **`vllm/core/block_manager.py`**: PagedAttention的内存管理实现
|
||||
|
||||
## 总结
|
||||
|
||||
vLLM通过Ray框架实现分布式推理,采用有状态的Worker设计来保持模型和缓存状态。其核心创新在于PagedAttention技术和智能调度系统,大幅提升了大语言模型的推理效率和资源利用率。
|
||||
|
||||
---
|
||||
title: vllm学习笔记(壹)
|
||||
date: 2025-09-06 23:00:00 # 发布日期和时间,格式:YYYY-MM-DD HH:MM:SS
|
||||
descriptionHTML: '<span style="color:var(--description-font-color);">学习笔记:ray介绍,vllm的作用和主要运行方式</span>'
|
||||
tags: # 文章标签列表,用于分类和搜索
|
||||
- AI
|
||||
- 笔记
|
||||
sidebar: true # 是否显示侧边栏:true显示,false隐藏
|
||||
readingTime: true # 是否显示阅读时间:true显示,false隐藏
|
||||
sticky: 0 # 精选文章设置:值越大在首页展示越靠前,0表示不精选
|
||||
recommend: true
|
||||
---
|
||||
|
||||
# vLLM学习笔记(壹)
|
||||
|
||||
> **版本说明**: 本文基于 vLLM 0.2.7 版本进行分析
|
||||
> **源码位置**: 相关代码主要位于 `vllm/engine/` 和 `vllm/worker/` 目录下
|
||||
|
||||
## Ray框架介绍
|
||||
|
||||
### Ray是什么
|
||||
|
||||
Ray是一个开源的分布式计算框架,专门为机器学习和AI工作负载设计。它提供了简单的API来构建和运行分布式应用程序。
|
||||
|
||||
### Ray中的有状态和无状态
|
||||
|
||||
#### 无状态服务
|
||||
- **特点**: 每次请求都是独立的,不依赖之前的状态
|
||||
- **示例**: HTTP API服务,每个请求处理完就结束
|
||||
|
||||
#### 有状态(Worker)服务
|
||||
- **特点**: 需要维护内部状态,请求之间有依赖关系
|
||||
- **优势**: 可以缓存数据,避免重复计算
|
||||
- **示例**: 数据库连接池,模型推理服务(需要保持模型在内存中)
|
||||
|
||||
在vLLM中,Worker节点就是典型的**有状态服务**,因为它们需要:
|
||||
- 在内存中保持加载的模型
|
||||
- 维护KV Cache状态
|
||||
- 跟踪正在处理的请求状态
|
||||
|
||||
## vLLM的作用与价值
|
||||
|
||||
### 主要作用
|
||||
1. 专门优化大语言模型的推理速度
|
||||
2. 通过PagedAttention技术显著减少内存占用
|
||||
3. 支持动态批处理,提高GPU利用率
|
||||
4. 支持多GPU和多节点部署
|
||||
|
||||
### 核心优势
|
||||
- **PagedAttention**: 将注意力机制的KV Cache分页管理,类似操作系统的虚拟内存
|
||||
- **连续批处理**: 动态调整批大小,无需等待整个批次完成
|
||||
- **零拷贝**: 减少不必要的数据复制操作
|
||||
|
||||
### KV Cache显存分配机制
|
||||
|
||||
在传统的Transformer推理中,KV Cache需要预先分配连续的显存空间,这会造成大量的内存浪费。vLLM通过PagedAttention技术,将KV Cache分割成固定大小的block块进行管理。
|
||||
|
||||
#### Block分配原理
|
||||
####
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "GPU显存空间"
|
||||
subgraph "KV Cache Pool"
|
||||
B1["Block 1<br/>16 tokens<br/>状态: 已分配"]
|
||||
B2["Block 2<br/>16 tokens<br/>状态: 已分配"]
|
||||
B3["Block 3<br/>16 tokens<br/>状态: 空闲"]
|
||||
B4["Block 4<br/>16 tokens<br/>状态: 空闲"]
|
||||
B5["Block 5<br/>16 tokens<br/>状态: 已分配"]
|
||||
B6["Block 6<br/>16 tokens<br/>状态: 空闲"]
|
||||
end
|
||||
|
||||
subgraph "模型权重"
|
||||
MW["Model Weights<br/>固定占用"]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph "请求管理"
|
||||
R1["Request 1<br/>Seq ID: 001<br/>长度: 25 tokens"]
|
||||
R2["Request 2<br/>Seq ID: 002<br/>长度: 18 tokens"]
|
||||
end
|
||||
|
||||
subgraph "Block映射表"
|
||||
BT["Block Table<br/>Seq 001: [Block1, Block2]<br/>Seq 002: [Block5]<br/>Free: [Block3, Block4, Block6]"]
|
||||
end
|
||||
|
||||
R1 --> B1
|
||||
R1 --> B2
|
||||
R2 --> B5
|
||||
|
||||
BT --> B1
|
||||
BT --> B2
|
||||
BT --> B5
|
||||
|
||||
style B1 fill:#ff9999,stroke:#333,stroke-width:2px,color:#000
|
||||
style B2 fill:#ff9999,stroke:#333,stroke-width:2px,color:#000
|
||||
style B5 fill:#ff9999,stroke:#333,stroke-width:2px,color:#000
|
||||
style B3 fill:#99ff99,stroke:#333,stroke-width:2px,color:#000
|
||||
style B4 fill:#99ff99,stroke:#333,stroke-width:2px,color:#000
|
||||
style B6 fill:#99ff99,stroke:#333,stroke-width:2px,color:#000
|
||||
style MW fill:#cce5ff,stroke:#333,stroke-width:2px,color:#000
|
||||
style R1 fill:#fff2cc,stroke:#333,stroke-width:2px,color:#000
|
||||
style R2 fill:#fff2cc,stroke:#333,stroke-width:2px,color:#000
|
||||
style BT fill:#f0f0f0,stroke:#333,stroke-width:2px,color:#000
|
||||
```
|
||||
|
||||
#### 关键特性说明
|
||||
|
||||
1. **固定Block大小**: 每个Block通常包含16个token的KV Cache
|
||||
2. **动态分配**: 根据序列长度动态分配所需的Block数量
|
||||
3. **非连续存储**: Block在物理内存中可以不连续,通过映射表管理
|
||||
4. **高效回收**: 请求完成后立即回收Block,供其他请求使用
|
||||
|
||||
#### 内存利用率对比
|
||||
|
||||
| 方案 | 内存预分配 | 实际使用率 | 浪费率 |
|
||||
|------|------------|------------|--------|
|
||||
| 传统方案 | 最大序列长度 | 20-30% | 70-80% |
|
||||
| PagedAttention | 按需分配 | 90-95% | 5-10% |
|
||||
|
||||
#### Block管理的具体流程
|
||||
|
||||
```python
|
||||
# 位置: vllm/core/block_manager.py
|
||||
class BlockManager:
|
||||
def allocate_blocks(self, sequence_length):
|
||||
"""为序列分配所需的Block"""
|
||||
blocks_needed = math.ceil(sequence_length / self.block_size)
|
||||
allocated_blocks = []
|
||||
|
||||
for _ in range(blocks_needed):
|
||||
if self.free_blocks:
|
||||
block = self.free_blocks.pop()
|
||||
allocated_blocks.append(block)
|
||||
else:
|
||||
# 内存不足,触发抢占机制
|
||||
self.preempt_sequences()
|
||||
|
||||
return allocated_blocks
|
||||
|
||||
def free_blocks(self, sequence_id):
|
||||
"""释放序列占用的Block"""
|
||||
blocks = self.sequence_to_blocks[sequence_id]
|
||||
self.free_blocks.extend(blocks)
|
||||
del self.sequence_to_blocks[sequence_id]
|
||||
```
|
||||
|
||||
这种设计的优势:
|
||||
- **内存碎片化最小**: 固定大小的Block避免了内存碎片
|
||||
- **动态扩展**: 序列可以根据需要动态申请更多Block
|
||||
- **共享机制**: 多个序列可以共享相同的prefix Block(如系统提示词)
|
||||
|
||||
## vLLM运作方式详解
|
||||
|
||||
### 整体架构流程
|
||||
|
||||
```
|
||||
用户请求 → LLMEngine → Scheduler → Workers → GPU推理 → 结果返回
|
||||
```
|
||||
|
||||
### 详细运作步骤
|
||||
|
||||
1. `LLMEngine`接收用户的文本生成请求
|
||||
2. `Scheduler`决定哪些请求可以被处理
|
||||
3. 为请求分配GPU内存和计算资源
|
||||
4. 多个`Worker`并行执行推理任务
|
||||
5. 收集各Worker的输出并返回给用户
|
||||
|
||||
## 调度器(Scheduler)详解
|
||||
|
||||
### 调度器的核心职责
|
||||
|
||||
调度器是vLLM的"大脑",主要负责:
|
||||
|
||||
#### 1. 请求管理
|
||||
```python
|
||||
# 位置: vllm/engine/llm_engine.py
|
||||
class LLMEngine:
|
||||
def __init__(self):
|
||||
self.scheduler = Scheduler(...)
|
||||
```
|
||||
|
||||
#### 2. 资源调度策略
|
||||
1. 跟踪可用的GPU内存
|
||||
2. 决定哪些请求可以组成一个批次
|
||||
3. 根据请求的优先级和到达时间排序
|
||||
|
||||
|
||||
### 调度算法核心逻辑
|
||||
|
||||
```python
|
||||
# 简化的调度逻辑示例
|
||||
def schedule_requests(self):
|
||||
# 1. 检查可用资源
|
||||
available_memory = self.get_available_memory()
|
||||
|
||||
# 2. 选择可执行的请求
|
||||
executable_requests = []
|
||||
for request in self.waiting_requests:
|
||||
if self.can_allocate(request, available_memory):
|
||||
executable_requests.append(request)
|
||||
|
||||
# 3. 返回调度结果
|
||||
return executable_requests
|
||||
```
|
||||
|
||||
## Worker的作用与机制
|
||||
|
||||
### Worker的核心功能
|
||||
|
||||
Worker是vLLM的"执行者",每个Worker负责:
|
||||
|
||||
#### 1. 模型加载与管理
|
||||
```python
|
||||
# 位置: vllm/worker/worker.py
|
||||
class Worker:
|
||||
def __init__(self):
|
||||
self.model_runner = ModelRunner(...)
|
||||
self.cache_engine = CacheEngine(...)
|
||||
```
|
||||
|
||||
#### 2. 推理执行
|
||||
- **前向传播**: 执行模型的前向计算
|
||||
- **KV缓存管理**: 管理注意力机制的键值缓存
|
||||
- **内存分配**: 为每个请求分配必要的内存空间
|
||||
|
||||
#### 3. 状态维护
|
||||
- **请求状态跟踪**: 记录每个请求的处理进度
|
||||
- **缓存状态管理**: 维护PagedAttention的页面状态
|
||||
- **错误处理**: 处理推理过程中的异常情况
|
||||
|
||||
### Worker的工作流程
|
||||
|
||||
1. **初始化**: 加载模型权重,初始化缓存引擎
|
||||
2. **接收任务**: 从调度器接收批处理任务
|
||||
3. **执行推理**: 并行处理批次中的所有请求
|
||||
4. **返回结果**: 将推理结果返回给引擎
|
||||
|
||||
## 关键代码文件位置
|
||||
|
||||
### 主要源码文件结构
|
||||
|
||||
```
|
||||
vllm/
|
||||
├── engine/
|
||||
│ ├── llm_engine.py # 主引擎,协调整个推理流程
|
||||
│ └── async_llm_engine.py # 异步版本的引擎
|
||||
├── core/
|
||||
│ ├── scheduler.py # 调度器核心逻辑
|
||||
│ └── block_manager.py # 内存块管理器
|
||||
├── worker/
|
||||
│ ├── worker.py # Worker基类实现
|
||||
│ └── model_runner.py # 模型运行器
|
||||
└── attention/
|
||||
└── backends/ # PagedAttention实现
|
||||
```
|
||||
|
||||
### 重要文件说明
|
||||
|
||||
- **`vllm/engine/llm_engine.py`**: 整个系统的入口点和协调中心
|
||||
- **`vllm/core/scheduler.py`**: 实现了复杂的请求调度算法
|
||||
- **`vllm/worker/worker.py`**: Worker的具体实现逻辑
|
||||
- **`vllm/core/block_manager.py`**: PagedAttention的内存管理实现
|
||||
|
||||
## 总结
|
||||
|
||||
vLLM通过Ray框架实现分布式推理,采用有状态的Worker设计来保持模型和缓存状态。其核心创新在于PagedAttention技术和智能调度系统,大幅提升了大语言模型的推理效率和资源利用率。
|
||||
|
||||
|
||||
171
docs/sop/notes/vllm-learning-notes-pre.md
Normal file
171
docs/sop/notes/vllm-learning-notes-pre.md
Normal file
@@ -0,0 +1,171 @@
|
||||
---
|
||||
title: vllm汇报稿
|
||||
date: 2025-09-26 23:00:00 # 发布日期和时间,格式:YYYY-MM-DD HH:MM:SS
|
||||
descriptionHTML: '<span style="color:var(--description-font-color);">预汇报稿件</span>'
|
||||
tags: # 文章标签列表,用于分类和搜索
|
||||
- AI
|
||||
- 笔记
|
||||
sidebar: true # 是否显示侧边栏:true显示,false隐藏
|
||||
readingTime: true # 是否显示阅读时间:true显示,false隐藏
|
||||
sticky: 0 # 精选文章设置:值越大在首页展示越靠前,0表示不精选
|
||||
recommend: true
|
||||
---
|
||||
|
||||
# vLLM 报告
|
||||
|
||||
> 主题聚焦:**PagedAttention 分页注意力、整体架构、调度器原理、Worker 原理、PP 与 TP 的区别、预填充(Prefill)与解码(Decode)**
|
||||
|
||||
## 1. 为什么需要 PagedAttention
|
||||
|
||||
### 1.1 传统 KV Cache 的两类浪费
|
||||
|
||||
* **内部碎片**:必须为每个请求按“可能最长序列(prompt+output)”预留 **连续** KV 空间,未用到的预留位被浪费。
|
||||
* **外部碎片**:全局连续大块分配导致“零头”拼不起来,无法切给其他请求。
|
||||
* **共享缺失**:**相同前缀的 KV** 无法复用,重复存储。
|
||||
|
||||
|
||||
### 1.2 PagedAttention 的核心思路
|
||||
|
||||
* 预分配一大块显存,**切成固定大小的 block**。
|
||||
* 逻辑上给每个序列分配 **Logical Blocks**,实际落在 **Physical Blocks**;两者通过 **Block Table** 映射。
|
||||
* 最多浪费 < block_size 个 slot,**显著减少内外部碎片**。
|
||||
|
||||
---
|
||||
|
||||
## 2. vLLM 的总体架构(抓主线)
|
||||
|
||||
|
||||
* **LLMEngine**:一次迭代做三件事:`schedule()` → `execute_model()` → `process_outputs()`。
|
||||
* **Scheduler**:决定本轮处理哪些请求、是否换入/换出 KV。
|
||||
* **Worker / ModelRunner**:执行模型前向,读写 KV cache,采样下一个 token。
|
||||
* **CacheEngine**:分配/维护 KV Blocks(GPU/CPU)、管理 **swap in/out、copy** 的 CUDA 流与事件。
|
||||
|
||||
---
|
||||
|
||||
## 3. 调度器原理(continuous batching)
|
||||
|
||||
### 3.1 核心策略
|
||||
|
||||
* **Iteration-level(continuous batching)**:每生成一个 token 后**重新调度**,因此 batch 大小可变。
|
||||
* **阶段区分**:vLLM 将请求分为 **Prefill(填充)** 与 **Decode(生成)** 两类批次,**同一轮只处理同一阶段**。
|
||||
|
||||
### 3.2 三个队列
|
||||
|
||||
* **waiting**:刚到达的请求,尚未分配 GPU blocks(只分配逻辑块)。
|
||||
* **running**:正在解码或已完成 prefill 的请求。
|
||||
* **swapped**:因显存不足被抢占、KV 暂存在 CPU 的请求。
|
||||
|
||||
### 3.3 块管理关键路径
|
||||
|
||||
* **BlockSpaceManager.can_allocate()**:预判 waiting 请求的 prompt 是否能拿到足够的 GPU blocks。
|
||||
* **allocate()**:为 prompt 的每个逻辑块绑定一个物理块。
|
||||
* **can_append_slot() / append_slot()**(解码迭代):若最后一个物理块**独占**则直接追加,否则触发复制。
|
||||
|
||||
### 3.4 抢占与换入/换出
|
||||
|
||||
* **Recompute**:单序列分支,释放 GPU 块,下次换回后**重算** KV。
|
||||
* **Swap**:多分支或不宜重算的场景,把物理块搬到 CPU;后续再 **swap-in** 回 GPU。
|
||||
* **优先级**:`swapped` 队列优先于 `waiting`。
|
||||
|
||||
---
|
||||
|
||||
## 4. Worker 原理(模型执行链路)
|
||||
|
||||
### 4.1 角色与初始化
|
||||
|
||||
* **Worker ↔ GPU**:一张卡一个 Worker;多卡时配合 **Tensor Parallel(TP)** 切分模型。
|
||||
* 初始化步骤:加载权重 → 建立分布式组 → **profile** 可用块 → **init CacheEngine** →(可选)**CUDA Graph** 预捕获。
|
||||
|
||||
### 4.2 一次执行(`execute_model`)
|
||||
|
||||
1. **状态同步**:驱动 Worker 广播批次规模与内存操作。
|
||||
2. **数据交换**:调用 CacheEngine 的 `swap_in/out`、`copy`。
|
||||
3. **准备输入**:生成 `input_tokens / positions / input_metadata`。
|
||||
4. **前向**:
|
||||
|
||||
* **Prefill**:走 FlashAttn;
|
||||
* **Decode**:走 PagedAttention 内核。
|
||||
5. **采样**:产生下一个 token。
|
||||
|
||||
### 4.3 CacheEngine 的数据结构
|
||||
|
||||
* 每层有 **key_blocks / value_blocks**。
|
||||
* **Block Table**:记录 `seq_id → [block_numbers...]`。
|
||||
* **slot_mapping**:映射“本轮 token”写入到物理块的哪个 slot。
|
||||
|
||||
---
|
||||
|
||||
## 5. Prefill vs Decode(执行特点与调优,展开版)
|
||||
|
||||
### Prefill(填充阶段)
|
||||
|
||||
* **目标**:对完整 prompt 做一次性前向传播,构建 KV 缓存,并生成第一个 token。
|
||||
* **数据特征**:长序列、少批次、padding 多、计算密集。
|
||||
* **实现**:FlashAttention;输入 `_prepare_prompt`,输出第一个 token。
|
||||
* **瓶颈**:HBM 带宽、padding 浪费、长 prompt 拖慢 batch。
|
||||
* **调优**:限制 `max_num_batched_tokens`,分批/压缩长 prompt,减少 padding。
|
||||
|
||||
### Decode(解码阶段)
|
||||
|
||||
* **目标**:逐 token 生成。
|
||||
* **数据特征**:迭代频繁、短序列、并发依赖多。
|
||||
* **实现**:PagedAttention;输入 `_prepare_decode`,只追加一个 slot。
|
||||
* **瓶颈**:Kernel 启动开销、随机访存、并发不足。
|
||||
* **调优**:提高 `max_num_seqs`、用 CUDA Graph、调整 block_size、控制采样分支。
|
||||
|
||||
### Prefill vs Decode 对比总结
|
||||
|
||||
| 维度 | Prefill | Decode |
|
||||
| ---------------- | --------------------- | -------------------------- |
|
||||
| **目标** | 编码完整 prompt,建立 KV 前缀 | 逐 token 生成 |
|
||||
| **批次特征** | 少批次、长序列、padding 多 | 多批次、短序列、迭代频繁 |
|
||||
| **Attention 路径** | FlashAttention | PagedAttention |
|
||||
| **主要瓶颈** | HBM 带宽 + Padding | Kernel Overhead + 随机访存 |
|
||||
| **优化抓手** | 控制 padding、限制长 prompt | 提升并发、CUDA Graph、block size |
|
||||
|
||||
---
|
||||
|
||||
## 6. TP 与 PP:概念、区别与 vLLM 现状
|
||||
|
||||
* **TP(Tensor Parallelism)**:层内张量切分;通信频繁;适合实时推理。
|
||||
* **PP(Pipeline Parallelism)**:层间切分;通信少但需流水线调度;更多见于训练。
|
||||
* **vLLM 支持**:TP 是主力;PP 支持有限。
|
||||
|
||||
---
|
||||
|
||||
## 7. 关键流程串讲
|
||||
|
||||
### Prefill 批
|
||||
|
||||
1. waiting 进入 running;BlockSpaceManager 分配块;
|
||||
2. Worker `_prepare_prompt` → FlashAttn → 写入 KV;
|
||||
3. Sampler 采样首 token。
|
||||
|
||||
### Decode 批
|
||||
|
||||
1. Scheduler 选择 running 序列;
|
||||
2. `_append_slot` 写 KV;
|
||||
3. Worker 调 PagedAttention → 输出;
|
||||
4. 采样 → EOS/长度 → 释放序列。
|
||||
|
||||
---
|
||||
|
||||
## 8. 参数与调优清单
|
||||
|
||||
* **`block_size`**:16;权衡碎片与索引开销。
|
||||
* **`gpu_memory_utilization`**:估算可分配 KV;预留峰值空间。
|
||||
* **`max_num_seqs`**:提升解码并发。
|
||||
* **`max_num_batched_tokens`**:限制长 prompt。
|
||||
* **`swap_space_bytes`**:CPU 交换空间,优先考虑 Recompute。
|
||||
* **采样参数**:top-k/top-p/温度/惩罚影响解码步数。
|
||||
* **CUDA Graph**:捕获稳定批,降低开销。
|
||||
|
||||
---
|
||||
|
||||
## 9. 可讲的亮点/考点总结
|
||||
|
||||
1. **PagedAttention**:block 化 + 块表管理,解决碎片问题。
|
||||
2. **continuous batching**:每 token 重调度,提升吞吐。
|
||||
3. **Recompute vs Swap**:计算 vs 带宽权衡。
|
||||
4. **TP 优先,PP 备选**。
|
||||
5. **Prefill vs Decode**:不同执行路径与瓶颈决定不同调优抓手。
|
||||
Reference in New Issue
Block a user