GPU 传统上是用于 graphic 的,但由于其适合并行计算的构造,近几年被越来越多地运用到深度学习和人工智能领域,刮起了一阵猪都能飞的风。尤其是最近国外 AIGC 的技术突破,让 GPU 再次成为一个关注的焦点。所谓“适合并行计算”,应该是相对传统的 CPU 而言的。要论单个计算单元的能力,CPU 的 ALU(算术逻辑)和 FPU(浮点运算)是要强于 GPU 的:SM's 4-byte registers hold just a single float, whereas the vector registers in an Intel AVX-512 core hold 16 floats.
但论数量,CPU 就得自叹不如了。以 Nvidia 为例,其 GPU 由 SM (Streaming Multiprocessor) 构成(AMD 使用的术语是和 OpenCL 标准一致的 CU,即 Compute Unit,以下将混用这两个词),而一个 SM/CU 可运行成百上千的 thread(这个 thread 不同于 GPU 的 thread)。
因此也就需要大量保存这些 thread 状态信息的寄存器。以 Nvidia 的 Tesla V100 为例,一个 register file 含有 65536 个 registers。
构造的不同,决定了 CPU 擅长多任务、串行处理,而 GPU 则以高算力、高吞吐为强项。前段时间,美国限令 TSMC 暂停为一家中国的 GPU 公司生产芯片,因为该司宣称自己的算力世界第一(PPT 上说是 Nvidia 旗舰产品的三倍),把大家都吓到了。那“算力”究竟是什么呢?其中的一个重要指标就是 GFLOP (Floating Point Operations Per second),32 位浮点为 Signle Precision,64 位浮点为 Double Precision。以这个指标来看,CPU 确实只能甘拜下风:但在一个以 CPU 为球队核心的系统中,往往有不同种类的 workload,这时 highly parallel 和 less parallel 的处理器正好构成互补,都有各自的用武之地。那要设计一个怎样的技战术体系,才能让两者的搭配相得益彰,完成一个高质量的 teamwork 呢?瓷器活
咱们还是以拥有专属 memory 的 Discrete GPU(独立显卡)为例。假设现在有一张 JPEG 的图像从磁盘读取到系统内存了,需要 GPU 来处理,那么首先 GPU 的手要能够到这个内存位置对不对。让 GPU 的手够到 system memory 不难,但是中间得经过 PCIe 总线,速度上比不了访问自己的 video memory,所以最好还是能把数据拷贝到 video memory。copy 这种粗活,就不劳烦 CPU 亲自动手了,交给 DMA 这种专门的 copy engine 去做吧(CPU 侧有 DMA 控制器,一些 GPU 也有自己的 DMA 引擎)。以使用 GPU 侧的 DMA 为例,具体的过程是:CPU 通过 MMIO 操作,向 DMA engine 写入传输的源地址、目标地址和大小,然后触发 DMA transaction。GPU 内部往往有多个 IP,比如用于图形编码的、解码的,有些 IP 上会运行 firmware,为了让它们对物理内存的访问互不影响,也可能使用虚拟地址,经 GPU 内部的地址翻译单元(前文提过的 GpuMmu),转换成物理地址(如果是访问 system memory,理论上也可以使用 CPU 侧的 IOMMU 来转换)。每个 SM/CU 有自己的 TLB,但共享 Page table worker。相比于 CPU 的 TLB 平均 10% 的 miss rate,GPU 的 translation 量更大,TLB miss rate 可高达 30%。缓解 miss 的措施同 CPU 类似,一是使用 large page,二是增大 Page walk cache。此外,CPU 还可能发送一些 command,来控制 GPU 上 IP 的运行。
具体的过程是:CPU 侧 userspace 的程序(比如 CUDA),经过专有的编译器,形成一些 command queue,借助 kernel driver 创建的通道,发送到 GPU 侧。command 被 GPU 上的程序处理完后,会将结果返回给 CPU。
在此过程中,CPU 程序使用的是 CPU VA,GPU 程序使用的是 GPU VA (IOVA),如果两者能保持一致(pointer is pointer),将带来编程上的方便,这叫做 SVA (Share Virtual Address)。
CPU 寻址物理内存使用 MMU,而 GPU 使用系统的 IOMMU 或自己的 GpuMmu,在 SVA 框架下,当共享一段系统内存时,需要 MMU 和 IOMMU 访问的页表项一致。
小结
计算和图形处理无疑是当今 GPU 的核心功能,但由于其行为受到运行在 CPU 上软件的调控和指挥,因此还得和 CPU 侧的应用程序建立高效的信息传递机制。在此过程中,作为「搬运工」的 DMA 和作为「寻路者」的 IOMMU 都不可或缺,它们相互配合,共同满足了 GPU 编程模型的需要。