新書推薦:
![闲坐说金庸:揭秘比小说更精彩的金庸人生传奇](http://103.6.6.69/upload/mall/productImages/y24/8/9787554585689.jpg)
《
闲坐说金庸:揭秘比小说更精彩的金庸人生传奇
》
售價:HK$
74.8
![二战新史:鲜血与废墟中的世界,1931——1945](http://103.6.6.66/upload/mall/productImages/24/27/9787521763737.jpg)
《
二战新史:鲜血与废墟中的世界,1931——1945
》
售價:HK$
216.2
![汉字古今谈](http://103.6.6.66/upload/mall/productImages/24/28/9787101165777.jpg)
《
汉字古今谈
》
售價:HK$
41.4
![天亡之秋](http://103.6.6.66/upload/mall/productImages/24/28/9787203134558.jpg)
《
天亡之秋
》
售價:HK$
89.7
![KO!再见,焦虑症!](http://103.6.6.66/upload/mall/productImages/24/27/9787523106365.jpg)
《
KO!再见,焦虑症!
》
售價:HK$
57.3
![嘉靖帝:丹鼎青烟里的王朝乱象](http://103.6.6.66/upload/mall/productImages/24/26/9787547324448.jpg)
《
嘉靖帝:丹鼎青烟里的王朝乱象
》
售價:HK$
97.8
![甲骨文字趣释](http://103.6.6.66/upload/mall/productImages/24/28/9787229185947.jpg)
《
甲骨文字趣释
》
售價:HK$
66.7
![利润的暗影:资本主义全球扩张与环境变迁史(探秘历史深处的经济与生态交织)](http://103.6.6.66/upload/mall/productImages/24/27/9787308250030.jpg)
《
利润的暗影:资本主义全球扩张与环境变迁史(探秘历史深处的经济与生态交织)
》
售價:HK$
82.8
|
編輯推薦: |
·讨论如何利用MPI、Pthreads、OpenMP和CUDA这四种广泛使用的并行编程API来编写并行程序,其中,关于CUDA的章节是全新的。 ·新增关于GPU编程和异构编程的章节,此外,还新增了与并行程序开发相关的示例和练习。 ·学习曲线友好,从简单的编程示例开始,逐步构建更具挑战性的示例,关于四种API的章节相互独立,便于读者根据需要选择阅读。 ·配有丰富的练习和编程作业,所有源代码均可从本书网站免费下载。
|
內容簡介: |
本书主要讲解如何使用MPI、Pthreads和OpenMP开发有效的并行程序,并在多核和集群架构上编译运行并行程序。本书第1版已经过广泛的本科教学实践,第2版做了细致的更新,清晰地阐释了如何设计、调试和评估分布式和共享内存程序的性能,并新增关于GPU编程和异构编程的内容,对加速器的讨论更加全面。第2版还对习题做了更新,读者可通过习题进一步熟悉并掌握编译、运行和修改示例程序的方法。
|
關於作者: |
彼得·S.帕切科(PeterS. Pacheco)旧金山大学计算机科学荣休教授,曾任旧金山大学计算机系主任、数学系主任。之前曾为加州大学洛杉矶分校教授。他的主要研究方向是并行科学计算,包括电路仿真的并行软件开发、语音识别、模拟大规模神经元网络等。他拥有佛罗里达州立大学数学博士学位。
马修·马伦塞克(Matthew Malensek) 旧金山大学计算机科学系助理教授。他的研究兴趣是数据科学的系统方法,重点是可扩展分析、海量数据流的存储和管理,以及云/边缘计算,这些项目涵盖大气科学、流行病学和地理信息系统等领域。他拥有科罗拉多州立大学计算机科学博士学位。
|
目錄:
|
目 录
An Introduction to Parallel Programming, Second Edition
译者序
前言
第1章 为什么需要并行计算1
1.1 为什么需要不断提高性能1
1.2 为什么需要建立并行系统2
1.3 为什么需要编写并行程序2
1.4 如何编写并行程序5
1.5 我们将做什么6
1.6 并发、并行和分布式7
1.7 本书其余部分8
1.8 一点警告8
1.9 排版惯例9
1.10 小结9
1.11 练习10
第2章 并行硬件与并行软件12
2.1 背景知识12
2.1.1 冯·诺依曼体系结构12
2.1.2 进程、多任务和线程13
2.2 冯·诺依曼模型的改进14
2.2.1 缓存基础14
2.2.2 缓存映射16
2.2.3 缓存和程序:示例17
2.2.4 虚拟内存18
2.2.5 指令级并行19
2.2.6 硬件多线程21
2.3 并行硬件22
2.3.1 并行计算机的分类22
2.3.2 SIMD系统22
2.3.3 MIMD系统24
2.3.4 互连网络26
2.3.5 高速缓存一致性30
2.3.6 共享内存与分布式内存32
2.4 并行软件33
2.4.1 注意事项33
2.4.2 协调进程/线程33
2.4.3 共享内存34
2.4.4 分布式内存37
2.4.5 GPU编程40
2.4.6 混合系统编程40
2.5 输入和输出41
2.5.1 MIMD系统41
2.5.2 GPU41
2.6 性能42
2.6.1 在MIMD系统中的加速比和
效率42
2.6.2 阿姆达定律44
2.6.3 MIMD系统的可扩展性45
2.6.4 MIMD程序的计时46
2.6.5 GPU性能48
2.7 并行程序设计49
2.7.1 示例49
2.8 编写和运行并行程序53
2.9 假设53
2.10 小结54
2.10.1 串行系统54
2.10.2 并行硬件55
2.10.3 并行软件56
2.10.4 输入和输出57
2.10.5 性能57
2.10.6 并行程序设计58
2.10.7 假设58
2.11 练习58
第3章 基于MPI的分布式
内存编程62
3.1 入门62
3.1.1 编译和执行63
3.1.2 MPI程序64
3.1.3 MPI_Init和
MPI_Finalize64
3.1.4 通信域、MPI_Comm_size和MPI_Comm_rank65
3.1.5 SPMD程序66
3.1.6 通信66
3.1.7 MPI_Send66
3.1.8 MPI_Recv67
3.1.9 消息匹配68
3.1.10 status_p参数69
3.1.11 MPI_Send和MPI_Recv的
语义69
3.1.12 一些潜在的陷阱70
3.2 MPI中的梯形法则70
3.2.1 梯形法则70
3.2.2 梯形法则的并行化71
3.3 处理I/O74
3.3.1 输出74
3.3.2 输入75
3.4 集合通信76
3.4.1 树形结构的通信76
3.4.2 MPI_Reduce77
3.4.3 集合通信与点对点通信78
3.4.4 MPI_Allreduce79
3.4.5 广播80
3.4.6 数据分布82
3.4.7 分散83
3.4.8 收集84
3.4.9 综合实例85
3.5 MPI派生的数据类型88
3.6 MPI程序的性能评估91
3.6.1 计时91
3.6.2 结果93
3.6.3 加速比和效率95
3.6.4 可扩展性95
3.7 一种并行排序算法96
3.7.1 一些简单的串行排序算法96
3.7.2 并行奇偶移项排序98
3.7.3 MPI程序中的安全性100
3.7.4 关于并行奇偶排序的一些
补充细节102
3.8 小结103
3.9 练习106
3.10 编程作业112
第4章 Pthreads共享内存编程114
4.1 进程、线程和Pthreads114
4.2 Hello, world115
4.2.1 执行116
4.2.2 预备117
4.2.3 启动线程117
4.2.4 运行线程119
4.2.5 停止线程120
4.2.6 错误检查120
4.2.7 启动线程的其他方法120
4.3 矩阵-向量乘法121
4.4 临界区123
4.5 忙等待126
4.6 互斥锁128
4.7 生产者-消费者同步和信号量131
4.8 栅栏和条件变量135
4.8.1 忙等待和互斥锁135
4.8.2 信号量136
4.8.3 条件变量137
4.8.4 Pthreads栅栏139
4.9 读写锁139
4.9.1 排序的链表函数140
4.9.2 多线程链表142
4.9.3 Pthreads的读写锁144
4.9.4 各种实现方案的性能145
4.9.5 实现读写锁146
4.10 缓存、缓存一致性和伪共享147
4.11 线程安全150
4.11.1 不正确的程序可以产生
正确的输出153
4.12 小结153
4.13 练习154
4.14 编程作业159
第5章 OpenMP共享内存编程161
5.1 入门162
5.1.1 编译和运行OpenMP程序163
5.1.2 程序163
5.1.3 错误检查165
5.2 梯形法则166
5.2.1 第一个OpenMP版本166
5.3 变量的作用域170
5.4 归约子句170
5.5 parallel指令173
5.5.1 注意事项174
5.5.2 数据依赖性175
5.5.3 寻找循环迭代相关176
5.5.4 估算π176
5.5.5 关于作用域的更多内容178
5.6 关于OpenMP中的循环的更多
内容:排序179
5.6.1 冒泡排序179
5.6.2 奇偶移项排序180
5.7 循环的调度182
5.7.1 schedule子句183
5.7.2 static调度类型185
5.7.3 dynamic和guided调度
类型185
5.7.4 runtime调度类型186
5.7.5 哪种调度187
5.8 生产者和消费者188
5.8.1 队列188
5.8.2 消息传递188
5.8.3 发送消息189
5.8.4 接收消息189
5.8.5 终止检测190
5.8.6 开始190
5.8.7 atomic指令191
5.8.8 临界区和锁191
5.8.9 在消息传递程序中使用锁193
5.8.10 critical指令、atomic
指令或锁194
5.8.11 注意事项194
5.9 缓存、缓存一致性和伪共享195
5.10 任务化199
5.11 线程安全202
5.11.1 不正确的程序可以产生
正确的输出204
5.12 小结204
5.13 练习208
5.14 编程作业211
第6章 用CUDA进行GPU编程215
6.1 GPU和GPGPU215
6.2 GPU架构215
6.3 异构计算217
6.4 CUDA hello217
6.4.1 源代码218
6.4.2 编译与运行程序219
6.5 深入了解219
6.6 线程、线程块和线程网格220
6.7 NVIDIA计算能力和设备架构223
6.8 向量加法223
6.8.1 核函数224
6.8.2 Get_args函数225
6.8.3 Allocate_vectors函数和
托管内存226
6.8.4 main函数调用的其他函数227
6.8.5 显式内存传输229
6.9 从CUDA核函数返回结果231
6.10 CUDA梯形法则I233
6.10.1 梯形法则233
6.10.2 一种CUDA实现234
6.10.3 初始化、返回值和最后
更新235
6.10.4 使用正确的线程236
6.10.5 更新返回值和atomicAdd
函数236
6.10.6 CUDA梯形法则的性能237
6.11 CUDA梯形法则II:提升性能238
6.11.1 树形通信238
6.11.2 局部变量、寄存器、共享和
全局内存239
6.11.3 线程束和线程束洗牌240
6.11.4 使用线程束洗牌实现树形
全局求和241
6.11.5 共享内存和线程束洗牌的
替代方案242
6.12 用warpSize个线程块实现
梯形法则243
6.12.1 主机代码244
6.12.2 使用线程束洗牌的核函数244
6.12.3 使用共享内存的核函数244
6.12.4 性能245
6.13 CUDA梯形法则III:使用具有
多个线程束的线程块245
6.13.1 __syncthreads函数246
6.13.2 关于共享内存的更多内容247
6.13.3 使用共享内存的线程束
求和247
6.13.4 共享内存库248
6.13.5 收尾工作249
6.13.6 性能251
6.14 双调排序251
6.14.1 串行双调排序251
6.14.2 蝶式交换和二进制表示254
6.14.3 并行双调排序I256
6.14.4 并行双调排序II258
6.14.5 CUDA双调排序的性能259
6.15 小结260
6.16 练习264
6.17 编程作业267
第7章 并行程序开发269
7.1 两种n-body问题的解决方案269
7.1.1 问题描述269
7.1.2 两种串行方案270
7.1.3 并行化n-body求解方案274
7.1.4 关于I/O的说明276
7.1.5 使用OpenMP并行化基本
求解方案277
7.1.6 使用OpenMP并行化简化
求解方案279
7.1.7 评估OpenMP代码283
7.1.8 使用Pthreads并行化求解
方案284
7.1.9 使用MPI并行化求解方案284
7.1.10 使用MPI并行化简化求解
方案286
7.1.11 MPI简化求解的性能291
7.1.12 使用CUDA并行化基本
求解方案292
7.1.13 关于CUDA协同组的说明294
7.1.14 基本CUDA n-body求解
方案的性能295
7.1.15 提高CUDA n-body求解
方案性能的方法295
7.1.16 在n-body求解方案中使用
共享内存技术296
7.2 样本排序299
7.2.1 样本排序和桶排序299
7.2.2 选择样本数据300
7.2.3 Map函数的简单实现301
7.2.4 Map的另一种实现方案302
7.2.5 并行化样本排序305
7.2.6 使用OpenMP实现样本
排序308
7.2.7 使用Pthreads实现样本
排序312
7.2.8 使用MPI实现样本排序314
7.2.9 使用CUDA实现样本排序323
7.3 注意事项331
7.4 使用哪种API331
7.5 小结332
7.5.1 MPI333
7.6 练习334
7.7 编程作业340
第8章 下一步该怎么走343
参考文献345
|
內容試閱:
|
前 言
An Introduction to Parallel Programming, Second Edition
一段时间以来,并行硬件已经无处不在:很难找到不使用多核处理器的笔记本计算机、台式计算机或服务器。集群计算在今天几乎和20世纪90年代的高功率工作站一样普遍,而云计算正在使分布式内存系统像台式计算机一样普及。尽管如此,大多数计算机科学专业的学生在毕业时少有并行编程的经验。许多学院和大学提供并行计算方面的高年级选修课程,但由于大多数计算机科学专业的必修课程繁重,许多人在毕业时都没有编写过多线程或多进程程序。
似乎很明显,这种状况需要改变。虽然许多程序可以在单核处理器上获得令人满意的性能,但应该让计算机科学家意识到可以通过并行性获得潜在的巨大性能改进,并且他们应该能够在需要时利用这种潜力。
编写本书就是为了尝试解决这个问题。书中介绍了如何利用MPI、Pthreads、OpenMP和CUDA这四种广泛使用的并行编程API编写并行程序,目标读者是需要编写并行程序的学生和专业人士。阅读本书的先决条件很简单:学习过大学水平的数学课程和具备用C语言编写串行程序的能力。
先决条件是最基础的,因为我们认为学生应该尽早开始并行系统编程。在旧金山大学,计算机科学专业的学生在大一第一学期修读“计算机科学导论I”课程(这是大多数专业都会开设的课程)后,就可以立即基于本书学习并行编程课程,从而达到专业的要求。根据我们的经验,学生确实没有理由把学习编写并行程序推迟到大三或大四。相反,这门课程很受欢迎,学生发现在学习了这门课程之后,在其他课程中使用并行程序要容易得多。
如果大学二年级新生可以通过上课来学习编写并行程序,那么积极进取的计算机专业人士也应该能够通过自学来学习编写并行程序。我们希望这本书能成为他们的有用资源。
第2版重要更新
自本书第1版出版以来,已经过去了近十年。在这期间,并行编程的世界发生了很多变化,但令人惊讶的是,也有很多地方保持不变。我们编写第2版的目的是保留第1版中仍然普遍有用的材料,同时也在我们认为需要的地方添加新的材料。
最明显的补充是加入了关于CUDA编程的新的一章。第1版出版时,CUDA刚刚兴起。我们已经很清楚地看到,GPU在高性能计算中的应用将变得非常广泛,但在当时,GPGPU对于经验相对较少的程序员来说并不容易掌握。在过去的十年中,这种情况显然已经改变了。当然,CUDA不是一个标准,功能的增加、修改和删除都是非常迅速的。因此,使用CUDA的作者必须提出一个比标准(如MPI、Pthreads或OpenMP)变化更快的主题。尽管这样,我们希望本书对CUDA的介绍能在一段时间内持续有用。另一个很大的变化是Matthew Malensek作为合作者加入了我们。虽然Matthew是我们在旧金山大学的一位新同事,但他在并行计算的教学和应用方面都有丰富的经验。他在改善第2版的内容方面做出了很大的贡献。
关于本书
正如我们前面所指出的,本书的主要目的是向计算机科学背景有限、以前没有并行经验的读者讲授MPI、Pthreads、OpenMP和CUDA的并行编程。我们还想让这本书尽可能灵活,以便那些对学一两个API没有兴趣的读者仍然可以不费吹灰之力地阅读其余材料。因此,关于四个API的章节在很大程度上是相互独立的:可以按任何顺序阅读,其中一两章也可以省略。然而这种独立性也有一些代价:有必要重复这些章节中的一些材料。当然,重复的材料可以简单地浏览或跳过。
没有并行计算经验的读者应该先阅读第1章。该章试图提供相对非技术性的解释,说明为什么并行系统会在计算机领域占据主导地位。这一章还提供了关于并行系统和并行编程的简短介绍。
第2章介绍计算机硬件和软件的技术背景。第3章到第6章分别对MPI、Pthreads、OpenMP和CUDA进行介绍,且内容相对独立。第7章使用这四个API中的每一个开发两个不同的并行程序。最后,第8章提供了一些关于并行计算的补充信息。
我们使用C语言来开发程序,因为所有四个API都有C语言接口,而且,C语言是一种相对容易学习的语言—特别是对于C++和Java程序员来说,因为他们已经熟悉了C语言的控制结构。
教学建议
本书源于旧金山大学的一门低年级本科课程。该课程既满足计算机科学专业的要求,也满足学习本科操作系统、体系结构和网络课程的先决条件。该课程以为期四周的C语言编程学习开始。由于大多数学生已经编写过Java程序,这部分内容主要是关于C语言中指针的使用。课程的其余部分首先介绍MPI编程,然后是Pthreads和/或OpenMP,最后是关于CUDA的材料。
我们将大部分材料安排在第1、3、4、5和6章,一小部分材料安排在第2和7章。第2章的背景知识可根据需要学习。例如,在讨论OpenMP中的缓存一致性问题之前(第5章),我们先在第2章中介绍了关于缓存的材料。
课程作业包括每周的家庭作业、五次编程作业、几次期中考试和一次期末考试。家庭作业通常涉及编写一个非常短的程序或对现有程序进行小的修改。目的是确保学生与课程作业保持同步,并让学生亲身体验课堂上介绍的知识。似乎这些作业的存在是该课程成功的主要原因之一。本书中的大多数练习都适用于这些简短的作业。
编程作业比家庭作业复杂,但我们通常会给学生大量的指导:我们经常会在作业中加入伪代码,并在课堂上讨论比较困难的部分。这种额外的指导往往是至关重要的,以免学生在作业上花费过多时间。
期中考试和期末考试的结果以及讲授操作系统的教授充满热情的报告表明,该课程在教学生如何编写并行程序方面是非常成功的。
对于更高级的并行计算课程,本书及其在线支持材料可以作为补充。因此,关于四个API的语法和语义的大部分材料可以作为课外阅读材料。
本书也可以作为基于项目的课程和计算机科学以外的需要并行计算的课程的补充。
支持材料
本书的在线配套网站为www.elsevier.com/books-and-journals/book-companion/9780128046050。
这个网站包括勘误表和我们在本书中讨论的较长程序的完整源码。为教师提供的额外材料,包括可下载的图片和书中练习的答案,可以从https://educate.elsevier.com/9780128046050
下载。
我们将非常感谢读者让我们知道他们发现的任何错误。如果你确实发现了错误,请发送电子邮件至 mmalensek@usfca.edu。
致谢
在本书的编写过程中,我们得到了许多人的帮助。我们要感谢第2版的审稿人Steven Frankel(以色列理工学院)和Il-Hyung Cho(萨吉诺谷州立大学),他们阅读并评论了CUDA章节的初稿。感谢那些阅读并评论了本书初稿的审稿人:Fikret Ercal(密苏里科技大学)、Dan Harvey(南俄勒冈大学)、Joel Hollingsworth(伊隆大学)、Jens Mache(路易斯和克拉克大学)、Don McLaughlin(西弗吉尼亚大学)、Manish Parashar(罗格斯大学)、Charlie Peck(厄勒姆学院)、Stephen C. Renk(北中央大学)、Rolfe Josef Sassenfeld(得克萨斯大学埃尔帕索分校)、Joseph Sloan(沃福德学院)、Michela Taufer(特拉华大学)、Pearl Wang(乔治梅森大学)、Bob Weems(得克萨斯大学阿灵顿分校)和Cheng-Zhong Xu(韦恩州立大学)。我们也深深感谢以下人士对本书各章的评论:Duncan Buell(南卡罗来纳大学)、Matthias Gobbert(马里兰大学巴尔的摩郡分校)、Krishna Kavi(北得克萨斯大学)、Hong Lin(休斯敦大学)、Kathy Liszka(阿克伦大学)、Leigh Little(纽约州立大学)、Xinlian Liu(胡德学院)、Henry Tufo(科罗拉多大学博尔得分校)、Andrew Sloss(ARM顾问工程师)和Gengbin Zheng(伊利诺伊大
学)。他们的意见和建议使本书内容得到了不可估量的改进。当然,我们对其余的错误和遗漏负全责。
幻灯片和第1版的答案手册分别由Kathy Liszka和Jinyoung Choi准备,感谢他们两位。
爱思唯尔公司的工作人员在整个项目中给予我们很大的帮助。Nate McFadden协助完成了文本的开发。Todd Green和Steve Merken是本书的组稿编辑。Meghan Andress是内容开发经理,Rukmani Krishnan是制作编辑,Victoria Pearson是设计师。他们的工作非常出色,我们对他们所有人都非常感激。
南加州大学计算机科学和数学系的同事在编写本书的过程中给予我们极大的帮助。Peter特别感谢Gregory Benson教授,他对并行计算的理解—特别是Pthreads和信号量—是一种宝贵的资源。非常感谢我们的系统管理员Alexey Fedosov和Elias Husary,他们耐心并有效地处理了我们在为本书编写程序时出现的所有“紧急事件”。他们还做了一项了不起的工作—为我们提供了用于进行所有程序开发和测试的硬件。
如果没有Holly Cohn、John Dean和Maria Grant的鼓励和精神支持,Peter将无法完成这本书,非常感谢他们的帮助。特别感谢Holly允许我们使用她的作品《七条记号》作为
封面。
Matthew要感谢南加州大学计算机科学系的同事,以及Maya Malensek和Doyel Sadhu,感谢他们的爱和支持。最重要的是感谢Peter Pacheco,作为在他学术生涯形成期的一位导师,Peter是建议和智慧的可靠来源。
我们最大的人情债来自我们的学生。他们一如既往地告诉我们什么是易于掌握的,什么是难以理解的。他们教会了我们如何讲授并行计算,对他们所有人表示最深切的感谢。
|
|