描述
开 本: 16开纸 张: 胶版纸包 装: 平装-胶订是否套装: 否国际标准书号ISBN: 9787302607373
编写可扩展的、快速、强大、节能的程序,才适合处理大量数据。使用并行编程,可将数据处理任务分布在多个CPU上完成,从而从根本上提高性能。只需要稍加学习,读者就可以创建速度和效率化的软件。
《并行计算与高性能计算》将讲述用于提高代码运行效率的技术。你将学习评估硬件架构,学会使用OpenMP和MPI等行业标准工具,将掌握用于高性能计算的数据结构和算法,并学习手持设备的节能技术。你甚至可在一组GPU上运行大规模海啸仿真程序。
主要内容 ●规划新的并行项目 ●了解CPU和GPU架构上的差异 ●找到性能不佳的内核和循环 ●使用批处理调度来管理应用程序
第Ⅰ部分 并行计算介绍
第1 章 为什么使用并行计算 3
1.1 为什么要学习并行计算 5
1.1.1 并行计算的潜在优势是什么 7
1.1.2 并行计算的注意事项 9
1.2 并行计算的基本定律 9
1.2.1 并行计算的极限:Amdahl 定律 9
1.2.2 突破并行极限:Gustafson-Barsis定律 10
1.3 并行计算如何工作 12
1.3.1 应用程序示例 13
1.3.2 当今异构并行系统的硬件模型 18
1.3.3 当今异构并行系统的应用程序模型及软件模型 21
1.4 对并行方法进行分类 24
1.5 并行策略 25
1.6 并行加速与比较加速:两种不同的衡量标准 26
1.7 你将在本书中学到哪些内容 27
1.7.1 扩展阅读 27
1.7.2 练习 28
1.8 本章小结 28
第2 章 规划并行化 29
2.1 处理新项目:准备工作 30
2.1.1 版本控制:为并行代码创建一个安全的存储库 31
2.1.2 测试套件:创建健壮、可靠的应用程序的步 32
2.1.3 查找和修复内存问题 40
2.1.4 提高代码的可移植性 41
2.2 概要分析:探测系统功能和应用程序性能之间的差距 42
2.3 计划:成功的基础 42
2.3.1 探索benchmark 和mini-apps 43
2.3.2 核心数据结构和代码模块化设计 43
2.3.3 算法:重新设计并行 44
2.4 实施 44
2.5 提交:高质量的打包过程 45
2.6 进一步探索 46
2.6.1 扩展阅读 46
2.6.2 练习 46
2.7 本章小结 46
第3 章 性能极限与分析 49
3.1 了解应用程序的潜在性能限制 49
3.2 了解硬件性能:基准测试 52
3.2.1 用于收集系统特征的工具 52
3.2.2 计算浮点运算的理论值 55
3.2.3 内存层级和理论内存带宽 55
3.2.4 带宽和浮点运算的实证测量 56
3.2.5 计算flop 和带宽之间的机器平衡 59
3.3 描述你的应用程序:分析 59
3.3.1 分析工具 60
3.3.2 处理器时钟频率和能耗的实证测量 69
3.3.3 在运行时跟踪内存 70
3.4 进一步探索 71
3.4.1 扩展阅读 71
3.4.2 练习 71
3.5 本章小结 71
第4 章 数据设计和性能模型 73
4.1 数据结构与性能:面向数据的设计 74
4.1.1 多维数组 76
4.1.2 结构数组(AoS)与数组结构(SoA) 80
4.1.3 数组结构的数组(AoSoA) 85
4.2 缓存未命中的3C:强制、容量与冲突 86
4.3 简单性能模型:案例研究 90
4.3.1 全矩阵数据表示 92
4.3.2 压缩稀疏存储表示 95
4.4 高级性能模型 98
4.5 网络消息 101
4.6 进一步探索 103
4.6.1 扩展阅读 104
4.6.2 练习 104
4.7 本章小结 104
第5 章 并行算法与模式 105
5.1 并行计算应用的算法分析 105
5.2 性能模型与算法复杂性 106
5.3 什么是并行算法 109
5.4 什么是哈希函数 110
5.5 空间哈希:一种高并行度算法 111
5.5.1 使用完美哈希进行空间网格操作 113
5.5.2 使用紧凑哈希进行空间网格操作 126
5.6 prefix sum(扫描)模式及其在并行计算中的重要性 132
5.6.1 Step-efficient 并行扫描操作 133
5.6.2 Work-efficient 并行扫描操作 134
5.6.3 用于大型数组的并行扫描操作 135
5.7 并行全局和:解决关联性问题 135
5.8 并行算法研究的未来 141
5.9 进一步探索 141
5.9.1 扩展阅读 141
5.9.2 练习 142
5.10 本章小结 142
第II 部分 CPU:并行的主力第6 章 向量化:免费的flop 145
6.1 向量及单指令多数据流(SIMD)概要 145
6.2 向量化的硬件趋势 146
6.3 向量化方法 147
6.3.1 使用优化软件库可以轻松提高性能 148
6.3.2 自动向量化:向量化加速的简单方法(大多数情况下) 148
6.3.3 通过提示来指导编译器:pragma和指令 152
6.3.4 使用向量本征库处理无法向量化的循环 157
6.3.5 大胆尝试:使用汇编代码进行向量化 162
6.4 实现更好向量化的编程风格 163
6.5 与编译器向量化相关的编译器标志 164
6.6 使用OpenMP SIMD 指令实现更好的移植性 170
6.7 进一步探索 172
6.7.1 扩展阅读 172
6.7.2 练习 172
6.8 本章小结 173
第7 章 使用OpenMP 实现并行计算 175
7.1 OpenMP 介绍 175
7.1.1 OpenMP 概念 176
7.1.2 OpenMP 简单程序示例 179
7.2 典型的OpenMP 用例:循环级OpenMP、高级OpenMP 和MPI OpenMP 183
7.2.1 使用循环级OpenMP 进行快速并行化 184
7.2.2 使用高级OpenMP 获得更好的并行度 184
7.2.3 使用MPI OpenMP 获得极限可扩展性 185
7.3 标准循环级OpenMP 示例 185
7.3.1 循环级OpenMP:向量加法示例 186
7.3.2 stream triad 示例 189
7.3.3 循环级OpenMP:stencil 示例 190
7.3.4 循环级示例的性能 191
7.3.5 使用OpenMP 线程的global sum的约减示例 192
7.3.6 循环级OpenMP 的潜在问题 193
7.4 OpenMP 中变量范围对结果准确性的重要性 193
7.5 函数级OpenMP:使整个函数实现线程并行 194
7.6 使用高级OpenMP 改进并行可伸缩性 196
7.6.1 如何实现高级OpenMP 197
7.6.2 实现高级OpenMP 的示例 199
7.7 使用OpenMP 混合线程及向量化 201
7.8 使用OpenMP 的高级示例 204
7.8.1 在x 和y 方向单独传递的stencil示例 204
7.8.2 使用OpenMP 线程实现kahan求和 208
7.8.3 通过线程实现的prefix scan算法 209
7.9 线程工具对健壮程序的重要性 210
7.9.1 使用Allinea/ARM MAP快速获得应用程序的高层概要文件 211
7.9.2 使用Intel Inspector 查找线程竞态条件 212
7.10 基于任务的支持算法示例 213
7.11 进一步探索 214
7.11.1 扩展阅读 214
7.11.2 练习 215
7.12 本章小结 215
第8 章 MPI:并行骨干 217
8.1 MPI 程序基础 217
8.1.1 为每个MPI 程序进行基本MPI函数调用 218
8.1.2 简单MPI 程序的编译器包装器 219
8.1.3 使用并行启动命令 219
8.1.4 MPI 程序的小工作示例 219
8.2 用于进程间通信的发送和接收命令 221
8.3 聚合通信:MPI 的强大组件 227
8.3.1 使用barrier 来同步计时器 228
8.3.2 使用广播处理小文件输入 228
8.3.3 使用约减从所有进程中获取单个值 230
8.3.4 使用gather 在调试打印输出中排序 233
8.3.5 使用scatter 和gather 将数据发送到工作进程 234
8.4 数据并行示例 236
8.4.1 使用stream triad 来测量节点上的带宽 236
8.4.2 二维网格中的ghost cell 交换 238
8.4.3 三维stencil 计算中的ghost cell交换 244
8.5 使用高级MPI 功能来简化代码和启用优化 245
8.5.1 使用自定义MPI 数据类型来简化代码并提升性能 245
8.5.2 MPI 中的笛卡儿拓扑 250
8.5.3 ghost cell 交换变体的性能测试 255
8.6 通过联合使用MPI 和OpenMP实现极高的可扩展性 257
8.6.1 混合MPI 和OpenMP 的优势 257
8.6.2 MPI 与OpenMP 混合示例 258
8.7 进一步探索 259
8.7.1 扩展阅读 260
8.7.2 练习 260
8.8 本章小结 261
第III 部分 GPU:加速应用程序运行
第9 章 GPU 架构及概念 265
9.1 作为加速计算平台的CPU-GPU
系统 266
9.1.1 集成GPU:商业化系统中没有被充分使用的资源 267
9.1.2 独立GPU:高性能计算的主力 267
9.2 GPU 和线程引擎 268
9.2.1 使用流多处理器(或子片)作为计算单元 270
9.2.2 作为独立处理器的处理单元 270
9.2.3 每个处理单元进行多个数据操作 270
9.2.4 计算GPU flop 的理论峰值 270
9.3 GPU 内存空间的特点 272
9.3.1 计算内存带宽的理论峰值 273
9.3.2 测量GPU stream benchmark 274
9.3.3 GPU 的Roofline 性能模型 275
9.3.4 使用mixbench 性能工具为工作负载选择GPU 276
9.4 PCI 总线:CPU 与GPU 之间的数据传输桥梁 278
9.4.1 PCI 总线的理论带宽 279
9.4.2 PCI 带宽benchmark 应用程序 281
9.5 多GPU 平台和MPI 284
9.5.1 优化网络中GPU 之间的数据移动 284
9.5.2 一种比PCI 总线性能更高的替代方案 285
9.6 GPU 加速平台的潜在收益 286
9.6.1 缩短解决问题的时间 286
9.6.2 使用GPU 降低能耗 287
9.6.3 使用GPU 降低云计算成本 292
9.7 何时使用GPU 292
9.8 进一步探索 292
9.8.1 扩展阅读 293
9.8.2 练习 293
9.9 本章小结 293
第10 章 GPU 编程模型 295
10.1 GPU 编程抽象:通用框架 296
10.1.1 大规模并行处理 296
10.1.2 无法在任务之间进行协调 297
10.1.3 GPU 并行性的术语 297
10.1.4 将数据分解成独立的工作单元:NDRange 或网格 297
10.1.5 为工作组提供大小合适的工作块 300
10.1.6 通过lockstep 执行子工作组、warp 与wavefront 300
10.1.7 工作项:操作的基本单元 301
10.1.8 SIMD 或向量硬件 301
10.2 GPU 编程模型的代码结构 302
10.2.1 “Me”编程:并行kernel的概念 302
10.2.2 线程索引:将本地tile 映射到全局中 303
10.2.3 索引集 304
10.2.4 如何在GPU 编程模型中对内存资源进行寻址 305
10.3 优化GPU 资源利用 306
10.3.1 kernel 将使用多少寄存器 307
10.3.2 利用率:提高工作组的负载率 307
10.4 约减模式需要跨工作组进行同步 309
10.5 通过队列(流)进行异步计算 310
10.6 为GPU 定制并行化应用程序的策略 311
10.6.1 场景1:三维大气环境仿真 311
10.6.2 场景2:非结构化网格应用 312
10.7 进一步探索 312
10.7.1 扩展阅读 313
10.7.2 练习 314
10.8 本章小结 314
第11 章 基于指令的GPU 编程 315
11.1 为GPU 实现应用编译指令和pragma 的过程 316
11.2 OpenACC:在GPU 上运行的简单方法 317
11.2.1 编译OpenACC 代码 319
11.2.2 OpenACC 中用于加速计算的并行计算区域 320
11.2.3 使用指令减少CPU 和GPU之间的数据移动 325
11.2.4 优化GPU kernel 329
11.2.5 stream triad 性能结果的总结 334
11.2.6 高级OpenACC 技术 335
11.3 OpenMP:加速器领域的重量级选手 337
11.3.1 编译OpenMP 代码 337
11.3.2 使用OpenMP 在GPU 上生成并行工作 339
11.3.3 使用OpenMP 创建数据区域来控制到GPU 的数据移动 342
11.3.4 为GPU 优化OpenMP 346
11.3.5 用于GPU 的高级OpenMP 350
11.4 进一步探索 353
11.4.1 扩展阅读 353
11.4.2 练习 354
11.5 本章小结 355
第12 章 GPU 语言:深入了解基础知识 357
12.1 原生GPU 编程语言的特性 358
12.2 CUDA 和HIP GPU 语言:底层性能选项 359
12.2.1 编写和构建个CUDA应用程序 360
12.2.2 CUDA 的约减kernel:事情变得复杂 367
12.2.3 Hipifying CUDA 代码 372
12.3 OpenCL:用于可移植的开源GPU 语言 375
12.3.1 编写和构建个OpenCL应用程序 376
12.3.2 OpenCL 中的约减 381
12.4 SYCL:一个成为主流的实验性C 实现 384
12.5 性能可移植性的高级语言 387
12.5.1 Kokkos:性能可移植性生态系统 387
12.5.2 RAJA 提供更具适应性的性能可移植性层 390
12.6 进一步探索 392
12.6.1 扩展阅读 392
12.6.2 练习 393
12.7 本章小结 393
第13 章 GPU 配置分析及工具 395
13.1 分析工具概要 395
13.2 如何选择合适的工作流 396
13.3 问题示例:浅水仿真 397
13.4 分析工作流的示例 400
13.4.1 运行浅水应用程序 400
13.4.2 分析CPU 代码来制定行动计划 402
13.4.3 为实施步骤添加OpenACC计算指令 403
13.4.4 添加数据移动指令 405
13.4.5 通过引导分析获取改进建议 406
13.4.6 强大的辅助开发工具:NVIDIA Nsight 工具套件 408
13.4.7 用于AMD GPU 生态系统的CodeXL 409
13.5 专注于重要指标 409
13.5.1 利用率:是否有足够的工作量 410
13.5.2 发布效率:你的warp 是否经常停滞? 410
13.5.3 获得带宽 411
13.6 使用容器和虚拟机来提供备用工作流 411
13.6.1 将Docker 容器作为解决方案 411
13.6.2 使用VirtualBox 虚拟机 413
13.7 移入云端:提供灵活和可扩展能力 415
13.8 进一步探索 415
13.8.1 扩展阅读 415
13.8.2 练习 416
13.9 本章小结 416
第Ⅳ部分 高性能计算生态系统
第14 章 关联性:与kernel 休战 419
14.1 为什么关联性很重要 420
14.2 探索架构 421
14.3 OpenMP 的线程关联 422
14.4 进程关联性与MPI 429
14.4.1 OpenMPI 的默认进程放置 429
14.4.2 进行控制:在OpenMPI 中指定进程放置的基本技术 430
14.4.3 关联性不仅仅是进程绑定:全面讨论 434
14.5 MPI OpenMP 的关联性 436
14.6 从命令行控制关联性 440
14.6.1 使用hwloc-bind 分配关联性 440
14.6.2 使用likwid-pin: likwid 工具套件中的关联工具 441
14.7 展望未来:在运行时设置和更改关联性 443
14.7.1 在可执行文件中设置关联性 443
14.7.2 在运行时更改进程关联性 445
14.8 进一步探索 447
14.8.1 扩展阅读 447
14.8.2 练习 448
14.9 本章小结 449
第15 章 批处理调度器:为混乱带来秩序 451
15.1 无管理系统所带来的混乱 452
15.2 如何顺利地在繁忙的集群中部署任务 452
15.2.1 繁忙集群中的批处理系统布局 453
15.2.2 如何合理地在繁忙的集群和HPC 站点上运行任务:HPC 中的推荐做法 453
15.3 提交个批处理脚本 454
15.4 为长时间运行的作业设定自动重启 459
15.5 在批处理脚本中指定依赖项 463
15.6 进一步探索 465
15.6.1 扩展阅读 465
15.6.2 练习 465
15.7 本章小结 466
第16 章 并行环境的文件操作 467
16.1 高性能文件系统的组成部分 467
16.2 标准文件操作:并行到串行(parallel-to-serial)接口 468
16.3 在并行环境中使用MPI
文件操作(MPI-IO) 469
16.4 HDF5 具有自我描述功能,可更好地管理数据 477
16.5 其他并行文件软件包 485
16.6 并行文件系统:硬件接口 485
16.6.1 并行文件设置 485
16.6.2 适用于所有文件系统的通用提示 489
16.6.3 特定文件系统的提示 490
16.7 进一步探索 493
16.7.1 扩展阅读 493
16.7.2 练习 494
16.8 本章小结 494
第17 章 用于编写优质代码的工具和资源 495
17.1 版本控制系统:一切从这里开始 497
17.1.1 分布式版本控制更适合全局协作 498
17.1.2 通过集中版本控制来简化操作并提高代码安全 498
17.2 用于跟踪代码性能的计时器例程 499
17.3 分析器:不去衡量就无法提升 500
17.3.1 日常使用的基于文本的分析器 501
17.3.2 用于快速识别瓶颈的高级分析器 502
17.3.3 使用中级分析器来指导应用程序开发 502
17.3.4 通过详细分析器了解硬件性能的细节信息 504
17.4 benchmark 和mini-apps:了解系统性能的窗口 504
17.4.1 使用benchmark 测量系统性能特征 504
17.4.2 通过mini-apps 提供应用程序的视角 505
17.5 为健壮的应用程序检测及修复内存错误 507
17.5.1 valgrind Memcheck:备用开源方案 507
17.5.2 使用Dr. Memory 诊断内存问题 507
17.5.3 对于要求严苛的应用程序使用商业内存检测工具 509
17.5.4 使用基于编译器的内存工具来简化操作 509
17.5.5 通过Fence-post 检查器来检测越界内存访问 510
17.5.6 GPU 应用程序所使用的内存工具 511
17.6 用于检测竞态条件的线程检查器 512
17.6.1 Intel Inspector:带有GUI 的竞态条件检测工具 512
17.6.2 Archer:一个基于文本的检测竞态条件的工具 512
17.7 Bug-busters:用于消除bug 的调试器 514
17.7.1 在HPC 站点中广泛使用的TotalView 调试器 514
17.7.2 DDT:另一种在HPC 站点广泛使用的调试器 514
17.7.3 Linux 调试器:为本地开发需求提供免费的替代方案 515
17.7.4 通过GPU 调试器消除GPU bug 515
17.8 文件操作分析 516
17.9 包管理器:你的个人系统管理员 519
17.9.1 macOS 的包管理器 519
17.9.2 Windows 包管理器 519
17.9.3 Spack 包管理器:用于高性能计算的包管理器 519
17.10 模块:加载专门的工具链 520
17.10.1 TCL modules:用于加载软件工具链的原始模块系统 522
17.10.2 Lmod:基于Lua 的替代模块实现 523
17.11 思考与练习 523
17.12 本章小结 523
附录A 参考资料 (可从配书网站下载)
附录B 习题答案 (可从配书网站下载)
探险家重要的任务之一就是为后来者画一张地图。这对我们这些在科技领域不断开拓的人来说尤其如此。我们在本书中的目标是为那些刚刚开始学习并行和高性能计算的人以及那些想要扩大知识面的人提供一个路线图。高性能计算是一个快速变化的领域,其中的语言和技术一直在变化。
出于这个原因,我们将关注长期保持稳定的基本面。对于用于CPU 和GPU 的计算机语言,我们强调跨许多语言的通用模式,以便你可以快速地为当前任务选择合适的语言。
本书的目标读者
本书适用于本科阶段高年级的并行计算课程,也可以作为从事计算工作的专业人员的文献。如果你对性能感兴趣,无论是运行时间、规模还是处理能力,本书都将为你提供改进应用程序和超越竞争对手的工具。随着处理器达到规模、热量以及功率的极限,我们不能指望下一代计算机来加快运行我们的应用程序。越来越多的高技能和知识渊博的程序员对于从当今的应用程序中获得性能至关重要。
在本书中,我们可以了解当今高性能计算硬件的关键思想。这些是为了性能而编程的基本真理。
这些主题构成了整本书的基础。
在高性能计算中,关键不在于编写代码的速度有多快,而在于代码运行的有多快。
这一想法总结了为高性能计算编写应用程序意味着什么。对于大多数其他应用程序,关注的重点是如何能够快速地完成编写应用程序的过程。如今,计算机语言的设计通常是为了提高编程速度,而不是提高代码的性能。虽然这种编程方法长期以来一直存在于高性能计算应用程序,但它还没有得到广泛的记录或描述。在第4 章中,我们将在近被称为面向数据设计的编程方法中讨论这一点。
一切都与内存有关:将多少内容加载到内存以及加载的频率。
即使你知道可用内存和内存操作几乎总是性能的瓶颈,但我们依旧倾向于花大量时间考虑浮点操作。目前大多数计算硬件对于每个内存负载能够执行50 个浮点操作,因此浮点操作已经是次要的了。在几乎每一章中,我们都使用了STREAM 基准测试,这是一个内存性能测试,用来验证我们是否从硬件和编程语言中获得了合理的性能。
如果加载一个值,则得到8 或16。
这就像买鸡蛋一样。你不可能每次只买一个。内存负载由512 位的高速缓存行完成。对于8 字节的双精度值,无论是否需要,都将加载8 个值。所以在编程过程中,让你的程序一次使用多个值而不是一个值,而且好是使用8 个连续的值,这样可以获得性能。如果代码中存在任何缺陷,并行执行时将暴露它们。
与串行运行的应用程序相比,在高性能计算中需要更多地关注代码质量。代码质量将贯穿整个并行化生命周期。使用并行化,你更有可能在程序中触发缺陷,而且还会发现调试并行程序更具挑战性,特别是在大规模使用并行的情况下。我们将在第2 章中介绍提高编程质量的方法,并在整个章节中都一直使用可以提高编程质量的工具,后,在第17 章中,我们列出了其他优秀的用于提高编程质量的工具。
这些关键主题不局限于硬件类型,对于CPU 环境和GPU 环境都同样适用。同时支持CPU 与GPU 是因为在现实中运行高性能程序往往受到物理硬件的限制,不可能所有的硬件都有GPU 环境。
本书内容的基本路线图
这本书并不要求你具备任何并行编程的知识,但希望你好是一位熟练的程序员,并且熟悉高性能编译语言,如C、C 或Fortran;同时也希望你对计算术语、操作系统基础知识和网络有一定的了解,并且能够完成其他的计算机操作,比如安装软件和完成轻量化的系统任务管理。
计算硬件的知识或许是对读者重要的要求。我们建议打开计算机,查看每个组件,并了解其物理特性。
本书由组成高性能世界的以下四部分组成。
● 第Ⅰ部分:并行计算介绍(第1~5 章)
● 第Ⅱ部分:CPU:并行的主力(第6~8 章)
● 第Ⅲ部分:GPU:加速应用程序运行(第9~13 章)
● 第Ⅳ部分:高性能计算生态系统(第14~17 章)
本书设计的主体顺序是面向处理高性能计算项目的人员。例如,对于应用程序项目,在项目开始之前,了解第2 章中介绍的软件工程主题是必要的。一旦软件工程就位,接下来就要决定数据结构和算法。然后是使用CPU 或GPU 进行实现。后,为应用程序使用并行文件系统或高性能计算系统的其他特有特性。
另一方面,我们的一些读者对获得并行编程的基本技能更感兴趣,可能想直接进入MPI 或
OpenMP 章节。今天,并行计算的技术如此丰富,所以不要止步于此。比如从可以将应用程序的速度提高一个数量级的GPU,到可以提高代码质量或指出需要优化的代码段的工具——潜在的收益仅受你的时间和专业知识的限制。
如果你将本书作为并行计算课程的教材,那么本书所提供的内容足够支撑两个学期的时间。你可将本书当作并行与高性能计算的知识集合,可根据自己的情况来选择学习的主题,并制定课程目标,比如下面列出的自定义学习目标的例子:
● 第1 章提供了并行计算的介绍。
● 第3 章讲解测量硬件和应用程序性能的方法。
● 第4.1~4.2 节描述面向数据的编程设计概念、多维数组和缓存基础知识。
● 第7 章讨论OpenMP(Open Multi-Processing)以获得节点上的并行性。
● 第8 章介绍消息传递接口(Message Passing Interface,MPI),用于实现跨多个节点的分布式并行。
● 第14.1~14.5 节介绍关联性与流程布局的概念。
● 第9 章和第10 章描述了GPU 硬件和编程模型。
● 第11.1~11.2 节主要介绍如何使用OpenACC 让应用程序在GPU 上运行。
你可以将算法、向量化、并行文件处理或更多GPU 语言等主题添加到上面的列表中,也可以删除某个主题,以便将更多时间花在其他主题上。还有一些额外的章节将吸引学生继续探索并行计算的世界。
关于代码
如果不实际编写代码并运行它,就无法学习并行计算。为此,我们在书中提供了大量的例子。
这些例子可扫描封底二维码下载。你可以下载这些示例的完整集合或单独按章节进行下载。
在这些示例代码、所涉及的软件和硬件当中不可避免地会有缺陷和错误。如果你发现了错误或不完整的内容,我们鼓励你对示例进行反馈。我们已经合并了一些来自读者的更改请求,对此我们非常感激。此外,源代码存储库是查找修正和讨论源代码的地方。
参考资料和习题答案
可扫描封底二维码下载。
软件与硬件需求
也许并行和高性能计算的挑战是所用到的广泛的硬件和软件。在过去,这些专门的系统只能在特定的环境下使用。近,硬件和软件变得更加大众化,甚至在台式机或笔记本电脑上都可以广泛使用。这是一个重大转变,可让高性能计算程序更容易开发。然而,硬件和软件环境的设置仍然是该任务中困难的部分。如果你可以访问已经配置好的并行计算集群,我们鼓励你利用它。
后,你可能希望设置自己的计算环境。这些示例在Linux 或UNIX 系统上是容易使用的,但许多情况下也可在Windows 和macOS 上运行,只是需要做一些额外更改。如果你发现某个示例不能在系统上运行,我们提供了Docker 容器模板和VirtualBox 设置脚本作为替代方案。
关于GPU 的练习,需要使用来自不同硬件制造商的GPU,包括NVIDIA、AMD Radeon 和Intel。
安装GPU 图形驱动程序仍然是设置本地运行环境遇到的困难。一些GPU 语言也可以在CPU上工作,从而允许在本地环境中为你没有的硬件开发代码。你可能还会发现在CPU 上调试更加容易,但是为了看到真实性能,你还必须安装GPU 硬件。
其他需要特殊安装的示例包括批处理系统和并行文件示例。为了更加接近真实情况,批处理系统需要在多台笔记本电脑或者工作站上进行设置。类似地,并行文件示例适合使用像Lustre 这样的专门文件系统,但其他的基本示例可在单独的笔记本电脑或工作站上运行。
关于封面插图
本书封面上的人物插图标题是M’de de brosses à Vienne,即《维也纳的刷子销售商》。该插图取自 Jacques Grasset de Saint-Sauveur(1757—1810 年)收集的各国礼服画集,名为Costumes de Différents Pays,于1797 年在法国出版。其中的每幅插图都是经手工精细绘制并上色的。Jacques Grassetde Saint-Sauveur 丰富多样的收藏生动地提醒我们,仅在200 年前,世界上的城镇和地区在文化上存在很大的差异。那时,人们彼此隔绝,说着不同的方言或语言;无论是在街上还是在乡下,只要看他们的衣着,就很容易看出他们住在哪里,从事什么职业或处于什么地位。
从那时起,我们的着装方式发生了变化,当时非常丰富的地域多样性已经消失。现在,已很难区分不同国家的居民,更不用说不同的城镇或地区了。也许我们已经用文化的多样性换取了更多样化的个人生活——当然,指的是更多样化和快节奏的技术生活。在当前这个电脑书籍同质化严重的时代,Manning 出版社用两个世纪前地区生活的丰富多样性的书籍封面来庆祝电脑行业的发明创造和首创精神,这些书被Jacques Grasset de Saint-Sauveur 的图片重新赋予了生命。
评论
还没有评论。