【深入 NVIDIA GPU 架构 01】GPU 是如何诞生的?

> 本文是《深入 NVIDIA GPU:从图形流水线、SM 微架构到 AI 超级芯片》专栏的第 1 章。

> 本章从计算机图形系统的实际需求出发,解释 GPU 为什么出现,以及它为什么从一开始就选择了不同于 CPU 的硬件设计路线。

摘要

今天提到 GPU,人们往往首先想到 CUDA、深度学习、Tensor Core 或大模型训练。但 GPU 最初并不是为通用计算设计的,它的直接目标是解决一个非常具体的问题:**如何持续、快速地生成屏幕上的像素。**

早期计算机主要依靠 CPU 完成图形计算。随着分辨率、色彩深度、三维场景复杂度和实时帧率不断提高,CPU 很难同时承担操作系统、应用逻辑和大量重复的图形运算。于是,一部分显示工作被逐步转移到专用硬件:显示控制器、二维加速器、三维光栅化芯片,最终发展成集几何处理、光栅化、纹理映射和像素输出于一体的图形处理器。

GPU 的核心价值并不是"单个运算单元比 CPU 更强",而是用大量相对简单的运算资源,同时处理海量结构相似的数据,以获得极高的总体吞吐率。


一、本章要解决的问题

读完本章,应当能够回答以下问题:

  1. 在 GPU 出现之前,计算机如何生成画面?

  2. 为什么图形任务会逐渐成为 CPU 的负担?

  3. 显示控制器、图形加速器和 GPU 有什么区别?

  4. 为什么图形处理天然适合并行硬件?

  5. GPU 与 CPU 的设计目标为什么不同?

  6. NVIDIA GeForce 256 在 GPU 发展史上有什么意义?


二、从一块屏幕说起

屏幕可以抽象为一个二维像素阵列。假设分辨率为 1920×1080,每个像素使用 32 bit 表示颜色,那么保存一帧画面大约需要:

```text

1920 × 1080 × 4 Byte ≈ 7.91 MiB

```

如果屏幕每秒刷新 60 次,仅仅把完整帧缓冲区读取并送往显示设备,理论数据量就约为:

```text

7.91 MiB × 60 ≈ 474.6 MiB/s

```

这里还没有计算:

  • 三角形的坐标变换;

  • 光照计算;

  • 纹理读取和过滤;

  • 深度测试;

  • 透明度混合;

  • 抗锯齿;

  • 后处理;

  • 多次中间渲染。

真正的三维渲染需要先经过大量计算,才能得到最终的一帧像素。

因此,图形系统面对的并不只是"把一张图片显示出来",而是要在很短的时间内完成大量几何计算、采样、比较、插值和像素写入。


三、GPU 出现之前:CPU 加帧缓冲

早期图形系统可以简化为以下结构:

```mermaid

flowchart LR

A"应用程序" --> B"CPU"

B --> C"系统内存中的图像数据"

C --> D"帧缓冲区"

D --> E"显示控制器"

E --> F"显示器"

```

其中各部分的工作如下:

  • CPU 计算要显示的内容;

  • 帧缓冲区保存每个像素的颜色;

  • 显示控制器按照固定时序读取帧缓冲;

  • 数字或模拟显示接口把图像信号送到显示器。

此时的显示控制器主要负责"扫描输出",并不负责复杂的图形生成。画线、填充矩形、复制图像,甚至字体绘制,都可能需要 CPU 逐像素完成。

这种方式在低分辨率、低刷新率和简单界面下可以工作,但存在明显问题:

  1. CPU 需要执行大量重复操作;

  2. 图像数据占用系统内存带宽;

  3. CPU 在处理图形时无法及时处理其他任务;

  4. 分辨率和色彩深度提高后,数据量迅速增长。

这推动了第一类图形专用硬件的出现。


四、从显示控制器到二维图形加速器

二维图形界面中经常出现一些高度重复的操作:

  • 绘制直线;

  • 填充矩形;

  • 位块传输,即 BitBLT;

  • 图像复制;

  • 颜色填充;

  • 光标叠加;

  • 字体和窗口绘制。

这些操作规则明确,而且会反复执行,非常适合固化为专用硬件。

例如,CPU 不再逐像素执行矩形填充,而是向图形加速器写入:

```text

起点坐标 = (x, y)

宽度 = width

高度 = height

颜色 = color

操作 = FILL_RECT

```

图形加速器收到命令后,自行生成目标地址并完成批量写入。

```mermaid

flowchart LR

A"CPU 提交绘图命令" --> B"2D 图形加速器"

B --> C"地址生成"

B --> D"颜色填充 / BitBLT"

C --> E"显存"

D --> E

E --> F"显示控制器"

```

这样做有三个直接收益:

  • CPU 只提交命令,不再处理每个像素;

  • 专用电路可以用更少的周期完成固定操作;

  • 图形数据可以放在独立显存中,减轻系统内存压力。

不过,二维加速器仍然无法解决日益增长的三维图形计算问题。


五、三维图形流水线为什么更加复杂

三维场景通常由大量顶点和三角形组成。要把三维场景显示在二维屏幕上,大致需要以下步骤:

```mermaid

flowchart LR

A"模型顶点" --> B"模型 / 视图 / 投影变换"

B --> C"光照与裁剪"

C --> D"透视除法与视口变换"

D --> E"三角形建立"

E --> F"光栅化"

F --> G"纹理采样与片元处理"

G --> H"深度 / 模板测试"

H --> I"颜色混合"

I --> J"帧缓冲区"

```

不同阶段处理的数据类型不同:

| 阶段 | 主要输入 | 典型计算 |

|---|---|---|

| 几何处理 | 顶点 | 矩阵乘法、向量运算 |

| 三角形建立 | 顶点属性 | 边界计算、裁剪 |

| 光栅化 | 三角形 | 覆盖测试、属性插值 |

| 纹理处理 | 坐标和纹理 | 寻址、采样、过滤 |

| 像素处理 | 片元 | 颜色计算、深度比较 |

| 输出合并 | 像素 | 混合、写回 |

这些计算有一个共同特征:**同一种运算会作用于大量顶点、片元或像素。**

例如,模型中的每个顶点都要乘以变换矩阵;一个三角形覆盖的许多像素都要进行纹理采样;屏幕上大量片元都要执行深度测试。不同数据之间往往具有较高的独立性,因此可以并行处理。


六、为什么图形处理天然适合并行

假设需要把同一个亮度调整公式应用到一百万个像素:

```text

outputi = clamp(inputi × scale + bias)

```

传统串行思路是一个接一个地处理:

```text

像素0 → 像素1 → 像素2 → ...... → 像素999999

```

并行思路则是让多个运算单元同时处理不同像素:

```text

运算单元0 → 像素0

运算单元1 → 像素1

运算单元2 → 像素2

......

```

只要像素之间没有强依赖,就不必等待前一个像素完成。

三维图形拥有大量这种数据级并行:

  • 不同顶点可并行变换;

  • 不同三角形可并行建立;

  • 不同片元可并行着色;

  • 不同像素可并行测试和写回。

图形工作负载还具有较好的规律性。许多数据执行相同或相近的操作,硬件可以让多个执行通道共享控制逻辑,从而把更多晶体管用于计算,而不是复杂的指令调度和分支预测。

这正是 GPU 选择高吞吐架构的重要原因。


七、CPU 与 GPU 的目标并不相同

CPU 和 GPU 都能执行计算,但二者优化的目标不同。

| 对比项目 | CPU | GPU |

|---|---|---|

| 主要目标 | 降低单线程延迟 | 提高总体吞吐率 |

| 任务特征 | 复杂控制、串行逻辑 | 大规模相似计算 |

| 核心数量 | 较少、单核复杂 | 大量、单元相对简单 |

| 缓存 | 大容量、多级低延迟缓存 | 用缓存与大量线程共同隐藏延迟 |

| 控制逻辑 | 分支预测、乱序执行、推测执行 | 更强调批量调度和规则执行 |

| 并行方式 | 线程级并行、SIMD | 大规模线程与 SIMT |

| 延迟处理 | 尽量缩短一次操作的等待 | 某批线程等待时执行其他线程 |

可以用两种交通工具来类比:

  • CPU 像少量高性能轿车,擅长尽快把少数乘客送到目的地;

  • GPU 像拥有大量座位的列车系统,追求单位时间运输更多乘客。

这个类比并不完全精确,但能说明"延迟"和"吞吐率"的区别。

NVIDIA 的 CUDA 最佳实践文档也将二者概括为:CPU Core 主要面向少量线程的低延迟执行,GPU 则面向大量轻量线程以最大化吞吐率。

需要注意,GPU 不是在所有任务上都比 CPU 快。当任务存在以下特征时,GPU 的优势可能很小:

  • 串行依赖很强;

  • 分支路径高度不规则;

  • 数据规模很小;

  • CPU 与 GPU 之间的数据传输成本过高;

  • 并行计算量不足以覆盖调度和启动开销。


八、固定功能三维加速器

在早期三维图形硬件中,许多阶段被直接实现为固定功能电路:

```mermaid

flowchart LR

A"CPU 处理顶点或提交命令" --> B"固定功能几何阶段"

B --> C"固定功能光栅化"

C --> D"固定功能纹理映射"

D --> E"固定功能颜色混合"

E --> F"显存"

```

所谓固定功能,是指硬件支持预先规定好的算法和状态组合。开发者可以设置参数,却不能任意改写处理逻辑。

其优点包括:

  • 电路针对特定操作优化;

  • 性能高;

  • 功耗和面积效率好;

  • 行为相对确定。

缺点则是:

  • 难以实现新的光照和材质算法;

  • 硬件功能升级依赖新芯片;

  • 不同效果常常需要多遍渲染;

  • 灵活性越来越无法满足游戏和专业图形需求。

因此,固定功能流水线只是 GPU 发展的一个阶段。后来出现的可编程着色器,将逐步改变图形处理器的性质。


九、GeForce 256 与"GPU"概念

1999 年,NVIDIA 发布 GeForce 256,并将其称为 GPU。NVIDIA 当时强调,它在单芯片中集成了变换、光照、三角形建立/裁剪和渲染等功能。NVIDIA 的公司时间线将 GeForce 256 称为其首款 GPU。

GeForce 256 的重要性不只是产品名称,而是它体现了一次明确的职责转移:

```text

早期:

CPU 完成大量几何计算

图形芯片主要负责光栅化和输出

GeForce 256 所代表的方向:

更多几何处理进入图形芯片

图形流水线在专用处理器内部变得更加完整

CPU 更专注于应用逻辑和命令提交

```

需要保持一个严谨认识:

> 图形加速硬件在 GeForce 256 之前已经存在多年,"GPU"也不是某一天凭空出现的全新物种。

GeForce 256 更适合作为一个具有代表性的里程碑:NVIDIA 将 GPU 一词系统地用于产品定位,并把硬件变换与光照等阶段集成到消费级单芯片图形处理器中。

换句话说,GPU 的形成是一个连续演进过程:

```mermaid

flowchart LR

A"显示控制器" --> B"2D 图形加速器"

B --> C"3D 光栅化加速器"

C --> D"集成几何处理的 GPU"

D --> E"可编程 Shader GPU"

E --> F"统一着色器 GPU"

F --> G"通用并行计算 GPU"

G --> H"AI / HPC 加速平台"

```


十、GPU 硬件设计的基本思想

回顾 GPU 的形成过程,可以提炼出几条贯穿后续架构演进的设计思想。

1. 把重复工作从 CPU 卸载到专用硬件

最早是扫描输出,随后是二维绘图、光栅化、纹理处理、几何变换,后来又扩展到光线追踪和矩阵运算。

2. 用并行资源换取吞吐率

当大量数据能够执行相似操作时,复制运算通道比增强单个复杂核心更有效。

3. 让控制成本由一组数据共同分担

多个数据元素执行相同指令时,可以共享部分取指、译码和调度逻辑。这一思想后来发展为 NVIDIA 的 SIMT 执行模型。

4. 通过流水线让不同任务重叠执行

当一个三角形进行光栅化时,后续顶点可以进行变换,之前生成的片元也可以进入深度测试。多个阶段同时工作,提高了硬件利用率。

5. 专用化与可编程性不断摆动

完全固定功能的硬件效率高但不灵活;完全通用的硬件灵活但成本较高。GPU 的发展并不是简单地取消专用单元,而是在可编程核心与纹理、光栅、视频、光追、矩阵等专用单元之间寻找平衡。


十一、一个完整的早期三维渲染流程

以显示一个旋转的三角形为例:

  1. 应用程序在 CPU 上更新三角形的旋转角度;

  2. CPU 准备顶点、颜色和纹理等数据;

  3. CPU 向图形处理器提交绘制命令;

  4. 几何阶段把三维顶点变换到屏幕坐标;

  5. 三角形建立单元确定三条边和覆盖范围;

  6. 光栅化器生成三角形覆盖的片元;

  7. 纹理单元根据插值后的坐标读取纹理;

  8. 深度测试判断片元是否被其他物体遮挡;

  9. 通过测试的颜色被写入帧缓冲;

  10. 显示控制器扫描帧缓冲并输出到显示器。

从这个流程可以看到,CPU 负责"决定画什么",GPU 负责"把它高效地画出来"。

现代 GPU 的执行过程已经复杂得多,但这一异构分工至今仍然存在:CPU 处理复杂控制和系统任务,GPU 处理适合大规模并行的工作。


十二、常见误区

误区一:GPU 就是显卡

GPU 是处理器芯片或其中的图形/计算核心;显卡则是一套完整板级产品,通常包含 GPU、显存、供电、PCB、散热器和外部接口。

误区二:GPU 从诞生之初就是通用处理器

早期 GPU 主要围绕图形流水线设计,通用可编程能力是逐步发展出来的。

误区三:GPU 的每个核心相当于一个 CPU Core

"CUDA Core"通常指 SM 中的算术执行通道,与具有复杂控制、缓存和乱序执行能力的 CPU Core 不是同一层级的概念。

误区四:GPU 比 CPU 快,所以可以取代 CPU

GPU 擅长高并行、高吞吐任务;CPU 擅长复杂控制、低延迟响应和串行任务。现代系统通常让二者协同工作。

误区五:并行单元越多,程序就一定越快

实际性能还受并行度、内存带宽、数据依赖、分支、调度、数据传输和软件实现影响。


十三、本章总结

GPU 并不是从通用计算需求中诞生的,而是图形系统不断发展的结果。

它经历了以下演进:

  1. 显示控制器负责读取帧缓冲和生成显示信号;

  2. 二维加速器接管画线、填充和 BitBLT;

  3. 三维加速器接管光栅化、纹理和像素处理;

  4. 几何变换与光照进入单芯片图形处理器;

  5. GPU 逐渐形成完整的硬件图形流水线。

GPU 之所以采用大规模并行架构,是因为顶点、三角形、片元和像素处理中存在大量结构相似、相对独立的计算。它通过牺牲一部分单线程控制能力,换取更高的整体吞吐率。

但此时仍然存在一个核心问题:固定功能硬件只能执行预先设计好的算法。开发者如果想实现新的材质、光照和视觉效果,就需要更强的可编程能力。

这正是下一章要讨论的内容。


十四、思考题

  1. 为什么提高屏幕分辨率会同时增加计算压力和显存带宽压力?

  2. BitBLT 为什么适合由专用硬件实现?

  3. 为什么三角形比任意复杂多边形更适合作为硬件光栅化的基本图元?

  4. 固定功能电路和可编程处理器分别有什么优势?

  5. GPU 为什么选择提高吞吐率,而不是重点降低单线程延迟?

  6. GPU 是否只适合图像数据?决定一个问题是否适合 GPU 的真正因素是什么?


十五、参考资料

  1. NVIDIA Corporate Timeline:1999 年 GeForce 256(https://www.nvidia.com/content/timeline/time_99.html)

  2. NVIDIA CUDA Programming Guide(https://docs.nvidia.com/cuda/cuda-programming-guide/part1.html)

  3. NVIDIA CUDA C++ Best Practices Guide(https://docs.nvidia.com/cuda/cuda-c-best-practices-guide/index.html)

  4. Khronos OpenGL Wiki:History of Programmability(https://wikis.khronos.org/opengl/History_of_Programmability)

  5. Khronos OpenGL Wiki:History of OpenGL(https://wikis.khronos.org/opengl/History_of_OpenGL)


下一章预告

下一章为:

> **《【深入 NVIDIA GPU 架构 02】从固定功能流水线到可编程着色器》**

下一章将重点讨论:

  • 固定功能图形流水线的限制;

  • Vertex Shader 与 Pixel/Fragment Shader 为什么出现;

  • Shader 指令、寄存器和执行单元;

  • DirectX 与 OpenGL 如何推动 GPU 可编程化;

  • 可编程着色器如何为后来的统一着色器架构铺路。

相关推荐
这个DBA有点耶4 小时前
分布式数据库到底该不该上?从判断标准到架构选型的实战思考
数据库·架构·dba
楚识科技4 小时前
破除通用瓶颈——企业级OCR定制化开发的架构思维与实战范式
架构·ocr
刘立军4 小时前
RESTful 与契约优先:规范接口定义,统一接口设计范式
后端·架构·ai编程
heimeiyingwang5 小时前
【架构实战】分布式事务:从CAP定理到Seata实战,一文讲透跨服务数据一致性
分布式·架构
独孤九剑打醒他5 小时前
RGB‑TOT 全架构系统仿真:红外波长簇光通信完整验证
架构
这个DBA有点耶6 小时前
从库延迟的“二次放大”效应:一次大事务,拖垮整个读写分离
数据库·mysql·架构
张宇Joaquin7 小时前
高性能模板库Eigen架构分析及性能优化实践
性能优化·架构
AI产品测评官8 小时前
AI 招聘系统的三代技术演进:从 DOM 注入到视觉语义读取的架构拆解
人工智能·架构·求职招聘
语核科技9 小时前
知识管理系统的技术选型:传统知识库与AI原生知识库的架构差异
架构·ai-native
梦奇不是胖猫9 小时前
从小餐厅 到 理解 互联网架构
架构