最近找到了一本介绍缓存一致性的书:A Primer on Memory Consistency and Cache Coherence. 本文主要是针对其第十章 Consistency and Coherence for Heterogeneous Systems 的学习笔记。下图是异构系统的缓存架构图。
一、GPU一致性的特点
作为异构系统的加速器中最重要的一部分,GPU 将会是着重介绍的部分。
1.1 GPU的运行流程
首先我们需要明确 GPU 究竟是如何运行。区别于 CPU,GPU 最核心的特点就是高度的并行性。为了搞明白 GPU 到底是如何运行的,这里将结合一个图像处理程序的案例来说明。以渲染一个 3D 场景为例,这涉及到很多复杂的并行计算任务,比如光照、阴影、纹理映射等。GPU 是如何在如此庞大的任务中快速完成计算的呢?
第一步,任务分配:CPU 和 GPU 的协作
首先,CPU 会启动整个程序并负责一些高层次的任务,比如读取 3D 模型、处理输入、计算相机位置等。然后,当需要进行大量的图形处理(比如渲染每一帧画面)时,CPU 会将这些任务分配给 GPU 来处理。这是因为 GPU 擅长同时处理大量的并行计算任务。就像工厂的主管(CPU)先负责规划生产任务,接着将具体的生产任务(渲染 3D 场景)交给流水线上的大量工人(GPU)。
第二步,GPU 内核与线程:分配并行任务
GPU 收到任务后,将把这些复杂的图形处理工作分解成很多小任务。比如,渲染一张图像时,图像上的每一个像素点都需要计算它应该是什么颜色,这个计算过程是并行的——每个像素点可以独立地计算。
在 GPU 中,这些独立的小任务会分配给称为"线程"的计算单元,每个线程负责处理一个像素点或一小块像素。线程们被组织成 CTA(Cooperative Thread Arrays),每个 CTA 负责处理一个图像的一部分。比如,一个 CTA 可能负责一片 16x16 像素的区域。CTA 就像一个小组工人,他们负责处理一块区域的像素。
第三步,线程层次结构:CTA 和存储器
GPU 中的线程并非是独立工作的,它们会利用硬件的分层结构来高效合作。CTA 内的所有线程会被分配到同一个流多处理器(SM,Streaming Multiprocessor)上,这意味着它们共享同一个 L1 缓存。L1 缓存是速度最快的缓存,CTA 内的线程可以通过它快速共享数据。
当不同的 CTA 之间需要通信时(例如跨区域的光照计算),它们会通过更大的 L2 缓存共享数据。L2 缓存是多个 CTA 共享的,但访问速度比 L1 缓慢一些。如果多个 CTA 需要共享更多全局数据,它们则会通过系统的共享内存(比如最后一级缓存 LLC)进行通信。
第四步,并行执行:成百上千的线程同时工作
由于图形渲染是一个高度并行化的任务,GPU 上的成百上千个线程可以同时处理图像的不同部分。例如,如果你要渲染一张 1920x1080 的图像,这意味着有 2 百万多个像素需要计算。GPU 会将这些任务分配给不同的线程,并行地处理每个像素的计算。这种大规模的并行处理是 GPU 相比 CPU 在图形处理时最大的优势。
第五步,最终结果:图像呈现
当 GPU 完成所有的计算后,所有的线程都会将它们各自计算好的像素颜色值传回显存,然后通过显示控制器渲染到屏幕上。这就完成了一帧图像的渲染。因为 GPU 的大规模并行计算能力,它可以在极短的时间内完成这种高密度的图像计算,从而实现高帧率、流畅的图形显示。
这个例子例子展示了 GPU 如何通过并行计算、线程层次结构以及高效的内存访问来快速完成复杂的任务。总而言之,GPU 的并行处理能力和其硬件架构,使得它非常擅长处理大规模的计算密集型任务,比如图形渲染、深度学习、科学计算等。通过细分任务、合理组织线程、充分利用缓存,GPU 能够在极短的时间内完成巨量的数据处理任务。
1.2 一致性的定义
在介绍 GPU 的一致性,或者说任何其他的什么缓存一致性之前。首先需要澄清一个概念,即什么是一致性。一致性分为两个维度 Consistency 和 Coherence,这是两个密切相关但各自侧重不同的术语。