
1.3 什么是并行计算
并行计算,我也称之为并行编程和并行化,是一种让你的计算机同时做多件事情的方法。例如,在前面的场景中,我们的年轻程序员需要一次处理多个Web页面,否则他们可能永远都处理不完这些Web页面——因为有太多的页面了。即使每半秒处理一个页面,他们也无法在一天内处理200000个页面。为了获取和分析整个互联网的数据信息,他们需要提升自己的处理能力。并行计算使得他们具备了这种能力。
1.3.1 理解并行计算
为了理解并行编程,我们首先来讨论一下在标准的过程式编程中会发生什么。标准的过程式编程的工作流通常是这样的:
1. 一个程序开始运行。
2. 程序发出一个指令。
3. 该指令被执行。
4. 重复步骤2和步骤3。
5. 程序完成运行。
这是一种简单、直接的编程方法;但是,它限定我们一次只能执行一条指令(如图1.1所示)。在执行步骤4之前必须先完成步骤2和步骤3,而步骤4又把我们带回到步骤2和步骤3,让我们陷入同样的困境。

图1.1 过程式计算的过程包括发出指令和按顺序解析指令。
在一个标准的线性程序中,如果步骤2中的指令需要很长时间才能执行,那么我们将无法进入问题的下一个部分。想象一下,对于我们这些年轻的程序员来说,试图抓取整个互联网的网页意味着什么。他们有多少指令是“抓取网页abc.com/xyz”?可能会非常多。更重要的是,我们知道抓取一个网页(比如亚马逊的主页)不会改变其他网页(比如《纽约时报》的主页)的内容。
并行编程允许我们同时执行所有这些相似且独立的步骤。在并行编程中,我们的工作流看起来更像是这样的:
1. 一个程序开始运行。
2. 这个程序把工作分解成多个由指令和数据组成的工作块(chunk)。
3. 每个工作块独立执行。
4. 工作块执行完后被重新组装。
5. 程序完成运行。
通过这种方式进行编程,我们可以将自己从之前陷入的指令执行循环中解放出来(如图1.2所示)。现在,只要有一种处理它们的方法,就可以把工作分成我们想要的、任意数量的工作块。
这个过程对于那些想要抓取整个互联网的年轻程序员来说会更好。他们仍然需要找到一种方法以获得足够的计算资源来处理所有的块;但是每当他们获得一台新机器时,都可以让处理速度更快。事实上,即使早期的谷歌也是在数千台计算机的集群上运行的。

图1.2 并行计算过程可以将工作划分为多个块,这些块可以分别进行处理,处理完成后可以再重新组合。
1.3.2 拥有map和reduce编程风格的可扩展计算
当我们想到map和reduce的计算风格时,了解数据的大小和我们可用计算资源的容量(如图1.3所示)是很重要的。正常大小的数据允许我们使用个人计算机的资源来处理可以存储在个人计算机上的数据——我们可以依赖于基本的map和reduce编程风格和标准的Python代码。在这个领域,我们不会看到它与其他编程风格有太多的不同。
随着数据量的增长,我们到达了一个可以使用个人计算机的硬件资源处理数据,但是无法在个人计算机上存储数据的阶段。此时,如果我们愿意,可以在一个集群中工作,但这不是必需的。在这里,map和reduce编程风格的好处开始变得明显起来。我们可以对处理较小规模数据的代码稍微进行修改,以处理这个规模级别的数据。
现在,我们介绍最后也是最大规模的一类数据。我们需要在分布式环境中处理和存储这些数据。在这里,我们可以使用分布式的计算框架,比如Hadoop和Spark。虽然我们不能使用完全相同的代码,但是可以使用较小规模数据的处理原则和模式。我们还经常需要使用云计算服务,比如AWS。

图1.3 我们可以将map和reduce编程风格想象成一个建造工程:从帮助我们组织工作的蓝图开始,到原材料的转化,再到将各个部分组装成最后的产品。
其他的大数据技术:Splunk、Elasticsearch、Pig和Hive
因为本书主要关注可扩展的工作流,所以我有意省略了那些只能用在大容量环境中的大数据工具,包括Splunk、Elasticsearch、Apache Pig和Apache Hive。后两者建立在Hadoop技术栈上,与Hadoop和Spark是天然的伙伴。如果你正在处理大量的数据,研究这些工具是非常值得的。
我们可以在图1.3中看到,根据数据的规模不同,会使用不同的工具。图1.3显示了本书中所介绍的技术如何与各种规模数据和可用计算资源相匹配。我们首先介绍可以在笔记本电脑或者个人计算机上使用的技术:Python内置的map和reduce函数以及并行计算能力。在最后两部分(第7章和以后的部分)中,我们将介绍分布式计算框架,比如Hadoop和Spark,以及如何通过Amazon Web Services EMR在云上部署这些服务。
1.3.3 何时应该使用map和reduce编程风格
map和reduce编程风格适用于任何地方,但它的特有优势在于可能会有扩展需要的领域。规模化意味着从一个小的应用程序开始,比如你可以在自己的笔记本电脑上开发一个小游戏作为自己的小项目,然后把它应用到一个更大的场景上,比如让每个人都可以在手机上玩游戏。
设想游戏中的一个环节:提高AI(人工智能)的能力。假设我们有一个所有玩家都要与之对抗的AI对手,我们希望AI的能力每1000场比赛能够提高一些。首先,需要能够在一台机器上更新AI。毕竟,我们只有1000场比赛,处理它们很简单。即使玩家的数量增加了,我们也只需要每隔几个小时进行一次改进。但是,如果游戏足够流行,那么我们最终必须用几台机器来工作;因为它们需要处理更大的信息量(在比赛历史记录中会有更多比赛),需要用更快的速度来处理(因为比赛的速度会更快)。对于map和reduce编程风格来说,这是一个非常适合的应用程序,因为我们可以很容易地修改代码使之并行化,从而能够将对AI能力的提升扩展到任意数量的用户。