高性能编程艺术再次受到重视。多年以前,程序员必须对每一比特数据的情况都了如指掌(这里说的“一比特”有时就是它字面上的意思,因为一比特的数据就有可能控制前面板上的开关)。现在,计算机有足够的能力来处理日常任务。当然,总有一些领域永远没有足够的计算能力。但是,大多数程序员都可以避免编写低效的代码。这并不是一件坏事,因为程序员可以不受性能限制,专注于以其他方式改进代码。
本书首先解释为什么越来越多的程序员不得不再次关注性能和效率。这为整本书定下基调,因为它定义了我们将在后续章节中使用的方法:关于性能的知识最终必须来自测量,并且每个与性能相关的意见都必须有数据支持。
高性能编程有5个组成部分,它们也是共同决定程序性能的5个元素。
第1个元素是计算硬件,它也是我们需要深入探索的底层基础。本书从单个组件(处理器和内存)到多处理器计算系统进行了比较全面的讨论,详细阐释了内存模型、数据共享的成本,甚至无锁编程等。
第2个元素是高效使用编程语言。正是基于这一点,本书更加特定于C++(其他语言有不同的低效率特征)。
第3个元素是编译器。本书讨论了与编译器相关的提高程序性能的技巧。
第4个元素是设计。也可以说,它其实应该是排在第一位的元素:如果设计没有将性能作为其明确目标之一,那么在后期添加良好的性能几乎是不可能的。当然,本书将性能设计安排在最后,因为这是一个高级概念,它需要以我们之前讨论的所有知识为基础。
高性能编程的第5个元素就是程序员,程序员的知识和技能将决定最终结果。
为了帮助读者顺利学习,本书包含许多示例,可用于读者的实战探索和自学。高性能编程是一项艺术,对于艺术的追求永无止境。因此,本书将是读者探寻高性能编程的起 点,而不是终点。
本书读者
本书适用于从事性能关键项目开发并希望学习不同技术以提高代码性能的经验丰富的开发人员和程序员。计算机建模、算法交易、游戏、生物信息学、基于物理的模拟、计算机辅助设计、计算基因组学或计算流体动力学等领域的程序员都可以从本书中学习到各种技术,并将之应用到自己的工作领域。
虽然本书使用的是C++ 语言,但书中展示的概念可以很容易地转移或应用到其他编译语言,如C、C#、Java、Rust和Go等。
内容介绍
本书分为3篇,共12章,具体介绍如下。
第1篇“性能基础”,包括第1~5章。
第1章“性能和并发性简介”,详细阐释了我们要关心程序性能的原因,特别是为什么会出现性能低下的现象,讨论了有关程序性能的指标,因为无论执行快慢,了解影响性能的不同因素以及程序特定行为的原因都很重要。
第2章“性能测量”,其内容与测量有关。性能通常是不直观的,所有涉及效率的决策,从设计选择到优化,都应以可靠数据为指导。本章描述了不同类型的性能测量,解释了它们的不同之处以及何时使用它们,并介绍了如何在不同情况下正确测量性能。
第3章“CPU架构、资源和性能”,研究了最重要的硬件资源以及如何有效地使用它们以实现最佳性能。本章着重介绍了CPU资源和功能、使用它们的最佳方法、未充分利用CPU资源的常见原因以及如何解决这些问题。
第4章“内存架构和性能”,阐释了现代内存架构及其固有的弱点,以及对抗或至少隐藏这些弱点的方法。对于许多程序来说,性能完全取决于程序员是否利用了旨在提高内存性能的硬件特性,本章介绍了这样做的必需技能。
第5章“线程、内存和并发”,继续研究了内存系统及其对性能的影响,但本章将研究扩展到多核系统和多线程程序领域。原本就很容易成为性能瓶颈的内存,在加入并发机制时,问题会更大。虽然硬件强加的基本限制无法克服,但大多数程序的性能甚至还没有接近这些限制,因此,熟练的程序员仍有很大的空间来提高代码的效率。本章为读者提供了与此相关的必要知识和工具。
第2篇“并发的高级应用”,包括第6~8章。
第6章“并发和性能”,介绍了如何为线程安全程序开发高性能并发算法和数据结构。一方面,要充分利用并发性,必须对问题和解决方案策略有一个高层次的看法,例如,数据组织方式、工作划分以及解决方案的选择等都会对程序的性能产生重大影响。另一方面,还要看到,性能受到缓存中数据排列等低级因素的影响很大,即使是最好的设计,也可能被糟糕的实现所破坏。
第7章“并发数据结构”,解释了并发程序中数据结构的性质,以及当数据结构在多线程上下文中使用时,诸如“栈”和“队列”之类的数据结构还意味着什么。
第8章“C++中的并发”,描述了在C++ 17和C++ 20标准中添加的并发编程特性。虽然现在谈论使用这些功能以获得最佳性能的最佳实践还为时过早,但我们可以描述它们的作用以及编译器支持的当前状态。
第3篇“设计和编写高性能程序”,包括第9~12章。
第9章“高性能C++”,开始将讨论重点从硬件资源的最佳使用转移到特定编程语言的最佳应用。虽然此前我们所学的一切都可以直接应用到任何语言的任何程序中,但本章的重点是讨论C++的特性。读者将了解C++语言的哪些特性可能会导致性能问题以及如何避免这些问题。
第10章“C++中的编译器优化”,讨论了编译器优化以及程序员如何帮助编译器生成更高效的代码。
第11章“未定义行为和性能”,本章有两个重点,一方面,解释了程序员在试图从他们的代码中榨取最大性能时经常忽略的未定义行为的危险;另一方面,解释了如何利用未定义行为来提高性能以及如何正确指定和说明此类情况。总的来说,与通常的“任何事情都可能发生”相比,本章提供了一种比较常见但更相关的方式来理解未定义行为的问题。
第12章“性能设计”,回顾了本书中介绍过的所有与性能相关的因素和特性,并探讨了我们获得的知识和理解如何影响我们在开发新软件系统或重新设计软件架构时做出的决策。
充分利用本书
除了与C++效率相关的章节,本书不依赖任何深奥的C++知识。本书所有示例均使用C++语言,但有关硬件性能、高效数据结构和性能设计的内容则适用于任何编程语言。要学习这些示例,读者至少需要具备C++的中级知识。
本书涉及的软硬件和操作系统需求如表P-1所示。
表P-1 本书涉及的软硬件和操作系统需求
本书涉及的软硬件 操作系统需求
C++编译器(GCC、Clang、Visual Studio等) Windows、macOS或Linux
性能分析器(VTune、Perf、GoogleProf等)
Benchmark Library(Google Benchmark)
本书每章都提到了编译和执行示例所需的附加软件(如果需要)。在大多数情况下,任何现代C++编译器都可以与本书示例一起使用,但第8章“C++中的并发”除外,因为该章需要最新版本才能完成关于协程的部分。
建议读者从本书的GitHub存储库访问代码(下文提供了链接)。这样做有助于避免与复制和粘贴代码相关的任何潜在错误。
下载示例代码文件
本书随附的代码可以在GitHub上找到,其网址如下:
https://github.com/PacktPublishing/The-Art-of-Writing-Efficient-Programs
如果代码有更新,也将在GitHub存储库中更新。
下载彩色图像
本书提供了一个PDF文件,其中包含本书中使用的屏幕截图/图表的彩色图像。可通过以下地址下载。
https://static.packt-cdn.com/downloads/9781800208117_ColorImages.pdf
本书约定
本书中使用了许多文本约定。
(1)文本中的代码字、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟URL、用户输入和Twitter句柄等示例如下。
我们还将演示另一个性能分析器的使用,即Google性能工具集(GperfTools)中的CPU性能分析器。该工具集的网址如下:
https://github.com/gperftools/gperftools
(2)有关代码块的设置如下。
std::vector
… 添加数据到v …
std::for_each(v.begin(), v.end(),[](double& x){ ++x; });
(3)任何命令行输入或输出都采用如下所示的粗体代码形式。
Main thread: 140003570591552
Coroutine started on thread: 140003570591552
Main thread done: 140003570591552
Coroutine resumed on thread: 140003570587392
Coroutine done on thread: 140003570587392
(4)术语或重要单词采用中英文对照形式,在括号内保留其英文原文,示例如下。
如果处理器有空闲的计算单元,那么为什么不能同时执行另一个线程来提高效率呢?这就是对称多线程(symmetric multi-threading,SMT)背后的想法,它也称为超线程(hyper- threading)。
(5)对于界面词汇或专有名词将保留英文原文,在括号内添加其中文译名,示例 如下。
在图2.8中,测量了CPU的cycles(周期)和instructions(指令),以及branches(分支)、branch-misses(分支未命中)、cache-references(缓存引用)和cache-misses(缓存未命中)。下一章将详细介绍这些计数器及其监视的事件。
(6)本书还使用了以下两个图标。
表示警告或重要的注意事项。
表示提示或小技巧。
****o 2023-01-01 00:34:19
不错,质量很好,价格实惠