你有没想过,为什么电脑里会同时装着一颗 CPU 和一颗 GPU?翻开规格表,两者都标着“核心数”和频率,看起来差不多,但它们要解决的是完全不同的并行难题。这个差异,恰好是理解 CUDA 一切秘密的钥匙。

CPU 的设计哲学,是死磕单任务的完成速度。为了把一件事情尽快做完,它牺牲了大量晶体管来换取“智能调度”。比如分支预测器,能在你的 if 语句还没真正执行时就猜出它会走哪条岔路;乱序执行引擎,会把没有依赖关系的指令插队执行,避免流水线空转;还有 L1、L2 甚至 L3 这种巨型缓存,像贴身助手一样把常用数据直接塞到核心手边。一言以蔽之,CPU 天生就是为不可预测、分支繁多、先后顺序十分苛刻的逻辑任务打造的。

打开网易新闻 查看精彩图片

GPU 的思路恰好完全相反。它默认任务高度规则、可预测且数学密集——同一条指令,要同时应用到海量数据上,比如屏幕上的每一个像素,又如超大规模矩阵里的每一个元素。正因为这个前提,GPU 大刀阔斧地砍掉了大部分分支预测和乱序执行的电路,把省下来的晶体管全部换成最朴素、最直接的算术单元。最终呈现出来的结构,是数千个轻量小核心,而不是寥寥几个高大全能的大核心。CPU 的座右铭是“一件快”,GPU 的座右铭是“百万件一起快”。

这两种分裂的设计,本来各走各的路。但机器学习偏偏是个异数。无论是矩阵乘法、卷积还是注意力机制,拆到最底层,都是同一批运算在超大规模张量上不断重复。这种“齐刷刷”的并行负载,简直是为 GPU 的量身定做,所以 GPU 顺理成章地成了训练和运行神经网络的默认硬件。

很多人已经忘了,GPU 最早根本不是用来跑任何通用程序的。2007 年以前,它的全部使命就只是图形管线:把一个由三角形构成的场景送进去,给每个顶点跑一遍顶点着色器,确定它最终会落在屏幕什么位置;接着再给每个像素跑一遍片段着色器,决定它该涂上什么颜色,最后写进帧缓冲,变成你看到的一帧画面。

然而研究人员发现了一件极有意思的事。片段着色器本质上就是一段在无数像素上并行执行的小程序。如果能把你的数据伪装成一幅“图片”,把数学运算伪装成“像素颜色计算”,就能让 GPU 用同样的海量并行为普通数值计算服务。这个取巧的办法被称为 GPGPU(通用图形处理器计算),核心就是要把正经的算术问题扭曲成图形管线能接受的形状。

一个夸张简化版的 GLSL 片段着色器,就用来“计算” a[i] + b[i],它会把矩阵 A、B 编码成纹理,