真实面经题目 · 原创解析

为什么 CPU 通常需要多级 Cache,而 GPU 更强调 shared memory、coalescing 和高带宽并行访存?

这题考 CPU/GPU 架构差异和访存优化思路。好答案要说明 CPU 面向低延迟、强控制流、少量复杂线程,依赖多级 Cache、分支预测和乱序执行降低单线程访存延迟;GPU 面向高吞吐、大量线程并行,用 warp 调度隐藏延迟,更强调 coalesced global memory access、shared memory 显式复用、高带宽和 occupancy。不能简单说 GPU 没有 Cache,而要说明 GPU 也有 L1/L2/纹理等缓存,只是优化重点从自动低延迟缓存转向显式数据布局和并行带宽利用。

出现于:阿里巴巴 · C/C++

60 秒回答模板

我会先从设计目标回答:CPU 和 GPU 都有缓存层次,但服务的目标不同。CPU 面向通用控制流和低延迟响应,核心数少但每个核心很强,程序经常有复杂分支、指针追踪和不可预测访存,所以需要 L1/L2/L3 多级 Cache、分支预测、乱序执行和预取,把单线程看到的内存延迟尽量压低。GPU 面向吞吐,核心或执行单元多,单个线程不追求极低延迟,而是用大量 warp/线程在一个 warp 等内存时切换到另一个 warp 执行,靠并行度隐藏延迟。因此 GPU 优化重点不是让每个线程像 CPU 一样享受大而复杂的多级私有缓存,而是让一组线程访问连续地址形成 coalescing,充分利用 HBM/显存带宽,并把会重复使用的数据显式放进 shared memory 或寄存器。shared memory 是程序员可控的片上存储,延迟低、带宽高,适合 tile 复用,例如矩阵乘、卷积、归约;但要注意 bank conflict、同步和容量限制。GPU 也不是只有两层或没有 cache,现代 GPU 通常有 L1、L2、constant/texture 等缓存结构,只是它们的角色和 CPU 不同,更多服务于吞吐、合并访问和缓存全局/只读数据。统一内存寻址也不等于 CPU/GPU 共享同一套 Cache 语义,它解决的是地址空间和迁移/访问便利性,性能上仍要关注数据驻留位置、page migration、PCIe/NVLink 开销和访问模式。

考点 CPU 优先低延迟
难度 真实面经题
回答目标 让候选人能从低延迟 CPU 与高吞吐 GPU 的架构目标出发,解释多级 Cache、shared memory、coalescing、带宽并行和统一内存的本质差异。

深入解析

01

设计目标不同

CPU 优先优化单线程延迟和通用性,适合操作系统、数据库、业务逻辑、分支密集和指针追踪任务。GPU 优先优化吞吐,适合大量数据并行任务。设计目标不同,决定了 CPU 更依赖复杂缓存和控制逻辑,GPU 更依赖海量线程、高带宽和简单高效的数据通路。

02

CPU 多级 Cache 降低延迟

CPU 核心数量相对少,但每个核心有复杂流水线、乱序执行和分支预测。L1 很小很快,L2 容量更大,L3 通常跨核心共享,用多级层次在容量、延迟和共享之间折中。这样即使程序访存不规则,也尽量让单线程少等主内存。

03

GPU 用并行隐藏延迟

GPU 单个线程遇到显存访问可能等待很久,但硬件同时驻留大量 warp。当一个 warp 等内存时,调度器可以切到另一个 ready warp 执行。它不是消除每次访存延迟,而是用足够并行度把延迟藏起来,因此 occupancy、线程数量和访存模式非常关键。

04

Coalescing 决定带宽利用

GPU global memory 带宽很高,但要求同一 warp 的线程尽量访问连续、对齐、规则的地址,这样多个线程的访问可以合并成少量内存事务。如果线程访问离散、跨 stride 或分支发散,带宽会被浪费,实际性能可能远低于理论峰值。

05

Shared memory 是显式复用

shared memory 是一个 block 内线程共享的片上存储,程序员显式加载、同步和复用。矩阵乘会把 A/B tile 放进 shared memory,多个线程多次读取,减少 global memory 访问。它比自动 cache 更可控,但容量有限,要处理 bank conflict、同步开销和占用率之间的平衡。

06

GPU 也有缓存但角色不同

不能说 GPU 不需要 cache 或只有简单两层。现代 GPU 通常有 L1、L2、只读/常量/纹理路径等缓存结构。差别在于 GPU 的性能关键往往不是靠复杂多级 cache 挽救任意访问,而是让访问模式规则化、合并化,并用 shared memory 和寄存器主动提高数据复用。

07

统一内存不等于同速访问

统一虚拟地址或统一内存让 CPU 和 GPU 可以更方便地引用同一数据,但性能仍取决于数据当前驻留在哪、是否发生 page migration、是否经过 PCIe/NVLink、访问粒度是否规则。工程上不能因为地址统一就忽略拷贝、prefetch、pin memory 和数据布局。

易错点

  • 简单说 CPU 有三层 Cache、GPU 只有两层,没有解释低延迟和高吞吐的设计目标差异。
  • 说 GPU 不需要 Cache 或没有 Cache,忽略 L1、L2、只读/常量/纹理缓存等实际结构。
  • 只讲 shared memory 快,不讲它需要显式管理、同步、容量限制和 bank conflict。
  • 把 coalescing 理解成普通缓存命中,没有说明 warp 内连续对齐访问和内存事务合并。
  • 认为 GPU 访存延迟低,所以快;实际上 GPU 常靠大量线程隐藏高延迟。
  • 忽略 occupancy、寄存器压力、shared memory 占用和访存模式之间的平衡。
  • 把统一内存寻址说成 CPU/GPU 访问完全同速,漏掉数据迁移、互连带宽和驻留位置。

面试官追问

为什么 CPU 通常有 L1、L2、L3,而 GPU 不强调同样的多级私有 Cache?

CPU 要服务不可预测的通用程序,单线程卡住就会直接影响延迟,所以用多级 Cache 在速度、容量和共享之间折中。GPU 有海量线程,可以通过 warp 切换隐藏单次访存延迟,并且 workload 更常见规则数据并行,因此更强调合并访问、shared memory 复用和高带宽。

Shared memory 和 L1 Cache 的区别是什么?

L1 Cache 通常是硬件自动管理,程序员主要通过访问模式间接影响命中率。shared memory 是 CUDA block 内显式管理的片上存储,程序员决定何时加载、如何布局、何时同步和如何复用。它可控性强,适合 tile 算法,但也带来 bank conflict 和同步复杂度。

什么是 memory coalescing?

在 GPU 中,同一 warp 的多个线程如果访问连续、对齐、规则的 global memory 地址,硬件可以把这些访问合并成更少的内存事务,提高带宽利用率。如果每个线程访问分散地址,就会产生更多事务,实际带宽和性能下降。

GPU 访存慢为什么还能快?

因为 GPU 不靠单个线程低延迟取胜,而是靠大量线程并行。当一些 warp 等待内存时,调度器执行其他 ready warp,把等待时间隐藏掉。前提是并行度足够、寄存器和 shared memory 不把 occupancy 压得太低,并且访存模式能用上带宽。

统一内存寻址会让 CPU/GPU 编程完全无成本吗?

不会。统一内存或统一虚拟地址主要降低编程复杂度,让指针和地址空间更统一,但数据可能仍需要在 CPU 内存和 GPU 显存之间迁移。若访问模式频繁跨设备、粒度小或没有预取,page migration 和互连带宽会成为明显性能瓶颈。