并行编程和并行编程有什么区别?我问谷歌,但没有找到任何可以帮助我理解这种差异的东西。您能给我两个例子吗?

现在我找到了以下解释:http://www.linux-mag.com/id/7411-但是“并发性是程序的属性” vs“并行执行是机器的属性”对我来说还不够-仍然我不能说什么是什么。

评论

并行与并行的可能重复-有什么区别?

#1 楼

如果您使用线程(并行编程)编程,则不一定要这样执行(并行执行),因为这取决于计算机是否可以处理多个线程。这是一个直观的示例。非线程计算机上的线程:

        --  --  --
     /              \
>---- --  --  --  -- ---->>


线程计算机上的线程:

     ------
    /      \
>-------------->>


破折号代表执行的代码。如您所见,它们既拆分又分别执行,但是线程机可以一次执行几个单独的部分。

评论


并行执行和并行编程不是一回事。乔恩·哈罗普(Jon Harrop)的答案是正确的。但是问题似乎使并行执行和并行编程变得混乱。

–布莱布莱德
11年8月20日在21:52

并行执行线程的能力不仅仅取决于机器。例如,由于对垃圾收集器的全局锁定,OCaml(和Python?)可以同时执行线程,但不能并行执行线程。

– J D
2011年8月22日在8:48

根据该博客的介绍,并行编程不是并发编程的子集。您的回答没有考虑到这一点,您对此说法有何看法?

–凯文
11-10-12在11:31

@凯文:我认为“更笼统”的意思是超集。我同意这是错误的。

– J D
2012年1月7日在16:44

此答案有助于可视化并发执行与并行执行之间的区别,但不适用于发帖人最初的编程问题。

– Reorx
2015年11月11日在6:42



#2 楼

并发编程考虑的操作似乎是重叠的,并且主要涉及由于不确定性控制流而引起的复杂性。与并发程序相关的定量成本通常既是吞吐量又是延迟。并发程序通常受IO约束,但并非总是如此,例如并发垃圾收集器完全在CPU上。并发程序的教学示例是Web搜寻器。该程序启动对网页的请求,并在下载结果可用时并发接受响应,从而累积一组已被访问的页面。控制流是不确定的,因为每次运行程序时不一定都以相同的顺序接收响应。这种特性会使调试并发程序变得非常困难。某些应用程序基本上是并发的,例如Web服务器必须同时处理客户端连接。 Erlang,F#异步工作流和Scala的Akka库可能是高度并发编程的最有前途的方法。

多核编程是并行编程的一种特殊情况。并行编程涉及为了提高吞吐量的特定目标而重叠的操作。通过确定控制流可以避免并发编程的困难。通常,程序会生成并行运行的子任务集,并且父任务仅在每个子任务完成后才继续。这使得并行程序比并行程序更容易调试。并行编程的难点是针对诸如粒度和通信之类的问题进行性能优化。在多核的情况下,后者仍然是一个问题,因为与将数据从一个缓存传输到另一个缓存相关的成本很高。密集矩阵矩阵乘法是并行编程的教学示例,可以通过使用Straasen的分治法和并行处理子问题来有效解决。 Cilk可能是在多核上进行高性能并行编程的最有前途的方法,并且已被Intel的线程构建模块和Microsoft的Task Parallel库(在.NET 4中)采用。

评论


“并行编程的困难部分,例如粒度和通信。”如果并行任务需要通信,那不是使它们并行吗?

–贾斯汀·凯斯(Justin M. Keyes)
13年2月3日,0:35

“如果并行任务需要通信,那不是使它们并行吗?”。哇,好问题!不一定,不。超级计算机通常使用批量并行操作进行编程,然后进行数据的全局重新分配和更多批量并行性。因此,存在并行性和通信性,但是没有真正的并发性。在这种情况下,我更多地考虑了多核并行性,其中通信意味着缓存的复杂性,例如高速缓存一致性所需的通信。尽管这是并发的,但它也不是直接可见的。

– J D
13年2月3日,在1:25

@BoppityBop仅仅因为我可以在绘画中说出他在小说中所说的话,并不能使我的答案变得正确。对于那些实际上不知道答案的人来说,阅读起来更容易。我想这是来到这里的重点。您可以用本文所用的语言来写书,但这对大多数读者来说绝对是轻描淡写的,因为如果您已经知道jon所写内容的一半,那么您可能不会用谷歌搜索这个问题。

– Tor Valamo
2014年4月4日在21:20

这张图片对我来说非常有帮助,对这个话题来说是个新手,@ JonHarrop的描述对我很有用,即使是技术性的语言,他们也喜欢正确的语言。这两个答案有助于我更全面地理解。我们都赢了! (尽管我很欣赏并行执行与并行编程之间的区别)

– Sammaron
2014-10-9 18:30



“ Erlang也许是最有前途的即将到来的语言……”。有趣的单词选择,因为Erlang已有30多年的历史,并于1998年开源。

– steinar
16年4月22日在12:17

#3 楼

https://joearms.github.io/published/2013-04-05-concurrent-and-parallel-programming.html

并发=两个队列和一个咖啡机。

平行=两个队列和两个咖啡机。



评论


错误和误导。并发=允许一个或多个队列(不确定的组成)。并行=如果不为空,则有多个队列使任何一个队列比原始队列短(渐近效率)。

– FrankHB
18年2月2日在2:30

并发代码需要两个或更多处理器(或“咖啡机”)。因此,这个答案本质上是错误的。

–杰弗里·安德森(Geoffrey Anderson)
19年1月1日,0:23



@GeoffreyAnderson不,不是。例如,线程和进程在单个核心计算机上同时执行。

– J D
19年1月3日在21:42

@FrankHB-请查看stackoverflow.com/a/57223044/1406510,并查看源链接-在Oracle站点上-没错,但我们的理解可以。所以是时候重新考虑了。看完之后我确实改变了看法。

– Nananosoft
19年7月26日在15:32

@GeoffreyAnderson-请查看stackoverflow.com/a/57223044/1406510。它包含来自oracle的链接,并清楚说明了什么。因此需要与之保持一致。

– Nananosoft
19年7月26日在15:34

#4 楼

将原始问题解释为并行/并行计算而不是编程。

在并行计算中,两个计算都彼此独立地进行。第二个计算不必等到第一个计算完成就可以进行。但是,它没有说明如何实现此目标的机制。在单核设置中,需要在线程之间挂起和交替(也称为抢先式多线程)。

在并行计算中,两个计算同时进行-实际上是在同一时间。

来自文章的图像:“ Node.js中的并行vs并行”



#5 楼

在处理器视图中,可以用此图片描述



在处理器视图中,可以用此图片描述

#6 楼

我相信并发编程是指多线程编程,它是让您的程序从硬件详细信息中抽象出运行多个线程的方法。例如,您可以并行执行某些算法的两个分支,以期比起先检查第一个然后再检查第二个分支的结果更快(平均)达到结果。

评论


换句话说,并行执行两件事可以使它们完成的速度快两倍。如果同时执行两个操作,则可能需要花费与先执行相同的时间,然后再执行另一个操作,如果在执行第一个操作和第二个操作之间只有一个CPU时间片来回切换,等等。

–user189169
09年12月13日在22:24

#7 楼

我在一些博客中找到了此内容。认为它是有用和相关的。

并发和并行性不是一回事。如果两个任务T1和T2的执行顺序没有预先确定,则两个任务T1和T2是并发的,

T1可以在T2之前执行并完成,在T1之前,
T1和T2可以在同一时间(并行性)同时执行,
T1和T2可以交替执行,
...
如果两个并发操作系统将线程调度为在一个单核非SMT非CMP处理器上运行,您可能会获得并发性,但不能并行。在多核,多处理器或分布式系统上可能实现并行化。 />来源:https://blogs.oracle.com/yuanlin/entry/concurrency_vs_parallelism_concurrent_programming

#8 楼

它们是两个短语,从(非常轻微)不同的角度描述同一件事。并行编程从硬件的角度描述了这种情况-至少有两个处理器(可能在单个物理包中)并行处理问题。并发编程从软件的角度描述了更多东西-可能在同一时间(并发)完全同时发生两个或多个动作。当真正不存在时划清界限。现实情况是,他们试图绘制的分界线数十年来一直模糊且模糊,并且随着时间的推移变得越来越模糊。一段时间以来,大多数计算机只有一个CPU。当您在单个CPU上执行多个进程(或线程)时,CPU一次实际上仅从这些线程之一执行一条指令。并发的外观是一种错觉-CPU在不同线程之间执行指令之间的切换足够快,以至于让人感觉到(不到100毫秒左右的瞬间瞬间),就好像它正在一次做很多事情。 />
与之明显的对比是一台具有多个CPU的计算机,或者一台具有多个内核的CPU,因此该计算机正好同时执行来自多个线程和/或进程的指令;执行一个代码对另一个执行代码不会/不起作用。

现在的问题是:如此清晰的区分几乎从未存在过。计算机设计师实际上是相当聪明的,所以他们很久以前就注意到(例如)当您需要从磁盘等I / O设备读取某些数据时,花了很长时间(就CPU周期而言)完。他们没有让CPU闲置,而是想出了各种方法让一个进程/线程发出I / O请求,并让其他进程/线程的代码在I / O请求完成时在CPU上执行。 br />
因此,早在多核CPU成为规范之前,我们就有多个线程并行执行的操作。

这只是冰山一角。几十年前,计算机也开始提供另一个级别的并行性。再次,作为非常聪明的人,计算机设计师注意到,在很多情况下,他们的指令不会互相影响,因此可以从同一流中同时执行多个指令。早已广为人知的一个例子是Control Data6600。这是(在相当大的程度上)1964年推出时地球上最快的计算机-至今仍使用许多相同的基本体系结构。它跟踪每条指令使用的资源,并具有一组执行单元,一旦它们依赖的资源可用,它们就会执行指令,这与最新的Intel / AMD处理器的设计非常相似。

但是(正如商业广告过去所说的)​​等等-并非全部。还有另一个设计元素,进一步增加了混乱。它被赋予了许多不同的名称(例如“ Hyperthreading”,“ SMT”,“ CMP”),但它们都引用相同的基本思想:一个CPU可以同时使用多个资源的组合执行多个线程每个线程和线程之间共享的一些资源是独立的。在典型情况下,这与上面概述的指令级并行性结合在一起。为此,我们有两组(或更多组)体系结构寄存器。然后,我们有一组执行单元,可以在必要的资源可用时立即执行指令。这些通常可以很好地结合在一起,因为来自不同流的指令实际上几乎不依赖于相同的资源。

然后,我们当然可以使用具有多核的现代系统。这里的事情很明显,对吧?我们有N个(目前介于2到256个左右之间)单独的内核,它们都可以同时执行指令,因此我们拥有真正的并行性的明确案例-在一个进程/线程中执行指令不会不会影响另一条指令的执行。

,有点。即使在这里,我们也有一些独立的资源(寄存器,执行单元,至少一个缓存级别)和一些共享资源(通常至少是最低缓存级别,并且肯定还有内存控制器和内存带宽)。

总结一下:人们喜欢在共享资源和独立资源之间进行对比的简单场景实际上在现实生活中从未发生过。在共享所有资源的情况下,我们最终会遇到类似于MS-DOS的情况,在该环境中,我们一次只能运行一个程序,并且必须停止运行一个程序才能完全运行另一个程序。使用完全独立的资源,我们有N台运行MS-DOS的计算机(甚至没有网络来连接它们),根本无法共享它们之间的任何内容(因为即使我们可以共享文件,那也就是共享资源,违反了什么都不共享的基本前提。)

每个有趣的案例都涉及独立资源和共享资源的某种组合。每台相当现代的计算机(以及很多不是现代的计算机)至少都具有同时执行至少一些独立操作的能力,并且几乎任何比MS-DOS更复杂的事物都至少利用了这一点一定程度上。

人们喜欢画的“并发”和“平行”之间的漂亮,清晰的划分是不存在的,而且几乎从来没有。人们喜欢归类为“并发”的内容通常仍然涉及至少一种并且通常是更多不同类型的并行执行。他们喜欢归类为“并行”的东西通常涉及共享资源,(例如)一个进程在使用两者之间共享的资源时阻止了另一个进程的执行。

人们试图在“ “并行”和“并发”生活在实际上根本不存在的计算机中。

#9 楼



Concurrent programming通常是指我们定义的任务可以按任何顺序发生的环境。一个
任务可以在另一个任务之前或之后发生,并且某些或所有任务可以同时执行。
Parallel programming特别是指在不同处理器上同时执行并发任务。因此,所有
并行编程都是并发的,但并非所有并发编程
是并行的。




来源:PThreads编程-更好的POSIX标准多处理,Buttlar,Farrell,Nichols

#10 楼


在编程中,并发是独立执行进程的组成,而并行性是(可能是相关的)计算的同时执行

-Andrew Gerrand-





并发是独立执行
计算的组成。并发是一种结构化软件的方法,特别是
,它是一种编写与现实世界良好交互的干净代码的方法。
这不是并行性。

并发不是并行性,尽管它启用了并行性。如果
您只有一个处理器,则您的程序仍可以是并发的,但
它不能是并行的。另一方面,编写良好的并发程序可以在多处理器上并行高效地运行。该属性可能很重要...
-罗伯·派克-



要理解它们之间的区别,我强烈建议您看看这个罗伯·派克(Golang创作者之一)的视频。并发不是并行性

评论


vimeo链接在这里不起作用,是youtube链接youtube.com/watch?v=cN_DpYBzKso

– Shivprasad Koirala
18年15月15日在1:15

#11 楼

当同时执行代码并且每次执行彼此独立时,将发生并行编程。因此,通常不会对共享变量等有所关注,因为这种情况不太可能发生。

但是,并发编程由共享变量等的不同进程/线程执行代码组成,因此在并发编程中,我们必须建立某种规则来决定首先执行哪个进程/线程,我们希望这样做,以便我们可以确保一致性,并且可以确定会发生什么。如果没有控制权,并且所有线程同时进行计算并将事物存储在相同的变量中,那么我们怎么知道最终会发生什么?也许一个线程比另一个线程快,也许其中一个线程甚至在执行过程中停止了运行,而另一个线程使用损坏的(尚未完全计算出的)变量继续执行不同的计算,则可能性无限。在这种情况下,我们通常使用并发编程而不是并行编程。

#12 楼

经典的任务调度可以是串行,并行或并发。


串行:必须按照已知的欺骗顺序一个接一个地执行任务,否则任务将不起作用。足够容易。

并行:任务必须同时执行,否则将无法正常工作。时间-将会导致整个系统故障。
所有任务必须具有共同的可靠时间感。下午茶时间。

并发:我们不在乎。但是,我们并不是粗心的:我们已经分析过了,没关系;因此,我们可以随时使用任何可用工具执行任何任务。快乐的日子。

通常,在已知事件中可用的调度会发生变化,我们称之为状态变化。

人们经常认为这与软件有关,但实际上它是系统早于计算机的设计概念;软件系统的使用速度有些慢,甚至很少软件语言会尝试解决该问题。如果您感兴趣,可以尝试查找晶片机语言occam。

简洁地说,系统设计可解决以下问题:操作或算法)
名词-您要做什么(数据或接口)
何时-初始化,调度,状态更改
方法-串行,并行,并发
-一旦知道事情发生的时间,就可以说是在哪里发生的,而不是之前。
为什么-这是这样做的方法吗?还有其他方法,更重要的是,还有更好的方法吗?

祝你好运。

评论


我到处都看到帽子

– Bruno Penteado
2014年12月18日19:51

这个答案比并发和并行性这两个主题复杂得多。

–凯·塞格伦(Kai Sellgren)
2015年10月3日,11:14

#13 楼

我了解到的区别是:

1)并发-使用共享资源串联运行
2)并行-使用不同资源并排运行

所以您即使它们在点(2)汇合在一起,也可能有两个彼此独立发生的事件,或者在执行的整个操作(1)中两个事物都使用相同的储备金。

#14 楼

尽管对并行和并发之间的区别还没有达成完整的共识,但许多作者还是有以下区别:是一个程序,它可以随时执行多个任务。
在并行计算中,程序是一个程序,其中多个任务紧密协作以解决问题。

所以并行程序是并发的,但即使是在多内核操作系统中运行,例如多任务操作系统的程序也可以并行运行,因为可以随时执行多个任务。
来源:Peter Pacheco对并行编程的介绍

#15 楼

并发和并行性源

在单个处理器上的多线程进程中,处理器可以在线程之间切换执行资源,从而导致并发执行。

在同一处理器中的同一多线程进程中在共享内存多处理器环境中,进程中的每个线程可以同时在单独的处理器上运行,从而导致并行执行。

当进程的线程数少于或等于处理器数时,线程支持系统与操作环境相结合,确保每个线程在不同的处理器上运行。

例如,在具有相同数量的线程和处理器的矩阵乘法中,每个线程(和每个处理器) )计算结果的一行。

评论


该资源仅显示了实现的一种特殊情况-一种特殊形式的多线程。是的,它甚至没有涵盖多线程的整个故事,例如M:N用户空间线程模型和线程调度的作用。就系统体系结构(OS,VM,启用HT的CPU等)和/或编程接口而言,线程只是实现的一种特殊方式。在现代CPU的实现中,确实存在更多的指令级并行性,它不公开任何编程接口,也与线程无关。

– FrankHB
19年7月26日在16:21



@FrankHB:如果您可以共享有关您内容的任何真实链接,我将不胜感激。我真的很想探索是否还有更多。我目前的理解很简单-在具有给定线程调度机制的给定任何OS体系结构上运行多线程应用程序,这是并行的还是并发的?即使给定了M:N用户空间-如何确定RUN是并行还是并发?

– Nananosoft
19年7月31日在18:16

我已经写了一个答案来讨论不同抽象中的问题。

– FrankHB
19年8月1日在8:35

与基本抽象相比,运行多线程应用程序实际上非常复杂,因为“运行”是适合许多抽象的通用操作。在基本抽象上,实现中的线程模型(通常是用于编程应用程序的语言规范和语言运行时实现)必须补充了许多细节。

– FrankHB
19年8月1日在8:36

#16 楼

我会尝试以我自己的方式来解释它,它可能不是计算机术语,但它为您提供了总体思路。修剪草坪等,我们也有3个人(线程)A,B,C来完成它们/>
A --> cleaning dishes
B --> taking out trash 
C --> mowing the lawn 


这里,任务的顺序是不确定的,响应取决于工作量

并行:
如果要提高吞吐量,我们可以将多个人分配给一个任务,例如,我们分配两个人来清洗碗碟,A用肥皂给碗碟洗碗,B洗碗碟,这可能会提高生产率。
A --> soaping the dishes
B --> washing the dishes


等等

希望有个好主意!现在转到其他答案中解释的技术术语;)

#17 楼

不同的人在许多不同的特定情况下谈论不同类型的并发和并行性,因此需要一些抽象来掩盖它们的共同性质。

基本的抽象是在计算机科学中完成的,其中并发和并行性都是归因于程序的属性。在这里,程序是对计算的形式化描述。这样的程序不需要使用任何特定于实现的特定语言或编码。 API / ABI / ISA / OS的存在与这种抽象级别无关。当然,将需要更详细的特定于实现的知识(例如线程模型)来进行具体的编程工作,基本抽象背后的精神没有改变。和并行性可以共存于许多不同的抽象中。

有关一般区别,请参见并发v并行性基本视图的相关答案。 (也有一些链接包含一些其他资源。)并行编程和并行编程是在某些具有可编程性的系统上实现此类一般属性的技术。这些系统通常是编程语言及其实现。

编程语言可以通过内置语义规则公开预期的属性。在大多数情况下,此类规则会指定特定语言结构(例如表达式)的评估结果,从而使计算有效地并发或并行进行。 (更具体地说,评估所隐含的计算效果可以完美地反映这些属性。)但是,并发/并行语言语义本质上是复杂的,它们对于实际工作不是必需的(实现有效的并发/并行算法作为现实问题的解决方案)。因此,大多数传统语言都采用了一种更为保守和简单的方法:假设评估的语义是完全顺序和串行的,然后提供可选的原语以允许某些计算是并发和并行的。这些原语可以是该语言支持的关键字或过程结构(“功能”)。它们是基于与托管环境(OS,或“裸机”硬件接口)的交互来实现的,托管环境通常相对于该语言是不透明的(无法使用该语言来移植)。因此,在程序员所看到的这种特殊的高级抽象中,除了这些“魔术”原语和依赖于这些原语的程序之外,并发/并行是什么?如果并发/并行性属性不那么受关注,程序员可以享受较少的易于出错的编程经验。尽管基元在最高级的抽象中将复杂物抽象掉了,但实现仍具有语言功能未暴露的额外复杂性。因此,需要一些中级抽象。一个典型的例子是线程。线程允许语言实现(运行时)支持一个或多个执行线程(或简称为线程;有时也称为进程,它不一定是操作系统中计划的任务的概念)。线程通常是由运行时抢先调度的,因此线程无需了解其他线程。因此,只要不共享任何线程(关键资源),线程就很自然地实现并行化:只需分解不同线程中的计算,一旦基础实现允许执行过程中计算资源的重叠,它就会起作用。线程还受共享资源的并发访问的约束:仅以任何顺序访问资源都满足算法所需的最小约束,并且实现将最终确定何时访问。在这种情况下,可能需要执行一些同步操作。一些语言将线程和同步操作视为高级抽象的一部分,并将它们公开为原语,而其他一些语言则仅鼓励使用相对高级的原语(例如Future / Promises)。

在特定于语言的线程级别下,底层托管环境(通常是OS)进行多任务处理。操作系统级别的抢占式多任务用于实现(抢占式)多线程。在某些环境(如Windows NT)中,基本计划单元(任务)也是“线程”。为了通过上述线程的用户空间实现区分它们,它们称为内核线程,其中“内核”是指操作系统的内核(但是,严格来说,对于Windows NT而言并不完全;“真正的”内核是NT行政人员)。内核线程并不总是1:1映射到用户空间线程,尽管1:1映射通常会减少大多数映射开销。由于内核线程是创建/销毁/通信的重量级(涉及系统调用),因此在用户空间中没有非1:1的绿色线程可以以映射开销为代价克服开销问题。映射的选择取决于高级抽象中期望的编程范例。例如,当预期要同时执行大量用户空间线程时(例如Erlang),1:1映射永远是不可行的。处理器。这通常是程序员最底层的公共接口。在此级别下,可能存在SMT。这是一种由硬件实现的低级多线程的形式,但可以说,尽管有些通常只能由处理器制造商访问,但仍可以进行一些编程。请注意,硬件设计显然反映了并行性,但是也有并发调度机制可以使内部硬件资源得到有效利用。

在上面提到的每个“线程”级别中,并发性和并行性都涉及到。尽管编程接口差异很大,但它们都受一开始基本抽象所揭示的属性的影响。

#18 楼

只是分享一个有助于突出区别的示例:并行编程:说您要实现合并排序算法。每次将问题分为两个子问题时,都可以有两个线程来解决。但是,为了执行合并步骤,您必须等待这两个线程完成,因为合并需要两个子解决方案。此“强制等待”使它成为并行程序。

并发程序:假设您要压缩n个文本文件并为每个文本文件生成一个压缩文件。您可以有2个(最多n个)线程,每个线程都处理压缩文件的子集。每个线程完成后,就完成了,不必等待或执行其他任何操作。因此,由于按照“任意顺序”以交错方式执行不同的任务,因此该程序是并发的,而不是并行的。 ,但并非相反。