并发
并发意味着应用程序在多个任务上取得进展——同时或至少看似同时(并发)。
如果计算机只有一个 CPU,则应用程序可能不会 同时在多个任务上取得进展,但在应用程序内部一次有多个任务在进行。为了同时在多个任务上取得进展,CPU 在执行期间会在不同任务之间切换。如下图所示:
并行执行
并行执行是指计算机具有多个 CPU 或 CPU 内核,并同时在多个任务上取得进展。但是,并行执行并不是指与并行性相同的现象 。稍后我将回到并行性。并行执行如下图所示:
并行并发执行
可以进行并行并发执行,其中线程分布在多个 CPU 中。因此,在同一个 CPU 上执行的线程是并发执行的,而在不同 CPU 上执行的线程是并行执行的。下图说明了并行并发执行。
并行性
并行性 一词意味着应用程序将其任务拆分为更小的子任务,这些子任务可以并行处理,例如同时在多个 CPU 上。因此,并行性并不指的是与并行并发执行相同的执行模型——即使它们在表面上看起来相似。
为了实现真正的并行性,您的应用程序必须运行多个线程 - 每个线程必须在单独的 CPU/CPU 内核/显卡 GPU 内核或类似内核上运行。
下图说明了一个更大的任务,该任务被分成 4 个子任务。这 4 个子任务由 4 个不同的线程执行,这些线程在 2 个不同的 CPU 上运行。这意味着,这些子任务的一部分是并发执行的(那些在同一个 CPU 上执行的),而部分是并行执行的(那些在不同的 CPU 上执行的)。
相反,如果这 4 个子任务由各自 CPU(总共 4 个 CPU)上运行的 4 个线程执行,那么任务执行将是完全并行的。然而,将一个任务分解成与可用 CPU 数量一样多的子任务并不总是那么容易。通常,更容易将一个任务分解为多个子任务,这些子任务自然适合手头的任务,然后让线程调度程序负责在可用 CPU 之间分配线程。
并发性和并行性组合
回顾一下,并发性是指单个 CPU 如何看似同时处理多个任务(AKA 并发)。
另一方面,并行性与应用程序如何并行执行单个任务有关 - 通常通过将任务拆分为可以并行完成的子任务 。
这两种执行方式可以在同一个应用程序中组合。我将在下面介绍其中一些组合。
并发,非并行
应用程序可以是并发的,但不是并行的。这意味着它看似同时(同时)在多个任务上取得进展,但应用程序在每个任务上取得进展之间切换 - 直到任务完成。在并行线程/CPU中没有真正的并行执行任务。
并行,不并发
应用程序也可以是并行的,但不是并发的。这意味着应用程序一次只能处理一个任务,并且该任务被分解为可以并行处理的子任务。但是,每个任务(+子任务)在下一个任务被拆分并并行执行之前完成。
既不并发也不并行
此外,应用程序既不能是并发的,也不能是并行的。这意味着它一次只能处理一个任务,并且该任务永远不会分解为并行执行的子任务。这可能是小型命令行应用程序的情况,其中它只有一个作业,该作业太小而无法并行化。
并发和并行
最后,应用程序还可以通过两种方式同时并发和并行:
第一个是简单的并行并发执行。如果应用程序启动多个线程,然后在多个 CPU 上执行,就会发生这种情况。
第二种方式是应用程序同时处理多个任务,并将每个任务分解为子任务以并行执行。但是,在这种情况下,并发性和并行性的一些好处可能会丢失,因为计算机中的 CPU 已经相当忙于并发性或并行性。结合它可能只会导致很小的性能提升甚至性能损失。确保在盲目采用并发并行模型之前进行分析和测量。