Preface 前 言
多核架构出现在21世纪的第一个10年里,给并行计算带来了勃勃生机。新平台需要新方法来进行软件开发,其中一个新方法就是把工具和工作站网络时代的惯例同新兴软件平台(如CUDA)相结合。 为满足这种需求,本书将介绍目前主流的工具和技术,不仅是各自独立的工具和技术,更重要的是将它们相互结合。书中会提供多平台和程序设计范例(如消息传递和线程)高效结合的实例。顾名思义,“Hybrid”(混合)计算,是高性能计算的一个新趋势,针对百亿亿级的性能需求,使软件有可能扩展到数百万的线程上。
所有章节都包含丰富的示例和实际问题,并比较了不同的设计脚本,重点在于如何使其实际运作起来。那些能使得高效的软件开发区别于徒劳无功的软件开发训练的所有细节,都以有序的形式呈现出来。
本书介绍了从20世纪90年代继承而来的最新的先进工具(例如OpenMP和MPI标准),并包括更前沿的平台,如具有复杂线程管理功能的Qt库,以及具有在不同多核架构(包括CPU和GPU)上配置相同软件功能的Thrust模板库。
我不可能面面俱到地给出多核开发中的所有可用工具。即使是POSIX线程之类的一些行业标准,书中也并未涉及。
本书不仅旨在介绍主流范型(范围从OpenMP的串行代码半自动并行化到用来巩固MPI的显式通信“plumping”)的实例,还要讲解高效的多核软件开发背后的原理,并指导读者进行实践。
本书内容本书可以分成如下几个逻辑单元,虽然书中没有明确地这样区分。
多核软件的设计概述概述:第1章介绍多核硬件,讨论了一些具有影响力的体系结构范型示例。第1章也介绍了加速比和效率,在评估多核和并行软件时这些是基本的度量方式。1.5节告诉读者如何从多核和众核硬件激动人心的新进展中预测出什么是人们所期待的方法。
第2章讨论可应用于并行和多核软件开发的方法论与设计模式,包括工作分解模式和程序结构模式。
共享内存编程:讨论了两种不同的共享内存并行编程方法——显式并行化和隐式并行化。在显式方面,第3章覆盖了线程和两种最常用的同步机制——信号和monitor。对于通常遇到的设计模式(如生产者–消费者模式和读者–写者模式),均给出了详细解释并应用于一系列示例中。
在隐式方面,第4章介绍了OpenMP标准,该标准的设计使得我们能以最少的工作量将现有串行代码并行化。它可使开发时间大大缩短。该标准还有其他的好处,如解决了循环间存在的依赖。
分布式内存编程:第5章介绍了分布式内存并行编程的事实标准——消息传递接口(MPI)。MPI同多核编程相关,因为它旨在把程序从一个共享内存多核机器上扩展到一个具有上百万节点的超级计算机上。就其本身而言,MPI能够为利用多核机器的多重分解提供基础,以作为独立的虚拟平台。
这部分涉及的特征包括点对点通信和集合通信,也包括单边通信。有一节内容专门针对Boost.MPI库,虽然还未实现全部的功能,但它的确简化了使用MPI的过程。
GPU编程:GPU是把本书内容组织在一起的最初原因之一。以此类推到共享内存编程,这里从两个方面讨论了针对GPU软件开发的问题。一方面是NVIDIA的CUDA中的具体方法,该方法中的内存传输、数据放置和线程执行配置都需要仔细计划。这将在第6章进行介绍。
另一方面是高级的Thrust模板库算法方法,这部分在第7章中讨论。程序设计的类标准模板库(STL-like)方法为Thrust提供了把CPU和GPU平台均作为目标的能力,在本书所介绍的工具中,这是一个独特的特性。
负载均衡:第8章讨论在多核开发中经常被低估的一个方面。一般来说,一旦异构计算资源开始运行,就应该认真考虑负载均衡。举例来说,一个CPU和一个GPU构成这一组资源,我们在满足需求时不能只考虑一群不同机器的集合。第8章简要讨论了Linda语言,这可以被看做动态负载均衡的高级抽象。
书中主要的关注点在静态负载均衡,以及可以用于驱动负载分区和数据通信序列的数学模型。
很多场景中都应用了一种已经得到认可的方法论——可分负载理论(DLT),并且给出了解释。书中还介绍了一个简单的C++库,它实现了部分过去20年中已经发表过的DLT研究结果。
软件和硬件要求书中的示例都是在Ubuntu Linux系统上开发和测试的。本书中使用的所有软件都是可以免费获取或者是开源的。其中包括:
GNU C/C++ 编译器组件 4.8.x(兼容 CUDA),组件4.9.x (兼容OpenMP 4.0)Digia的 Qt 4.x 库或者Qt 5.x 库OpenMPI 1.6MPENVIDIA的 CUDA SDK 6.5Thrust 库 (版本1.7)如果拥有近期正确安装的Linux,并装有版本等于或高于上述软件列表中版本号的软件,那么执行本书中提供的示例代码应该不会有任何问题。虽然我没有提供Windows平台下的生成文件或者使用Visual Studio编译和执行示例代码的指令,但未安装Linux的用户只需进行少量代码改动就可以把示例移植到Windows上。考虑到我们使用的是标准C/C++库,因此对于代码的改动(如果存在)应该只会影响头文件,也就是那些需要被包括的(include)文件。
硬件部分唯一的实际局限是需要计算能力为2.x或者更高的NVIDIA GPU。早期芯片也可以使用,但是它们的独特性,尤其是关于全局内存的访问,在书中没有给出解释。没有NVIDIA GPU的用户可以通过使用附录E中介绍的方法来成功执行CUDA程序。
示例代码书中的程序可在Elsevier网站(http://store.elsevier.com/9780124171374)上获取压缩包。
程序存放在特定的文件夹中,以章名区分,如图1所示。
对于书中的代码清单,均在第1行给出了相对于该章目录的对应文件的位置。
单文件程序的第一行注释里包含编译和链接命令。多文件项目存放在它们自己的目录中,其中也包含一个生成文件或者一个项目(.pro)文件。如果需要输入样本值,该部分数据也在该目录下的文件中提供。
图1 截屏显示了示例代码在特定章节的文件夹中的组织方式教学建议本书中所涉及的内容适合高年级本科生或者研究生课程。学生需要具备的背景知识包括掌握C和C++编程(两种语言的使用贯穿整本书)、基本的操作系统概念,以及基本的计算机体系结构常识。
根据各自的需求,教师可以选择使用以下列出的一些教学建议。前两章是为后面的章节奠定基础,因此它们在所有的路径中都包括:
重点在并行编程(本科生):
第1章:Flynn分类法、当代的多核设备、性能标准。1.1~1.5节。
第2章:设计、PCAM方法论、分解模式、程序结构模式。2.1~2.5节。
第3章:线程、信号、monitor。3.1~3.7节。
第4章:OpenMP的基本概念、工作共享结构, 4.1~4.4节。
第5章:MPI、点对点通信、集合操作、目标/结构通信,以及调试和性能分析。5.1~5.12节、5.15~5.18节和5.20节。
第6章:CUDA编程模型,内存层次结构,针对GPU的优化。6.1~6.6节、 6.7.1节、6.7.3节、 6.7.6节、6.9~6.11节和6.12.1节。
第7章:Thrust基本的知识。7.1~7.4节。
第8章:负载均衡。8.1~8.3节。
重点在多核编程(本科生):
第1章:Flynn分类法、当代的多核设备、性能标准。1.1~1.5节。
第2章:设计、PCAM方法论、分解模式、程序结构模式。2.1~2.5节。
第3章:线程、信号、monitor。3.1~3.10节。
第4章:基本的OpenMP、工作共享结构,以及正确性和性能问题。4.1~4.8节。
第5章:MPI,点对点通信、集合操作、目标/结构通信,以及调试和性能分析。5.1~5.12节、 5.16~5.18节和5.21节。
第6章:CUDA编程模型、内存层次结构,以及针对GPU的优化。6.1~6.10节、 6.12.1节。
第7章: Thrust基本的知识。7.1~7.4节。
第8章:负载均衡。8.1~8.3节。
高级多核编程: 第1章:Flynn分类法、当代的多核设备、性能标准。1.1~1.5节。
第2章:设计、PCAM方法论、分解模式、程序结构模式。2.1~2.5节。
第3章:线程、信号、monitor、高级线程管理。3.1~3.10节。
第4章:OpenMP基本的知识,工作共享结构,以及正确性和性能问题。4.1~4.8节。
第5章:MPI、点对点通信、集合操作、目标/结构通信,以及调试和性能分析。5.1~5.12节、 5.15~5.18节和 5.21~5.22节。
第6章:CUDA编程模型、内存层次结构,以及针对GPU的优化。6.1~6.12节。
第7章:Thrust数据类型和算法。7.1~7.7节。
第8章:负载均衡、基于DLT的分割。8.1~8.5节。