# 零经验、两周、30多次编译：他从零写出一个能跑的GPU

> Cognitive Revolution No. 133 中文精读

- 原标题：TinyGPU, Massive Learning, with Adam Majmudar
- 发布日期：2024-05-06
- 主持：Nathan Labenz
- 网页版：https://cogrev.1mmt.com/ep/133-tinygpu-massive-learning-with-adam-majmudar-WulkHH.html
- 精读字数：约 5544 字（阅读约 12 分钟）

> 本文为 cogrev.1mmt.com 基于原始访谈的 AI 改写中文精读，非官方翻译；引用请注明出处并链接网页版。

一个从没设计过GPU的人，用两周时间从零写出了一个GPU。能跑矩阵加法，能跑矩阵乘法，代码全部开源，项目叫TinyGPU。整套设计流程在他的笔记本上跑一遍要20多分钟、50个步骤，他攒了30多次报错的运行记录才跑通。按传统路径，大学里学完计算机架构、再到能动手设计芯片，通常要两到三年。Adam Majmudar给自己定的目标，是把这段时间压缩100倍。

这是播客Cognitive Revolution的一期节目，主持人Nathan Labenz把这位TinyGPU作者请来，从软件层到硬件层把GPU拆了一遍。听完的感受很直接：GPU的核心逻辑其实相当好懂，一期节目就能搭出骨架；同时，AI正在实实在在地改变一个人学新东西的速度。

先交代背景。Adam大学期间开始创业，做了三年，最近停了下来。之后他给自己安排了一系列行业深潜，挑的都是未来一到二十年会变得重要的技术，也是他一直有兴趣的方向。每进入一个行业，他问同一个问题：**多快能同时达到技术能力和行业理解？**

芯片是他的第一个深潜对象，计划是两个两周冲刺。第一个两周，把芯片工程的整个链条过一遍：EDA（电子设计自动化，把架构设计变成芯片版图的软件）、制造流程、架构设计，这套内容在学校里对应两到三年的课程量。他有个判断，叫99/1法则：**一门学科里，1%的概念承载了绝大部分价值**。花三年学，买到的是全面和细节；花两周学，目标是把那1%抽出来。第二个两周，他要找个项目验证学到的东西。GPU一头连着图形，一头连着AI加速器、TPU这整片领域，拿它当地基最合适，TinyGPU就这么来了。

## 学造芯片，门槛卡在工具上

为什么几乎没人这么干过？Adam先对比了CPU。CPU足够老，教学资源能铺到很深的层：大学课程会教你控制信号，教你机器语言怎么变成芯片里的动作，软硬件之间是打通的，所以你能从零复刻一个CPU。GPU完全相反。NVIDIA和AMD公开的只有高层架构图，往下没有任何把东西拆简单、让人能自己动手实现一份的资料。Intel倒是公开过一些低层图，但那是生产级设计，复杂到没法当教材。

工具更卡人。行业里真正用来做芯片设计的EDA软件，Synopsys和Cadence的产品，一个席位动辄几十万美元，公司级授权上百万，个人基本碰不到。让这件事变得可能的是过去十年出现的三样东西：

- OpenROAD：DARPA资助的开源EDA软件，功能不如生产级工具全，个人和小项目够用；
- SkyWater的开源PDK：这家代工厂把自己的130纳米工艺节点开源了，晶体管尺寸不小，但流程是真的；
- Efabless和TinyTapeout：Efabless提供拼单流片，1万美元能拿100颗芯片；Matt Venn创办的TinyTapeout把一颗芯片切成约100个小格子，100个项目分摊成本。Adam称Matt Venn是如今让ASIC变得人人可做的关键人物，他还配套了一套从零到流片的课程，叫Zero to ASIC。

Nathan问，除了学习，这东西有什么用？Adam的判断是：大公司永远会走生产级工具链，但这里可能长出一个做原型的小型ASIC市场；更重要的是让新一代学生早点建立直觉，毕竟芯片法案和地缘政治都摆在那里，行业缺人。

Adam自己真打算把TinyGPU提交流片。拿到芯片后，他能玩自己的设计，也能玩同批另外99个人的项目，算是个意外的福利。

## 三个词讲完GPU：架构、并行、内存

回头看，Adam把整个项目的要点归纳成三个词：架构、并行化、内存。前两个在明面上，第三个是他一开始完全低估的。

先说一个前置决定。GPU这个词如今边界模糊，图形处理器、张量处理器、各种加速器都被往里装。Adam把目标定为剥离图形硬件这些具体分支，只保留所有GPU共有的骨架，让学的人能往上盖楼。至于别人认不认这是GPU，他不在乎，产品目标是教学，怎么教最有效就怎么设计。

再说并行化。GPU软件层的编程模式叫SIMD，单指令多数据。拿矩阵加法举例：两个1x8的矩阵a和b相加，结果放进矩阵c。CPU的写法是个for循环，8次迭代跑8个周期。GPU的写法是写一个kernel，这段代码只负责一对元素：读a的第i个元素，读b的第i个元素，相加，写进c的第i个位置。然后告诉硬件，这段代码执行8遍，i从0到7。每一遍就是一个线程。硬件层的对应物叫SIMT，单指令多线程。

问题来了：8个线程跑同一份代码，怎么让它们处理不同的数据？答案是硬件在运行时给每个线程塞上下文。TinyGPU里，每个线程有16个寄存器，最后3个是只读的，GPU自己往里写：你在哪个block、每个block多少线程、你是block里的第几个线程。代码拿这些值算内存偏移，就知道该读哪个元素。写过CUDA的人会眼熟，这就是blockIdx、blockDim、threadIdx那一套。线程按4个一组上core，这一组叫一个block。换算也简单：block编号乘以每block线程数，加上block内的线程编号，就是全局线程号。第3个block里的线程，对应全局的第12到15号线程。

指令集也顺带讲了。16位定长指令，4位操作码，所以最多16条指令；寄存器地址4位，所以最多16个寄存器；分支指令的立即数8位，所以程序内存最多256行。真实GPU的指令通常是32位，约束松得多。指令本身很朴素：加减乘除、load、store、常量装载，再加一对关键的组合，比较指令CMP和分支指令BR_NZP。CMP算两个寄存器的差，把正、零、负的结果存进NZP寄存器；BR_NZP按NZP的状态决定跳不跳转。矩阵乘法里一个线程要算点积、要循环累加，靠的就是这对指令。

然后是内存，Adam称这是他最大的认知修正。直觉上，并行的瓶颈是算力：想同时做100次加法，就得有100个能做加法的核。实际卡住的是内存。100个计算单元要同时从全局内存读100个位置，全局内存的带宽有限，请求开始排队，延迟一下子放大。他给了一个更极端的数字：1000个核同时要数据，带宽只够100个，剩下的全在等。他随机碰到了George Hotz，comma.ai的创始人，请对方看自己的设计，得到的反馈很直接：这个设计没解决内存层级，而那才是最重要的部分。

> GPU很大程度上就是在想办法绕开内存延迟，在不同的层级把它藏起来。

所以真实GPU有内存控制器、多层缓存、共享内存、线程同步屏障，全是为这件事服务的。TinyGPU为了保持简单，只做了寄存器和全局内存两层，屏障这类机制也砍掉了。这个结论放到今天的AI上同样成立：大模型的训练和推理都压在GPU上，访存长期是性能天花板，各家芯片堆缓存、堆带宽，思路一脉相承。

## 硬件里到底发生了什么

软件层讲完，硬件层反而好懂了。整个流程从主机开始：CPU把编译好的kernel装进程序内存，把矩阵数据装进数据内存，往设备控制寄存器里写线程数，然后拉高start信号。GPU开始跑，跑完拉高done信号，主机回来读结果。GPU从来不单独干活，它旁边永远有个主机管编译、装载和收结果。

GPU内部的第一层是dispatcher，派发器。它盯着4个core，用最朴素的轮询：谁空出来了，就把下一个block发过去，每个core一次4个线程，像食堂打饭，哪个窗口空了就往哪派活。core对外暴露三个信号：done、reset、start，派发器看到done就复位再发新活。代码层面它维护两个计数器，已派发的block数和已完成的block数，两者相等就向GPU输出done信号。Nathan问这个是不是有现成组件可以拖，Adam说没有，整个项目几乎没有现成组件，全是自己设计再用Claude验证。

每个core内部有共享的三件套：调度器、fetcher、decoder。fetcher去程序内存取指令，这里有个顺手的优化：所有线程执行同一份代码，指令取一次缓存住，大家共用。decoder把16位的0和1翻译成控制信号，分发给core里每个线程的执行单元。

每个线程独享一套资源：寄存器堆、程序计数器、ALU、LSU（访存单元）。到这一层，它基本就是个迷你CPU。真实GPU里各线程可能跳到不同的代码行，这叫分支分歧，实现起来很麻烦。TinyGPU里每个线程有自己的程序计数器，但Adam写的程序刻意让所有线程保持同行，绕开了这个坑。

有个细节很妙：ALU里的加法器、乘法器这些电路其实每个周期都在算，导线永远连着，多路选择器决定这一次取哪个结果输出。所谓执行指令，就是译码器把该开的开关打开。

内存控制器负责节流。4个core乘每core 4个LSU，全芯片16个访存单元可能同时发请求，内存带宽就那么多，控制器把请求排队，按带宽放行，再把结果送回去。

Nathan问了个好问题：4个线程一起发出去，为什么不会同时结束？答案还是内存。假如没有访存，一切都是确定的，每条指令固定周期，大家步调一致。DRAM有延迟，而且是异步的，带宽排队让有的线程先拿到数据，先拿到的只能等没拿到的。一个core可能因为数据回来得早就提前干完。绕来绕去，又绕回内存。

时钟也值得记一笔。芯片里寄存器（触发器）在时钟沿统一写入新值，时钟周期通常几纳秒。电信号跨芯片传播需要时间，时钟周期必须长于芯片里最长的那条传播路径，静态时序分析就是干这个检查的。

## 从Verilog到芯片：一台笔记本上的流水线

Adam用SystemVerilog写完功能逻辑，剩下的全交给开源EDA流程：先把代码综合成逻辑，化简到等价的最简形式；再把逻辑映射成具体工艺的标准单元；然后布局布线，把几万个门摆到芯片上、连上导线；中间穿插多轮优化，检查时序是否违规、处理寄生参数（导线挨得近会有电容，各种电气效应都能毁掉芯片）；最后输出GDS2文件送代工厂，再做一次版图与原理图的一致性核对。

硬件和软件在这里分道扬镳：**软件可以上线了再改，芯片错了就是错了，流片一次几万美元起步**。所以验证在芯片设计里的分量远超软件。

这套流程跑一遍要20到25分钟、50个步骤，Adam的M2笔记本扛得住。他本地存着30到35次运行记录，才等到第一次不报错跑通。报错信息文档少、内容随机，调试透明度很低，基本靠硬啃。跑通之后打开版图可视化，他说那一刻「很魔法」。

验证环节他写了个Python脚本模拟外部内存（内存本来就在GPU设计之外），测试用的机器码是他手动编译的。脚本装载程序和数据，设好线程数，逐周期推进。日志里能看到每个线程每个周期的寄存器值、ALU输出、当前状态，矩阵加法大概500个周期跑完，最后打印数据内存，结果正确。他鼓励好奇的人直接去仓库跑一遍，看那份日志。

Nathan在开场时点过一个题：Adam能做成这件事，脚下是几代工程师几十年攒出来的芯片设计和设计自动化软件。TinyGPU更像一座纪念碑，纪念那条多代人接力的技术栈。

## AI陪练，改变的是学习的循环

这个项目里最值得普通人抄的，其实是Adam的学习方法。GPU的核心设计全是专有的，没有教材教你怎么写dispatcher。他参考了两个开源GPU仓库（Miaow GPU和一个叫Verilog GPU的项目），但那两个文档稀少、面向生产、体量大到读不懂。他的办法是：看到仓库里一个模块的名字，先跟Claude从第一性原理聊，猜它该放在架构的哪个位置、内部怎么工作，提出自己的假设，让AI纠偏，然后回头对照仓库验证。先自己想一遍，再看别人的实现，看得懂了。

> 如果外星人来到地球发现一台计算机，它们靠拆开看晶体管和连线搞不懂这东西。它们得自己形成一套理解，再拿手头的计算机去验证。

Adam拿这个类比形容自己读GitHub仓库的过程。他还提到一个观察：Claude和ChatGPT有一种超越网上现成资料的工程直觉。有些实现细节从未公开，比如softmax在专有GPU里怎么做的，模型靠推理也能给出靠谱的方向。Nathan补了自己的体感：他最近用AI快速补AI与生物交叉领域的知识、规划一个macOS应用，同一种体验。**静态资料给你答案，AI陪你做假设检验，后者的理解深度完全不同。**

聊到行业，Nathan问：你两周都能走这么远，是不是意味着价值过度流向了设计端，制造端被低估了？Adam先声明自己资历不够，只给了一个建议：去读Hamilton Helmer的《7 Powers》，护城河为什么合理、为什么两周速成撼动不了在位者，书里讲得清楚。他还引了一条刚刷屏的推文，一位刚离职的英伟达员工说，离开之后可以确认，未来10年内没人追得上英伟达。在他看来，这个行业的激励密度让在位者很难变得无能，NVIDIA和TSMC都极其能干。他自己点名最有趣的挑战者是Atomic Semi，Jim Keller参与创办，试图把芯片迭代做得又快又便宜。

至于学到什么程度算够，Adam的标准很清楚：他追求的是全景加关键直觉，能跟一线工程师过招、听懂对方说的每个词，但不追求在单一方向钻到最深处，除非哪天业务真需要。

## 明天就能用上的四件事

- 列你的99/1清单。进任何新领域，先逼自己写出支撑它的最小概念集。GPU就是三件事：SIMD、内存层级、调度。写不出来，说明还没入门；写得出来，剩下的都是细节。
- 先假设，后验证。遇到不懂的机制，别直接搜答案，先猜一个版本，再拿AI或源码对照。Adam能两周走完别人两三年的路，这个循环是核心引擎。
- 让学习产出可运行的东西。两周冲刺的终点是一个别人能复现、能提问、能贡献的仓库，TinyGPU上线后收到的社区贡献已经超出Adam预期。输出物会替你筛选理解漏洞。
- 程序慢，先查内存。这是从GPU设计师那里直接搬来的结论：多数性能瓶颈卡在访存，不在计算。下次优化代码，先看数据怎么流动，再看算法。
