关于语言不可知:并发编程和并行编程有什么区别?

What is the difference between concurrent programming and parallel programming?

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

现在我发现了这个解释:http://www.linux-mag.com/id/7411-但是"并发性是程序的一个属性"vs"并行执行是机器的一个属性"对我来说还不够-但是我还是说不出什么是什么。


并发编程关注似乎重叠的操作,主要关注由于不确定性控制流而产生的复杂性。与并发程序相关的定量成本通常是吞吐量和延迟。并发程序通常是IO绑定的,但并不总是,例如并发垃圾收集器完全在CPU上。并行程序的教学示例是一个网络爬虫。此程序启动网页请求,并在下载结果可用时同时接受响应,从而累积一组已访问的网页。控制流是不确定的,因为在每次运行程序时,不一定以相同的顺序接收响应。这种特性使得调试并发程序非常困难。有些应用程序基本上是并发的,例如Web服务器必须同时处理客户端连接。对于高度并发的编程来说,Erlang可能是最有前途的未来语言。

并行编程涉及为提高吞吐量的特定目标而重叠的操作。通过使控制流具有确定性,避免了并发编程的困难。通常,程序生成并行运行的子任务集,父任务仅在每个子任务完成后继续。这使得并行程序更容易调试。并行编程的难点在于对粒度和通信等问题进行性能优化。在多核环境中,后者仍然是一个问题,因为将数据从一个缓存传输到另一个缓存会带来相当大的成本。密集矩阵乘法是并行编程的一个教学实例,利用Straasen的分而治之算法,并行处理子问题,可以有效地解决这一问题。CILK可能是共享内存计算机(包括多核)上高性能并行编程最有前景的语言。


如果您的程序使用的是线程(并发编程),则不一定像这样执行(并行执行),因为这取决于机器是否可以处理多个线程。

这是一个直观的例子。非螺纹机器上的螺纹:

1
2
3
        --  --  --
     /              \
>---- --  --  --  -- ---->>

螺纹机上的螺纹:

1
2
3
     ------
    /      \
>-------------->>

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


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

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

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


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

在并行计算中,两个计算都是独立进行的。第二个计算不需要等到第一个计算完成后才能进行。然而,它并没有说明如何实现这一目标的机制。在单核设置中,需要在线程之间挂起和交替(也称为先发制人多线程)。

在并行计算中,两个计算同时进行,也就是说同时进行。这在单CPU上是不可能的,需要多核设置。

suspending and taking turns versus parallel computing

根据:"node.js中的并行与并发"。


从处理器的角度来看,它可以用这张图来描述

In the view  from a processor, It can be described by this pic

从处理器的角度来看,它可以用这张图来描述


我相信并发编程指的是多线程编程,它让程序运行多个线程,而不涉及硬件细节。

并行编程是指专门设计程序算法以利用可用的并行执行。例如,您可以并行地执行一些算法的两个分支,以期望它比您首先检查第一个分支然后检查第二个分支更快(平均)到达结果。


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

并发性和并行性是不同的。如果两个任务在时间上的执行顺序没有预先确定,则两个任务T1和T2是并发的。

T1可在T2之前执行和完成,t2可在t1之前执行和完成,T1和T2可以在同一时间实例(并行性)上同时执行,T1和T2可交替执行,…如果操作系统计划在一个单核非SMT非CMP处理器上运行两个并发线程,则可能会获得并发性,但不会获得并行性。并行性可以在多核、多处理器或分布式系统上实现。

并发性通常被称为程序的一个属性,它是一个比并行性更普遍的概念。

资料来源:https://blogs.oracle.com/yunlin/entry/concurrency_vs_parallelism_concurrent_programming


它们是两个短语,从不同的观点(非常轻微地)描述同一件事。并行编程是从硬件的角度描述情况——至少有两个处理器(可能在一个物理包中)并行处理一个问题。并发编程是从软件的角度描述更多的事情——两个或更多的动作可能同时发生(同时发生)。好的。

这里的问题是,当两个短语都不存在时,人们试图用它们来明确区分。事实是,他们试图画的分界线几十年来一直模糊模糊,而且随着时间的推移变得越来越模糊。好的。

他们试图讨论的是,从前,大多数计算机只有一个CPU。当您在单个CPU上执行多个进程(或线程)时,CPU实际上一次只执行其中一个线程的一条指令。并发性的出现是一种错觉——CPU在不同线程的执行指令之间切换的速度足够快,以至于在人类的感知下(小于100毫秒的任何东西看起来都是瞬时的),它看起来像是同时做了许多事情。好的。

与此形成明显对比的是一台具有多个CPU的计算机,或者一台具有多个核心的CPU,因此机器同时执行来自多个线程和/或进程的指令;执行一个线程和/或进程的代码对另一个线程和/或进程的代码执行没有任何影响。好的。

现在的问题是:这样一个干净的区别几乎从未存在过。计算机设计者实际上相当聪明,所以他们很早以前就注意到(例如)当你需要从一个I/O设备(如磁盘)中读取一些数据时,需要很长时间(以CPU周期为单位)才能完成。他们没有在发生这种情况时让CPU闲置,而是想出了各种方法让一个进程/线程发出I/O请求,并让其他进程/线程的代码在I/O请求完成时在CPU上执行。好的。

因此,早在多核CPU成为标准之前,我们就有多个线程并行操作。好的。

不过,这只是冰山一角。几十年前,计算机也开始提供另一个级别的并行性。同样,作为相当聪明的人,计算机设计者注意到,在很多情况下,他们的指令彼此没有影响,因此可以同时从同一个流中执行多个指令。一个很早就为人所熟知的例子是控制数据6600。1964年,这台计算机问世时,它是世界上速度最快的计算机(相差甚远),而如今仍在使用许多相同的基本体系结构。它跟踪每个指令使用的资源,并有一组执行单元,这些执行单元在依赖的资源可用时立即执行指令,与最新的Intel/AMD处理器的设计非常相似。好的。

但是(就像广告上常说的那样)等一下——这不全是。还有另一个设计元素需要添加更多的混乱。它有很多不同的名称(例如,"超线程"、"smt"、"cmp"),但它们都引用了相同的基本思想:一个CPU,它可以同时执行多个线程,使用一些独立于每个线程的资源和一些线程间共享的资源的组合。在典型情况下,这与上面概述的指令级并行性结合在一起。为此,我们有两组(或更多)体系结构寄存器。然后我们有一组执行单元,可以在必要的资源可用时立即执行指令。这些通常结合得很好,因为来自不同流的指令实际上从不依赖相同的资源。好的。

然后,当然,我们会得到多核的现代系统。事情很明显,对吧?我们有n个(目前大约在2到256之间)独立的核心,它们都可以同时执行指令,所以我们有明确的真正并行情况——在一个进程/线程中执行指令不会影响在另一个进程/线程中执行指令。好的。

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

总结一下:人们喜欢将共享资源和独立资源进行对比的简单场景实际上在现实生活中从未发生过。在共享所有资源的情况下,我们最终得到的结果类似于MS-DOS,一次只能运行一个程序,在运行另一个程序之前,我们必须停止运行一个程序。有了完全独立的资源,我们有n台运行MS-DOS的计算机(甚至连连接它们的网络都没有),它们之间根本就没有共享任何东西的能力(因为如果我们甚至可以共享一个文件,那么,这就是共享资源,这违反了什么都不共享的基本前提)。好的。

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

人们喜欢画的"并行"和"并行"之间的清晰划分并不存在,而且几乎从未存在过。人们喜欢将其分类为"并发"的行为通常仍然涉及至少一种而且通常是更多不同类型的并行执行。他们喜欢将其归类为"并行"通常涉及共享资源和(例如)一个进程在使用两个进程共享的资源时阻塞另一个进程的执行。好的。

试图在"并行"和"并发"之间划清界限的人们,生活在一个从未真正存在过的计算机的幻想中。好的。好啊。


  • Concurrent programming is in a general sense to refer to environments in which the tasks we define can occur in any order. One
    task can occur before or after another, and some or all tasks can be
    performed at the same time.

  • Parallel programming is to specifically refer to the simultaneous execution of concurrent tasks on different processors. Thus, all
    parallel programming is concurrent, but not all concurrent programming
    is parallel.

来源:pthreads编程-一个POSIX标准,用于更好的多处理、Buttlar、Farrell、Nichols


并行编程发生在代码同时执行,并且每个执行都独立于另一个执行时。因此,通常不会关注共享变量,因为这不太可能发生。

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


In programming, concurrency is the composition of independently
executing processes, while parallelism is the simultaneous execution
of (possibly related) computations.
- Andrew Gerrand -

Concurrency is the composition of independently executing
computations. Concurrency is a way to structure software, particularly
as a way to write clean code that interacts well with the real world.
It is not parallelism.

Concurrency is not parallelism, although it enables parallelism. If
you have only one processor, your program can still be concurrent but
it cannot be parallel. On the other hand, a well-written concurrent
program might run efficiently in parallel on a multiprocessor. That
property could be important...
- Rob Pike -

为了理解这一区别,我强烈建议您观看Rob Pike(Golang创作者之一)的视频。并发不是并行


典型的任务调度可以是串行的、并行的或并发的。

  • 串行:任务必须按已知的顺序一个接一个地执行,否则将无法工作。足够简单。

  • 并行:任务必须同时执行,否则将无法工作。

    • 任何任务的任何故障(功能上或时间上)都将导致整个系统故障。
    • 所有的任务都必须有一个共同可靠的时间感。

    尽量避免这样,否则我们会在喝茶的时候流泪。

  • 并发:我们不在乎。不过,我们并不粗心:我们已经对它进行了分析,这无关紧要;因此,我们可以随时使用任何可用的工具执行任何任务。快乐的日子。

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

人们通常认为这是关于软件的,但事实上是一个系统设计概念提前更新了计算机;软件系统在接受上有点慢,甚至很少有软件语言试图解决这个问题。如果你感兴趣的话,你可以试着查一下电脑语言occam。

简单地说,系统设计解决了以下问题:

  • 动词-你在做什么(操作或算法)
  • 名词-你在做什么(数据或接口)
  • 何时-启动、计划、状态更改
  • 如何-串行、并行、并发
  • 在哪里——一旦你知道了事情发生的时间,你就可以说事情发生的地方,而不是以前。
  • 为什么-这是做这件事的方法吗?还有其他方法吗?更重要的是,有更好的方法吗?如果你不这么做会怎么样?

祝你好运。


我明白区别是:

1)使用共享资源并行运行2)使用不同资源并行运行

因此,您可以让两件事情同时发生,彼此独立,即使它们在点(2)处聚集在一起,或者在执行的整个操作(1)中,两件事情利用相同的储备。


虽然还没有完成关于"平行"和"同时"两个术语区别的协定,许多作者作出以下区分:

  • 在并行计算中,一个程序可以在任何时刻进行多个任务。
  • 在并行计算中,程序是多个任务紧密合作的程序。解决一个问题。

所以并行程序是并发的,但是多任务操作系统这样的程序也是并发的,即使它是在一台具有只有一个核心,因为多个任务可以在任何时刻进行。

资料来源:并行编程导论,彼得·帕切科