如何阐明异步编程和并行编程之间的区别?


138

许多平台都将异步和并行性作为提高响应能力的手段。我通常了解这种差异,但经常发现我和其他人都难以阐明。

我是一个工作日的程序员,经常使用异步和回调。并行感让人感到异国情调。

但是我觉得它们很容易混淆,特别是在语言设计级别。很想清楚地描述它们之间的关系(或不存在关系),以及最适合应用它们的程序类别。


我写了一篇博客文章异步和并行编程的关系- anat-async.blogspot.com/2018/08/...
阿列克谢·凯戈罗多瓦


6
并行是事物同时发生的时候。异步是指您不必费心等待动作继续执行。您只需入睡,然后在稍后的某个时间出现结果,按铃,您醒来并从那里继续。异步执行只能在一个线程中完美地串行发生。(这几乎就是javascript的功能)
Thanasis Ioannidis

Answers:


87

当您异步运行某些内容时,这意味着它是非阻塞的,无需等待它完成并继续进行其他操作即可执行它。并行是指同时并行运行多个事物。当您可以将任务分解为独立的工作时,并行处理效果很好。

以3D动画的渲染帧为例。渲染动画需要很长时间,因此,如果要从动画编辑软件中启动该渲染,则应确保它是异步运行的,因此它不会锁定UI,并且您可以继续做其他事情。现在,该动画的每个帧也可以视为一个单独的任务。如果我们有多个CPU /核心或多个计算机,则可以并行渲染多个帧以加快整体工作量。


让我看看我是否明白这一点。呈现不同帧的并行任务应分散在多个CPU /内核中。这与任务完成的时间或该任务是否阻止其他任务无关。这只是意味着一堆CPU将一起执行并使结果可用,就好像它在一个超快速CPU上运行一样。对?

1
“渲染动画需要很长时间,因此,如果要从动画编辑软件中启动该渲染,请确保(...)”。什么?

对于3D动画部分:首先,您永远不要运行带有在CPU上生成帧的3D图形程序-任何理智的人都会立即建议使用GPU。其次,如果我们这样做(强烈建议不要这样做),我们将使用计时器来测量可以渲染多少帧,否则我们最终可能会建立一堆未完成的渲染调用任务。但是您的观点对于大多数基于每个用户输入事件进行渲染的2D渲染应用程序是完全正确的。
ワイきんぐ

1
异步和非阻塞是不同的范例。
罗恩侯爵,

72

我相信主要区别在于并发并行

异步回调通常是表达并发性的一种方式(工具或机制),即一组可能互相交谈并共享资源的实体。在异步或回调通信的情况下是隐式的,而资源共享是可选的(请考虑在远程计算机上计算结果的RMI)。正确地指出,这样做通常是考虑到响应能力。不要等待长时间的延迟事件。

并行编程通常以吞吐量为主要目标,而等待时间(即单个元素的完成时间)可能比等效的顺序程序更糟糕。

为了更好地理解并发和并行性之间的区别,我将引用Daniele Varacca的并发概率模型,模型为并发理论提供了很好的注释:

当计算模型能够将系统表示为可能由相互独立的独立自主组件组成时,它就是并发模型。并发的概念不应与并行性的概念相混淆。并行计算通常涉及一个中央控制,该中央控制在多个处理器之间分配工作。同时,我们强调组件的独立性以及它们相互通信的事实。平行主义就像古埃及,法老王决定,奴隶在这里工作。并发就像现代的意大利一样,每个人都在做自己想做的事,所有人都使用手机。

总之,并行编程在某种程度上是并发的特殊情况,在这种情况下,单独的实体进行协作以获得高性能和吞吐量(通常)。

异步和回调只是允许程序员表达并发性的一种机制。考虑到众所周知的并行编程设计模式(例如master / worker或map / reduce)是由使用此类低级机制(异步)来实现更复杂的集中式交互的框架实现的。


37

本文对此进行了很好的解释:http : //urda.cc/blog/2010/10/04/asynchronous-versus-parallel-programming

它具有关于异步编程的功能:

异步调用用于防止应用程序内的“阻塞”。[Such a]调用将在一个已经存在的线程(例如I / O线程)中派生出来,并在可能的情况下执行其任务。

关于并行编程:

在并行编程中,您仍然要分拆工作或任务,但主要区别在于您为每个工作分块增加了新线程

总结:

异步调用将使用系统已经使用的线程,并行编程则要求开发人员中断所需的工作,启动和拆卸线程


3
本文>这里的所有答案(当然只有这一个!)
FellyTone84 2014年

1
感谢您的链接。所以... 通常,从UI到服务器(或从客户端到Web服务)通信时,请使用异步调用。在服务器或Web服务端以及您的业务层中使用并行线程。
goku_da_master 2015年

18

我的基本理解是:

异步编程解决了在执行其他任何操作之前要等待昂贵的操作完成的问题。如果在等待操作完成时可以完成其他工作,那将是一件好事。示例:在运行时保持UI运行,并从Web服务中检索更多数据。

并行编程是相关的,但与将大型任务分解为可以同时计算的较小块有关。然后可以合并较小块的结果以产生总体结果。示例:光线跟踪,其中各个像素的颜色基本上是独立的。

它可能比这更复杂,但是我认为这是基本区别。


这个说法很好,但这是完全错误的。像异步一样,并行性还允许控制流继续进行而无需等待动作完成。主要区别在于并行性取决于硬件。
serkan '16

13

我倾向于想到这些术语的区别:

异步:完成后,离开并执行此任务,然后告诉我并带来结果。同时我将继续处理其他事情。

并行:我希望您执行此任务。如果这样更容易,请一些人帮助。不过,这很紧急,因此我将在这里等到您返回结果。在你回来之前,我别无选择。

当然,异步任务可能会利用并行性,但是区别(至少在我看来是)是在执行操作时是否继续进行其他操作,或者是否完全停止所有操作直到结果出现。


13

异步:通过做这个自己在其他地方,并通知我,当你完成(回调)。到那时我可以继续做我的事情。

在此处输入图片说明

parallel:根据需要雇用尽可能多的人(线程),然后将工作拆分给他们,以便更快地完成工作,并在完成时通知我(回调)。到那时我可能会继续做我的其他事情。

在此处输入图片说明

主要区别在于并行性主要取决于硬件。


11

这是执行顺序的问题。

如果A与B异步,那么我无法预先预测A的子部分相对于B的子部分何时会发生。

如果A与B平行,则A中的事物与B中的事物同时发生。但是,执行顺序仍然可以定义。

也许困难在于异步这个词是模棱两可的。

当我告诉我的管家去商店买更多的葡萄酒和奶酪时,我执行了一个异步任务,然后忘了他,继续写我的小说,直到他再次敲开书房。并行在这里发生,但是我和男管家从事根本不同的任务,属于不同的社会阶层,因此我们在这里不使用该标签。

当每个女佣正在清洗不同的窗户时,我的女佣团队正在并行工作。

我的赛车支持团队是异步并行的,因为每个团队都在不同的轮胎上工作,他们在工作时不需要相互交流或管理共享资源。

我的足球(又名足球)团队进行并行工作,因为每个球员都独立处理有关该领域的信息并在其上移动,但是它们并不是完全异步的,因为他们必须交流并响应他人的交流。

当每个演奏者阅读音乐并控制他们的乐器时,我的游行乐队也是平行的,但是它们是高度同步的:他们彼此演奏并及时进行演奏。

凸轮式加特林机枪可以认为是平行的,但一切都是100%同步的,因此好像一个进程正在向前发展。


9

为什么是异步的?

随着当今应用程序的连接越来越紧密,并且可能需要长时间运行的任务或阻塞诸如网络I / O或数据库操作之类的操作,因此隐藏这些操作的延迟非常重要,方法是在后台启动这些操作并返回到用户界面尽快。在这里异步出现了,响应能力

为什么要并行编程?

随着今天的数据集越来越大,计算越来越复杂。因此,在这种情况下,通过将工作负载划分为多个块,然后同时执行这些块,可以减少这些受CPU约束的操作的执行时间,这一点非常重要。我们可以称其为“ Parallel”。显然,它将为我们的应用程序带来高性能


5

异步 假设您是客户的联系点,并且需要响应,即需要询问时共享状态,操作复杂性,所需资源等。现在您需要完成一项耗时的操作,因此由于需要响应客户端24/7,因此无法进行此操作。因此,您将耗时的操作委派给其他人,以便您能够及时响应。这是异步的。

并行编程 假设您有一个任务,要从一个文本文件读取100行,而读取一行则需要1秒钟。因此,您将需要100秒才能读取文本文件。现在,您担心客户端必须等待100秒才能完成操作。因此,您将再创建9个克隆,并使每个克隆从文本文件中读取10行。现在读取100条线仅需10秒。因此,您具有更好的性能。

综上所述,异步编码是为了实现响应性,并行编程是为了提高性能。


4

异步:在后台运行方法或任务,而不会阻塞。可能不必在单独的线程上运行。使用上下文切换/时间安排。

并行任务:每个任务并行运行。不使用上下文切换/时间安排。


4

我来这里的时候对这两个概念相当满意,但是我对它们并不清楚。

阅读一些答案后,我认为我有一个正确而有用的比喻来描述差异。

如果您将自己的代码行视为单独但有序的扑克牌(如果我在解释老式打孔卡的工作原理,请停止我的操作),那么对于每个单独编写的程序,您将拥有唯一的纸牌堆栈(不要复制和粘贴!),以及正常运行代码和异步运行代码正常运行之间的差异取决于您是否在乎。

运行代码时,您会向OS传递一组单个操作(您的编译器或解释器将您的“更高”级别的代码插入了这些操作)以传递给处理器。使用一个处理器,一次只能执行一行代码。因此,为了实现同时运行多个进程的错觉,OS使用了一种技术,即它一次只向给定进程发送几行处理器,并根据其看到的情况在所有进程之间进行切换适合。结果是多个过程似乎同时向最终用户显示进度。

对于我们的比喻,关系是操作系统总是在将卡发送到处理器之前先对其进行洗牌。如果您的纸牌叠不依赖于另一叠纸叠,则您不会注意到当另一叠纸叠处于活动状态时,您的纸叠不再被选中。因此,如果您不在乎,那就没关系。

但是,如果您确实在意(例如,确实存在相互依赖的多个进程-或成堆的卡-相互依赖),则操作系统的改组将使您的结果搞砸。

编写异步代码需要处理执行顺序之间的依赖性,而不管该顺序最终是什么。这就是为什么使用“回调”之类的构造的原因。他们对处理器说:“接下来要做的就是告诉另一个堆栈我们做了什么”。通过使用这样的工具,可以确保其他堆栈在允许操作系统运行其更多指令之前得到通知。(“如果Ifed_back == false:send(no_operation)”-不确定这实际上是如何实现的,但是从逻辑上讲,我认为它是一致的。)

对于并行流程,区别在于您有两个互不关心的堆栈,以及两个处理它们的工人。最终,您可能需要合并两个堆栈的结果,这将是一个同步问题,但是对于执行而言,您无需再担心。

不确定是否有帮助,但是我总是发现多种解释很有帮助。另外,请注意,异步执行不限于单个计算机及其处理器。一般而言,它处理时间,或者(甚至更一般而言)处理事件的顺序。因此,如果将相关的堆栈A发送到网络节点X,并将其耦合的堆栈B发送到Y,则正确的异步代码应该能够解决这种情况,就像它在笔记本电脑上本地运行一样。


2

通常,每次只有两种方法可以完成一件以上的事情。一个是异步的,另一个是并行的

从高层来看,就像流行的服务器NGINX和著名的PythonTornado一样,它们都充分利用了异步范例,即单线程服务器可以同时为数千个客户端(某些IOloopcallback)提供服务。使用ECF(遵循异常控制)可以实现异步编程范例。因此异步有时并不能真正做到同时做,但在某些工作上,异步确实可以提高性能。

并行模式通常是指多线程和多。这样可以充分利用多核处理器,真正做到同时做事。


-1

以上所有答案的摘要

  1. 并行计算:

▪解决吞吐量问题。关于将大任务分解成较小的块

▪与机器有关(需要多台机器/内核/ CPU /处理器),例如:主从机,映射减少。

并行计算通常涉及一个中央控制,该中央控制可在多个处理器之间分配工作

  1. 异步:

▪解决了延迟问题,即在执行其他任何操作之前需要“等待”完成昂贵的操作的问题

▪与线程相关(需要多线程)

线程化(使用Thread,Runnable,Executor)是在Java中执行异步操作的一种基本方式

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.