CH07-数据并行

数据并行就像是八车道的高速公路,虽然每辆车的速度相对平缓,但由于多辆车可以同时行进,所以通过某一点的车流量可以很大。

到目前为止,我们讨论的每一项技术都可以用于解决多种编程问题。相比之下,数据并行只适用于很窄的范围。顾名思义,数据并行是并行编程技术,而不是并发编程技术。

GPGPU

图形处理单元(GPU)是隐藏在电脑中的超级计算机。现代 GPU 是一个强力的数据并行处理器,其用于数学计算时的性能超越 CPU,这种做法称为基于图形处理器的通用计算,即 GPGPU。

图形处理与数据并行

计算机图形学主要研究如何处理数据、如何处理大量数据以及如何快速处理大量数据。3D 游戏的一个场景是由无数个小三角构成的,每个三角形都需根据与视点的透视关系计算出其在屏幕上的位置,并进行裁剪、光照处理、修饰纹理等,这些操作每秒钟都要进行 25 次以上。

虽然需要处理的计算量是很大的,但它有一个非常好的特性:施加在数据上的操作都s’s是相对姜丹的向量操作或矩阵操作。因此这种场景非常适合数据并行——多个计算资源会在不同的数据上并行施加相同的操作。

现代 GPU 是十分复杂但非常强力的并行处理器,其 1 秒钟可以处理几十亿个三角形。虽然设计 GPU 的主要目的是为了满足图形计算的需要,但是 GPU 也可用于更广的领域。

数据并行可以通过多种方式来实现,我们要学习其中两种:流水线和多 ALU。

流水线

虽然看上去两数相乘是一个原子操作,但如果从芯片上的门电路角度看,这个操作实际上是分几步完成的。这些操作通常被排列成流水线型,如下图:

NAME

上图是一个拥有 5 个步骤的流水线,如果每一步需要一个时钟周期来完成,那将一组数(两个数)相乘就需要 5 个时钟周期。但如果有多组数相乘,就可以通过让流水线饱和来获得更好的性能,如下图:

NAME

如果需要将 1000 组数相乘,每组数需要 5 个时钟周期,看上去总共需要 5000 个时钟周期,而如上图所示,仅需要略多于 1000 个时钟周期即可完成。

多 ALU

CPU 中负责进行乘法运算的组件称为算术逻辑单元,即 ALU,如下图:

NAME

只需要搭配足够多的内存总线,多个 ALU 就可以同时获取多个操作数,这样施加在大量数据上的运算就可以并行了,如下图:

NAME

GPU 的内存总线通常有 256 位或更宽,也就是说一次可以获取 8 个或更多个 32 位的浮点数。

混乱的局面

为了获得更好的性能,现实中的 GPU 会综合使用流水线、多 ALU 以及许多本书尚未提及的技术,这就进一步增加了理解 GPU 的难度。更遗憾的是,不同的 GPU 之间的共性很少,如果必须针对某个 GPU 架构开发代码,GPGPU 编程并非最佳选择。

OpenCL 定义了一种类 C 的语言,可以针对多种架构抽象的进行编程。不过的 GPU 厂商会提供各自的编译器和驱动程序,使代码可以被编译并运行在对应的 GPU 上。

总结

优点

数据并行非常适用于处理大量数值数据,尤其适合用于科学计算、工程计算及仿真领域,比如流体力学、有限元分析、N 体模型、模拟退火、蚁群优化、神经网络等。

GPU 不仅是强大的数据并行处理器,在能耗方面也变现出众,比传统的 CPU 有更加优秀的 GFLOPS/watt 指标。世界上最快的超级计算机都广泛使用 GPU 或专用数据并行协处理器,其中能耗指标低是一个重要的原因。

缺点

数据并行编程,更准确的说是 GPGPU 编程,在其适合领域内所向披靡。但并不适用于所有问题领域。值得一提的是,虽然用数据并行可以解决一些非数值问题(如自然语言处理),但这样做并不容易——现今的工具集绝大多数关注的是数值处理。

对 OpenCL 内核的调优是个技术活,理解底层架构的细节才能有效的进行调优。如果要写出高效的跨平台代码,就会变得异常复杂。在解决某些问题时,从主机往设备上复制数据会消耗大量时间,这会减弱甚至低效我们从事并行计算中获得的收益…..