简介:本文从协处理器视角系统对比 CPU 与 GPU 的架构定位差异,拆解 GPU 内部 GPC、TPC、SM、SP 的层级控制链路与内存层次,并横向对比 GPU、NPU、TPU 类加速器与 DSP 的适用边界。读完本文,你将理解并行计算框架如何经驱动控制 GPU,掌握数据并行场景下的选型依据、占用率优化要点与迁移注意事项。
学习 GPU 并行计算编程模型的最终目的,是控制 GPU 上的大量处理器进行并行计算。从这个角度看,GPU 本质是一块硬件,而业界主流的 GPU 通用计算框架(下文统称“GPU 计算框架”)只是控制这块硬件的手段。与 CPU 体系结构资料大量公开不同,GPU 内部实现的公开资料非常有限,因此从驱动与体系结构的视角反推 GPU 内部到底做了哪些工作,是理解其原理的有效路径。
与此同时,在实际工程中,团队经常面临“这个任务该跑在 CPU 上还是 GPU 上”“要不要引入 NPU、TPU 类加速器”的选型问题。这些问题的答案,都建立在对 CPU 与 GPU 架构差异、GPU 内部工作链路的清晰理解之上。本文以 CPU 与 GPU 这对经典组合为核心对比对象,并延伸到协处理器家族的横向对比,帮助读者建立完整的理解与选型框架。
CPU(中央处理器)是通用计算的主处理器,通常由少量(几个到几十个)功能强大的核心构成。每个核心配备复杂的控制逻辑,包括乱序执行、分支预测、大容量多级缓存等机制,其设计目标是让单个线程尽可能快地完成,即优先优化延迟。CPU 直接运行操作系统和各类通用程序,是整个系统的“大脑”。
GPU(图形处理单元)最初为图形渲染而生,如今已发展为通用并行加速器。要理解 GPU,先要理解“协处理器”这个概念:协处理器是一种与 CPU 并行工作、主要用于执行特定计算任务、以减轻 CPU 负担的处理器。它可以附属于 CPU,通过扩展指令集或提供配置寄存器来扩展内核处理功能,与 CPU 紧密连接、快速传递数据,并拥有专门的指令集来执行特殊任务。
协处理器家族成员众多:数学协处理器负责浮点、三角函数等复杂数学运算;GPU 负责图形渲染和大规模并行计算;DSP 负责音视频等信号处理;还有面向加解密的加密协处理器,以及面向神经网络计算的 NPU、面向大规模矩阵运算的 TPU 类加速器。GPU 是其中最典型、可编程性最强的一员。
在现代计算系统中,CPU 与 GPU 是“主机—设备”关系:CPU 负责整体控制流、业务逻辑与任务派发,GPU 接受 CPU 通过驱动下达的命令,执行数据并行部分。GPU 计算框架最终也是通过 GPU 驱动来控制 GPU 的,这决定了理解 GPU 必须理解“驱动—硬件”这条控制链路。
尽管定位差异巨大,CPU 与 GPU 在底层逻辑上仍有大量共同点:
CPU 走“少而强”的路线:少量复杂核心,每个核心都有完善的前端取指、分支预测与乱序执行部件,以及大容量缓存。GPU 则走“多而简”的路线:芯片上集成成百上千个相对简单的执行核心,并按层级组织。以业界常见的 GPU 架构为例(不同厂商命名可能不同,但层级思路相似):
理解“GPC → TPC → SM → SP”这条层级链路,就理解了 GPU 如何把一个大规模并行任务层层拆分到每个执行核心上。
应用程序不会直接操作硬件,其调用链大致为:应用调用 GPU 计算框架的接口 → 框架运行时 → 用户态驱动 → 内核态驱动 → 命令队列 → GPU 前端命令处理器 → 调度到 GPC/TPC → 分配给 SM → SP 执行。基于这条链路,可以反推几个常见机制的大致实现:
GPU 的寄存器堆总量远大于 CPU,但会被海量线程分摊,单个线程可用的寄存器非常有限。如果寄存器存储不下需要处理的数据,这些数据就会被放到 local memory,而 local memory 的访问非常慢,会显著拖累性能。因此,GPU 编程的一个重要目标是:让受内存瓶颈约束的数据量,都能在 GPU 的 block(线程块)内被合理承载和执行,让 SM 上保持足够多的活跃线程,即提高“占用率”。这与 CPU 形成鲜明对比:CPU 的大缓存对程序员透明,而 GPU 的性能高度依赖程序员对数据分布和访问模式的显式设计。
CPU 通过复杂控制把单线程延迟做到很低,适合分支密集、依赖复杂的任务;GPU 则通过海量线程之间的快速切换来“隐藏延迟”——某个线程等待内存时,硬件立刻切换到其他线程,保持计算单元持续满载。因此 GPU 在规则、密集、可并行的负载上吞吐远超 CPU,而在串行依赖强的负载上,大量核心会处于闲置状态。
CPU 编程使用通用语言与线程库即可,心智负担低;GPU 编程则需要理解 kernel(内核函数)、grid(网格)、block(线程块)、thread(线程)的层次结构,并掌握传输、同步、调优等额外技能。示意流程如下(伪代码,非特定厂商接口):
# 通用 GPU 并行计算流程(伪代码)1. dev_ptr = device_alloc(bytes) # 在设备侧分配显存2. copy_host_to_device(dev_ptr, host_ptr) # 将输入数据拷贝到设备3. launch_kernel(grid, block, kernel) # 以网格-块-线程组织并行任务4. event_synchronize(done_event) # 通过事件等待计算完成5. copy_device_to_host(host_ptr, dev_ptr) # 将结果拷回主机
利用多流可以进一步重叠传输与计算:
# 多流重叠(伪代码)stream1: copy(A) → kernel(A) → event(e1)stream2: copy(B) → kernel(B) → event(e2)host: 等待 e1、e2 后汇总结果
CPU 服务器生态成熟,运维体系完善;GPU 引入了额外的驱动版本管理、利用率监控、故障恢复、散热与功耗规划等运维事项,单卡成本与功耗也显著更高。这也是为什么很多团队会直接使用云上 GPU 算力产品,而非全部自建。
CPU 侧的进程隔离、权限控制体系成熟;GPU 侧则需要额外关注设备内存的隔离与清理、多租户共享或虚拟化场景下的数据隔离,以及算力任务的审计与计量。在云上使用 GPU 时,这些通常由平台层统一提供,但自建环境需要自行设计。
| 对比维度 | CPU | GPU |
|---|---|---|
| 系统定位 | 通用主处理器 | 并行协处理器/加速器 |
| 核心组织 | 少量复杂核心 | 海量简单核心,按 GPC→TPC→SM→SP 层级组织 |
| 优化目标 | 低延迟 | 高吞吐 |
| 控制逻辑 | 乱序执行、分支预测等复杂控制 | 控制简单,靠海量线程切换隐藏延迟 |
| 缓存与内存 | 大容量多级缓存,对程序员透明 | 寄存器堆大但按线程划分,溢出到 local memory 代价高 |
| 线程调度 | 操作系统调度,切换开销较大 | 硬件调度,切换开销极小 |
| 擅长任务 | 串行逻辑、复杂分支、事务处理 | 图形渲染、矩阵运算、AI 训练与推理 |
| 编程模型 | 通用语言 + 线程/进程 | kernel + grid/block/thread 层次 |
| 接入难度 | 低 | 需学习并行编程与性能调优 |
| 运维成本 | 生态成熟 | 需管理驱动、利用率、功耗等 |
| 单位算力成本 | 通用任务下更划算 | 并行任务下单位算力成本更低 |
既然 GPU、NPU、TPU、DSP 都属于协处理器,它们之间的差异也值得横向对比:
| 类型 | 定位 | 擅长任务 | 可编程灵活性 | 典型场景 |
|---|---|---|---|---|
| GPU | 通用并行加速器 | 图形渲染、通用并行计算、AI 训练/推理 | 高,通用可编程 | 图形、科学计算、深度学习 |
| NPU | 神经网络专用加速器 | 神经网络前向推理 | 中低,围绕典型算子优化 | 端侧与边缘推理 |
| TPU 类矩阵加速器 | 大规模矩阵运算加速 | 大矩阵乘法为主的训练与推理 | 中 | 数据中心 AI 负载 |
| DSP | 数字信号处理器 | 音视频等流式信号处理 | 中 | 通信、音频、图像信号处理 |
| 加密协处理器 | 加解密专用 | 对称/非对称加解密运算 | 低 | 安全通信、存储加密 |
可以看出:灵活性越高的协处理器,适用面越广,但针对特定负载的能效往往不如专用设计。GPU 以牺牲部分专用能效换取了几乎覆盖所有数据并行负载的通用性;NPU、TPU 类加速器则针对规则、固定的计算结构换取更高能效;DSP 与加密协处理器则更加专精。
CPU 与 GPU 并非替代关系,而是分工明确的互补关系:CPU 是优化延迟的通用主处理器,GPU 是优化吞吐的并行协处理器,两者通过“主机—设备”模型协作。理解 GPU 的关键,在于抓住“GPC → TPC → SM → SP”这条层级控制链路,以及“寄存器—local memory”这一内存层次矛盾——前者解释了海量核心如何被组织与调度,后者解释了占用率为何是 GPU 编程的核心指标。进一步地,GPU、NPU、TPU 类加速器、DSP 同属协处理器家族,差异本质上是“通用性与专用能效”之间的取舍。选型时,应基于负载的并行度、规则性、延迟要求与团队能力做条件化判断:数据并行密集的负载交给 GPU,串行逻辑留给 CPU,结构固定的 AI 负载可评估专用加速器,而运维能力有限的团队则可借助云上通用算力产品降低门槛。理解了这些原理与差异,才能在算力选型与性能优化中做出有依据的决策。