Programming Massively Parallel Processors: A Hands-on Approach 大规模并行处理器 编程实战 日SEVIER nVIDIA 美) David B.Kirk 著 左罗医台能切比 译 Wen-mei W.Hwu MK 清华大学出版社
前 言 编写本书的原因 大众市场上的计算系统将多核CPU和众核GPU两者结合起来,在笔记本电脑上的运 算速度可以达到万亿次,在集群系统中的运算速度可以达到千万亿次。具有这种计算能力 以后,我们有望很快将计算实验推广到科学、工程、健康和商业等领域。通过使用计算实 验,很多人可能会在他们的学科领域中有所突破,这种规模是可控的、可观测的但规模水 平又是空前的。本书提供了实现这种构想的关键途径:教会数百万的本科生和研究生并行 编程,使计算思维能力和并行编程技能像数学运算那样普及。 从这门课的前身ECE498AL开始。在2006年的圣诞假期间,我们在疯狂地致力于幻 灯片的讲座和实验作业。David正在开发一套系统,试着把早期的GeForce8800 GTX GPU 卡经客轮拉到伊利诺伊州,但直到开学后几个星期才到货。显然也是在开学后的几个星期 以后,CUDA才开始公开。我们必须制定出合法的合同,以便在最初的几个星期内就能依 照NDA保密协议为学生开设这门课程。我们也需要公开,这样学生才会来报名,直到预 报告阶段之后我们才会公开这个课程。 2007年1月16日,我们上了第一堂课。所有事情才算是安顿下来。David每周都要乘 公交车来Urbana上课。我们招收了52个学生,比我们要招收的人数还多两个。前10次课, 我们大都要制作幻灯片。Wen-mei的研究生John Stratton,欣然主动地要求担任教学助理, 并帮我们布置实验室。所有的学生都签了NDA,因此在CUDA公开前,我们可以继续上 前几次课。我们把课堂的内容记录下来,但直到2月份才把它发布到网上。我们有物理、 天文、化学、电气工程、机械工程,以及计算机科学和计算机工程专业的研究生。教室里 洋溢的热情使我们都觉得这一切都是值得的。 从那以后,在一个学期的培养模式中,我们上3次课,在一周的密集培养模式中,我 们上两次课。ECE498AL这门课程已经成为一门永久性的课程,其中伊利诺伊州中的 Urbana-Champaign大学的ECE408很有名气。当我们第二次开ECE498AL这门课时,我们 开始着手编写本书的前几章。在我们2009年春季和夏季的班级中,我们测试了这些章节。 前4章也在麻省理工大学的班级上测试过,这门课由Nicolas Pinto在2009年春季时讲授
IV 大规模并行处理器编程实战 我们也在网上共享过前几章,从大量读者那里收到很多宝贵的反馈意见。我们受到了这些 反馈意见的鼓舞,并决定继续完成本书。现在,我们很乐意把本书的第1版呈现给读者。 目标受众 本书的目标受众是研究生和本科生,他们来自各种科学学科和工程学科,他们的学科 中需要用到计算思维能力和并行编程技巧,通过用已经普及的万亿次运算硬件能使他们在 自己的领域中有所突破。我们假设读者至少已经具备基本的C语言编程经验,因此不管是 在计算机科学领域内还是领域外,他们都是比较高级的程序员。我们专门面向计算领域内 的科学家,如机械工程、土木工程、电气工程、生物工程、物理和化学,这些科学家将通 过计算在他们的领域中进行进一步的研究。正因为这样,这些科学家既是他们领域内的专 家,也是高级程序员。本书采用基本的C语言编程技巧,来教会大家用C语言进行并行编 程。我们在CUDA中也用C语言,CUDA是一种支持NVIDIA公司开发的GPU并在少量 CPU上模拟的并行编程环境。大约有2亿左右的使用者和专业人士在使用这些处理器,其 中超过40000的程序员在主动使用CUDA。读者作为学习经验的一部分而开发的应用程序 将会被一个庞大的用户社区运行。 如何使用本书 本书通过具体资料提供我们在教ECE498AL时的经验。 分3个阶段的学习方法 我们为了能同时兼顾ECE498AL的课程和编程作业,把学习过程分成3个阶段: 第1个阶段一基于第3章的一次课致力于教会学生CUDA基本的存储器和线程模 型、CUDA对C语言的扩展和基本的编程与调试工具。在这次课后,学生要能在几个小时 内编出原始并行矩阵乘法的代码。 第2个阶段一下一个阶段是10次课,使学生从理论上理解CUDA存储器模型、CUDA 线程模型、GPU硬件的性能特点、现代计算机系统体系结构和普通的数据并行编程模式, 这些都是开发高性能并行应用程序所必需的。这些课的内容基于第47章。经过这个阶段 后,矩阵乘法代码的性能提高了将近10倍。经过这个阶段后,学生也应该完成关于卷积、 向量归约和前缀扫描的作业
前 言V 第3个阶段 旦学生掌握了CUDA基本的编程技巧,剩下的课程内容涵盖计算思 想、各种并行执行模型和并行编程规则。这些课的内容对应于第8~11章(这些课程的录音 和视频可以从网上下载(http:/courses.ece.illinois.edu/ece498/al). 把所有内容连贯起来:最终项目 当读者通过这门课、实验和本书的章节掌握了基础知识后,最终项目把所学到的经验 联系起来。最终项目对这门课如此重要,以致于它在这门课中的地位很显眼,大概需要花 费两个月的时间。它采用了5个创新点:指导、专题讨论、检查、最终的报告和专题讨论 会(在ECE498AL的网站上可以下载最终项目的更多信息(http://courses..ece.illinois.edu/ ece498/al),我们想提供对这些设计因素的深入思考). 我们鼓励学生选取目前研究领域中一些具有挑战性的问题作为他们的最终项目。这个 过程中,指导老师会成立计算科学研究小组来提出问题,这些研究小组就是后来的导师。 我们要求导师提供一到两页的项目规格说明表,这个表应该简单地描述应用程序的重要性, 导师想要学生组在应用程序中完成什么工作,需要了解与开发应用程序相关的技术和技能 (特定类型的数学、物理、化学课程),以及一个网站和传统资源列表。学生可以利用这些 表中对应的内容了解技术背景、构建模块,以及特定的实现方式和代码示例对应的具体的 URL或即路径。这些项目说明表也应该为学生提供学习经验,在以后的工作当中可以定义 他们自己的研究项目(在ECE498AL课程的网站上可以下载几个这种示例)。 我们也鼓励读者在项目的选择过程中可以与他们的导师不断地交流。只要学生和导师 都同意了某个项目,他们就会密切地联系、频繁地切磋并不断地报告项目的进展情况。我 们试图为学生和导师之间的协作关系提供方便,不仅是为学生也是为导师增长宝贵的经验。 项目专题讨论 整个班级对彼此的最终项目的意见的主要交流方式是专题讨论。我们通常会安排6个 报告厅来进行专题讨论。专题讨论是为学生设计的。例如,如果一个学生已经确定了项目, 就可以把专题讨论作为一种提出初步想法、获取反馈意见和招募队友的场所。如果一个学 生还没有确定自己的项目,他可以仅参加演讲,参加讨论并加入其中的一个项日组。在项 目专题讨论期间,学生没有等级之分,这么做是为了营造一种和谐的气氛,所以学生可以 集中精力与导师、教学助理以及班上其他同学进行有意义的谈话。 有了专题讨论日程表后,导师和教学助理就可以花些时间给项目组提供反馈意见,以 便学生也可以问问题。演讲的时间限制在10分钟内,因此在上课期间还有反馈和提问的时
VI 大规模并行处理器编程实战 间。假设每次课90分钟,这将班级的大小限制在36人左右。为了严格控制时间安排并使 反馈时间最大化,所有演示文稿预先加载到PC中。由于在专题讨论中并不是每个学生都 会出席,因此每个班大概能容纳50个学生,可以根据需要提供额外的专题讨论时间。 导师和教学助理必须参加所有演讲,并给出有用的反馈意见。学生经常在下列问题上 寻求帮助。第一,对于给定的时间,项目的规模是太大还是太小?第二,在这个领域中是 否存在有利于这个项目的现有工作?第三,为并行执行而设立的目标计算是否适合CUDA 编程模型? 设计文档 一旦学生决定选择某个项目并形成了团队后,我们就要求学生提交一个关于项目的设 计文档。这有助于他们在正式进入项目前,思考整个项目的步骤。制定这种计划的能力对 于他们将来事业的成功很重要。设计文档应该讨论项目的背景与目的,应用程序级目标和 可能带来的影响,应用程序的主要特点,设计的概况,实现计划,他们的性能目标,经过 论证的计划和可接受的测试,以及项目进度表。 在班级专题讨论会的前一周,教学助理对最终项目组进行一次项目检查。这个检查过 程有助于确保学生没有偏离轨道,并且他们已经发现了设计过程早期存在的障碍。要求学 生组带上他们最初的草案来检查,草案包括其应用程序的如下3个版本:()性能最优的 CPU串行代码,采用SSE2和其他优化方案构建一系列健壮的基本代码,便于比较它们的 速度:(2)性能最优的CUDA并行代码。这个版本是项目的主要成果;(3)基于版本3中同 样的算法,但是用单精度实现的CU串行代码版本。学生可以用这个版本认识到并行算法 涉及额外的计算量时带来的系统开销。 学生组都要准备好讨论的主要思想,包括在每个版本用到的代码,任何浮点精度问题, 任何针对应用程序之前结果的比较,以及如果他们显著地提高了运行速度会对这个领域产 生什么影响。依我们的经验来看,在班级专题研讨会前一周进行检查,这是最佳的时间安 排。如果时间太早,可能会把时间浪费在对不太成熟的项目和没有太大意义的会议上。如 果时间太晚,学生就没有足够的时间根据反馈意见修订他们自己的项目。 项目报告 学生应该提交一份项目报告,这个报告关于他们的团队的主要发现。把6次课的时间 放在一天,举行班级专题讨论会。在专题讨论会期间,学生所用的演讲时间正比于团队的 规模。在演讲期间,学生要强调项目报告中做得最好的部分,这样也有益于整个班集体。 演讲过程在学生的成绩中占的比例很高。每个学生必须单独回答一个直接向他或她提出的
前言VI 问题,因此同一个团队中每个学生的成绩也不相同。专题研讨会为学生提供了很好的制作 简洁的演示文稿的机会,简洁的演示文稿能激发其他人阅读整篇文档。演讲结束后,学生 要提交一份最终项目的完整报告。 在线补充 如果教师用本书作为课程的教材,就可以使用我们的实验安排、最终项目指南和示例 项目说明。虽然本书提供了这些课程的知识性内容,但要想实现全部教学目标还应该查阅 其他资料。我们也想邀请大家充分利用与本书相关的在线资料,这些资料可以在ELSEVIER 出版社的网站www.elsevierdirect.com/9780123814722上下载。 最后,我们鼓励读者提交反馈意见。如果读者有关于改进本书的任何想法或者对在线 资料的补充,我们想听听读者的想法。当然,我们也想知道读者喜欢本书的哪一方面。 David B.Kirk Wen-mei W.Hwu
目 录 第1章引言…… 1.1GPU与并行计算机… …2 1.2现代GPU的体系结构 …7 13为什么需要更高的速度和并行化…8 1.4并行编程语言与模型… …11 1.5综合目标… …12 1.6本书的组织结构… …13 第2章GPU计算的发展历程… …17 2.1图形流水线的发展… …18 2.1.1固定功能的图形流水线时代… 18 21.2可编程实时图形流水线的发展… …21 213图形与计算结合的处理器… …23 2.1.4GPU:一个中间步骤… …25 2.2GPU计算… …26 2.2.1可扩展的GPU… …27 2.2.2发展近况… …27 2.3未来发展趋势… …28 第3章CUDA简介… …31 3.1 数据并行性… …32 3.2CUDA的程序结构… …33 3.3 矩阵乘法示例… …34 3.4设备存储器与数据传输… …37 3.5 kernel函数与线程… …41 3.6小结… …45 3.6.1函数声明… …45 3.6.2启动kernel函数… …46 3.6.3预定义变量… …46
X大规模并行处理器编程实战 3.6.4运行时AP… …46 第4章 CUDA线程… 49 4.1CUDA线程组织结构 50 4.2使用blockIdx和threadIdx… …54 4.3同步与透明可扩展性… …58 4.4线程分配… 59 4.5线程调度和容许延时… …60 4.6小结… 62 4.7习题… …63 第5章 CUDA存储器模型… 65 5.1存储器访问效率的重要性… …66 5.2CUDA设备存储器的类型… …67 5.3减少全局存储器流量的策略… …70 5.4存储器 一限制并行性的一个因素 …76 5.5小结… …77 5.6习题 …78 第6章性能优化… …79 6.1更多关于线程执行的问题… …80 6.2全局存储器的带宽… …86 6.3SM资源的动态划分… …93 6.4数据预取… …95 6.5 指令混合… …97 6.6线程粒度 …98 6.7可度量的性能和小结 …99 6.8习题… …100 第7章浮点运算… 105 7.1浮点格式… …106 7.1.1M的规范化表示… 106 7.1.2E的余码表示… …107 7.2能表示的数 …109 7.3特殊的位模式与精度 …113
录XⅪ 7.4算术运算的准确度和舍入… …114 7.5 算法的优化 …114 7.6小结… …115 7.7习题…116 第8章 应用案例研究:高级MRI重构 …117 8.1 应用背景 …118 8.2 迭代重构… …120 8.3 计算F …123 8.4最终评估 …139 8.5习题 …142 第9章应用案例研究:分子可视化和分析 …143 9.1应用背景… …144 9.2 kernel函数简单的实现方案 …145 9.3指令执行效率 …149 9.4存储器合并 …151 9.5 附加性能比较… …154 9.6采用多GPU …156 9.7习题 …157 第10章并行编程和计算思想 …159 10.1并行编程的目标 …160 10.2问题分解… …161 10.3 算法选择 …163 10.4计算思想 …168 10.5习题… …169 第11章 OpenCL简介… 171 11.1背景… …172 11.2数据并行性模型… …173 113设备的体系结构… …175 1l.4 kernel函数 …176 1l.5设备管理和启动kernel-… …177 11.60 penCL中的静电势图谱…179
‖大规模并行处理器编程实战 11.7小结 …183 11.8习题… …184 第12章结论与展望… …185 12.1重申月标… …186 12.2存储器体系结构的演变 …187 12.2.1大型虚拟和物理地址空间… 187 12.22统一的设备存储空间… …188 12.2.3可配置的缓存和暂时存储器… …188 12.2.4提高原子操作的速度… …189 12.2.5提高全局存储器的访问速度… …189 12.3 kernel函数执行控制过程的演变 …190 12.3.1 kernel函数内部的函数调用… …190 12.3.2 kernel函数中的异常处理… …190 12.3.3多个kernel函数的同步执行… …191 12.3.4可中断的kernel函数… …191 12.4内核的性能… …………191 12.4.1双精度的速度… … 191 12.4.2提高控制流的效率… …192 12.5编程环境… …192 12.6美好前景… …193 附录A矩阵乘法主机版的源代码… 195 附录BGPU的计算能力… 207