第2章:计算基础与数据流——计算机体系结构回顾
各位同学,咱们今天聊聊计算机体系结构里最基础、也最绕不开的两个概念:冯·诺依曼架构和哈佛架构。说实话,我当年刚入行时,觉得这东西就是背背定义,直到后来做AI芯片映射,才发现这些底层结构直接决定了你的算子能跑多快。
2.1 冯·诺依曼与哈佛架构:存储与指令的博弈
冯·诺依曼架构,说白了就是「指令和数据共用一套存储总线」。你想想看,CPU取指令和读写数据都挤在同一条路上,这就带来了著名的「冯·诺依曼瓶颈」。我在做早期的CNN加速器时,就遇到过这种情况:卷积核权重加载和指令读取互相抢带宽,导致计算单元经常空等。
哈佛架构呢?它把指令存储和数据存储分开了,各走各的路。这样取指令和访存就能并行进行。嗯,这里要注意:现代很多DSP和嵌入式处理器都采用改进型哈佛架构——指令和数据物理上分开,但可以共享一部分地址空间。
我个人习惯在算子映射时先画一张「访存冲突图」:哪些数据是频繁读取的?哪些指令是循环执行的?如果指令和数据有严重冲突,我会优先考虑哈佛式的分离设计。
2.2 数据流驱动计算模型:让数据自己找路
传统的控制流计算是「指令驱动」——程序计数器告诉你下一步做什么。数据流计算反过来:数据准备好了,计算就自动触发。这有点像流水线上的工人:零件到了,你手里的活就开始干,不用等老板喊你。
我在做稀疏矩阵运算时,特别喜欢数据流模型。为什么呢?因为稀疏矩阵里很多元素是0,传统控制流要一条条指令判断「是不是0」,浪费大量时钟周期。数据流模型下,只有非零数据才会触发计算,效率直接翻倍。
数据流模型有几个关键特征:
- 数据驱动:操作数就绪即执行,没有显式的指令顺序
- 无副作用:每个计算节点只依赖输入,不修改全局状态
- 天然并行:只要数据依赖允许,所有节点可以同时运行
2.3 SIMT与SIMD架构对比:单指令多数据的两种面孔
SIMD(单指令多数据)和SIMT(单指令多线程)经常被混为一谈,其实差别很大。我画个图帮你理解:
SIMD就像军训队列——所有人同时做同一个动作,步调完全一致。SIMT更像一个班级——大家听同一个老师讲课(同一指令),但每个人可以有自己的笔记本(私有寄存器),有人可以举手问问题(分支)。
我拿矩阵乘法举个例子:
// SIMD 风格:数据打包
__m128 a = _mm_load_ps(&A[i]);
__m128 b = _mm_load_ps(&B[j]);
__m128 c = _mm_mul_ps(a, b); // 4个乘法同时完成
// SIMT 风格:线程独立
int tid = threadIdx.x;
float result = A[tid] * B[tid]; // 每个线程算自己的
在实际AI芯片中,GPU用的是SIMT,而很多NPU用的是SIMD。为什么?GPU需要处理各种不规则的分支(比如不同像素的着色器),SIMT更灵活。NPU处理的是规整的卷积、全连接,SIMD的确定性更高,硬件开销更小。
2.4 三种模型的融合:现代AI芯片的实践
你可能会问:这三种模型到底选哪个?我的答案是:全都要。现代AI芯片往往是混合体。
| 架构特征 | 冯·诺依曼 | 哈佛 | 数据流 |
|---|---|---|---|
| 指令存储 | 与数据共享 | 独立 | 隐含在数据依赖中 |
| 并行粒度 | 指令级 | 指令级+访存并行 | 数据级+任务级 |
| 典型应用 | 通用CPU | DSP、MCU | 脉动阵列、稀疏加速器 |
| AI芯片中的角色 | 控制核、调度 | 权重存储、指令缓存 | 计算核心(如Systolic Array) |
举个例子,Google的TPU:控制部分用冯·诺依曼(取指令、调度),权重存储用哈佛思想(独立SRAM),计算核心用数据流(脉动阵列里数据自动流动)。你看,三个模型在一个芯片里和谐共处。
好了,这一章的内容就到这里。记住:体系结构不是死板的教条,而是你手里的工具箱。遇到不同的算子,拿出合适的工具来用就行。
—— 一个在AI芯片坑里摸爬滚打多年的工程师