并行编程和并行编程有什么区别?我问谷歌,但没有找到任何可以帮助我理解这种差异的东西。你能给我两个例子吗?
现在,我找到了以下解释:http : //www.linux-mag.com/id/7411-但是“并发是程序的属性”与“并行执行是机器的属性”对我来说还不够-我还是不能说什么。
并行编程和并行编程有什么区别?我问谷歌,但没有找到任何可以帮助我理解这种差异的东西。你能给我两个例子吗?
现在,我找到了以下解释:http : //www.linux-mag.com/id/7411-但是“并发是程序的属性”与“并行执行是机器的属性”对我来说还不够-我还是不能说什么。
Answers:
如果您使用线程(并行编程)编程,则不一定要这样执行(并行执行),因为这取决于计算机是否可以处理多个线程。
这是一个视觉示例。非线程机器上的线程:
-- -- --
/ \
>---- -- -- -- -- ---->>
线程计算机上的线程:
------
/ \
>-------------->>
破折号代表执行的代码。如您所见,它们既拆分又分别执行,但是线程机可以一次执行几个单独的部分。
并发编程考虑到似乎重叠的操作,并且主要涉及由于不确定性控制流而引起的复杂性。与并发程序相关的量化成本通常是吞吐量和延迟。并发程序通常受IO约束,但并不总是如此,例如,并发垃圾收集器完全在CPU上。并发程序的教学示例是Web搜寻器。该程序启动对网页的请求,并在下载结果可用时并发接受响应,从而累积一组已被访问的页面。控制流是不确定的,因为每次运行程序时不一定都以相同的顺序接收响应。这种特性会使调试并发程序变得非常困难。Erlang,F#异步工作流和Scala的Akka库可能是高度并发编程的最有前途的方法。
多核编程是并行编程的特例。并行编程涉及为了提高吞吐量的特定目标而重叠的操作。通过确定控制流可以避免并发编程的困难。通常,程序会生成并行运行的子任务集,并且父任务仅在每个子任务完成后才继续。这使得并行程序比并发程序更容易调试。并行编程的难点是针对诸如粒度和通信之类的问题进行性能优化。在多核的情况下,后者仍然是一个问题,因为与将数据从一个缓存传输到另一个缓存相关的成本很高。Cilk可能是在多核上进行高性能并行编程的最有前途的方法,并且已在英特尔的线程构建模块和Microsoft的任务并行库(在.NET 4中)中采用。
https://joearms.github.io/published/2013-04-05-concurrent-and-parallel-programming.html
并发=两个队列和一台咖啡机。
并行=两个队列和两个咖啡机。
将原始问题解释为并行/并发计算,而不是编程。
在并发计算中,两个计算都彼此独立地进行。第二个计算不必等到第一个计算完成就可以进行。但是,它没有说明如何实现此目标的机制。在单核设置中,需要在线程之间挂起和交替(也称为抢先式多线程)。
在并行计算中,两个计算都同时进行 -实际上是在同一时间。单CPU无法实现,而是需要多核设置。
图片来自文章:“ Node.js中的并行与并发”
与
我相信并发编程是指多线程编程,它是让您的程序运行从硬件详细信息中抽象出来的多个线程。
并行编程是指专门设计程序算法以利用可用的并行执行。例如,您可以并行执行某些算法的两个分支,以期比起先检查第一个然后再检查第二个分支的结果更快(平均)达到结果。
我在一些博客中找到了此内容。认为它是有用和相关的。
并发和并行性不是一回事。如果未预先确定两个任务的执行顺序,则两个任务T1和T2是并发的,
T1可以在T2之前执行并完成,T2可以在相同时间(并行)同时执行T1,T1和T2之前执行并完成,T1和T2可以交替执行,...如果有两个并发线程如果操作系统将其调度为在一个单核非SMT非CMP处理器上运行,则可能会并发但不会并行。并行可能在多核,多处理器或分布式系统上进行。
并发通常被称为程序的属性,并且是比并行性更笼统的概念。
资料来源:https : //blogs.oracle.com/yuanlin/entry/concurrency_vs_parallelism_concurrent_programming
他们是两个短语,从(非常轻微)不同的角度描述同一件事。并行编程从硬件的角度描述了这种情况-至少有两个处理器(可能在单个物理包中)并行处理问题。并发编程从软件的角度描述了更多东西-可能在同一时间(同时)发生两个或多个动作。
这里的问题是,当人们不真正使用这两个短语时,他们会尝试使用这两个短语进行明确的区分。现实情况是,他们试图绘制的分界线数十年来一直模糊不清,并且随着时间的推移变得越来越模糊。
他们试图讨论的事实是,从前,大多数计算机只有一个CPU。当您在单个CPU上执行多个进程(或线程)时,CPU一次实际上仅在其中一个线程中执行一条指令。并发的外观是一种错觉-CPU在不同线程之间执行指令之间的切换足够快,以至于让人感觉到(任何小于100 ms的瞬间看起来都是瞬时的),看起来好像它正在一次做很多事情。
与此形成鲜明对比的是,计算机具有多个CPU或具有多个内核的CPU,因此该计算机正好同时执行来自多个线程和/或进程的指令。执行一个的代码不会/不会对另一个执行的代码产生任何影响。
现在的问题是:如此清晰的区分几乎从未存在过。计算机设计师实际上是相当聪明的,所以他们很久以前就注意到(例如)当您需要从I / O设备(例如磁盘)读取某些数据时,花了很长时间(就CPU周期而言)完。他们没有让CPU闲置,而是想出了各种方法让一个进程/线程发出I / O请求,并让其他进程/线程的代码在I / O请求完成时在CPU上执行。
因此,早在多核CPU成为规范之前,我们就有来自多个线程的操作并行发生。
不过,那只是冰山一角。几十年前,计算机也开始提供另一级别的并行性。再次,作为非常聪明的人,计算机设计师注意到,在很多情况下,他们所使用的指令不会互相影响,因此可以从同一流中同时执行多个指令。早已广为人知的一个例子是Control Data6600。这是1964年推出时(相当大幅度)世界上最快的计算机-至今仍使用许多相同的基本体系结构。它跟踪每条指令使用的资源,并具有一组执行单元,一旦它们依赖的资源可用,它们就会执行指令,这与最新的Intel / AMD处理器的设计非常相似。
但是(正如商业广告所说的那样)等等-还不止这些。还有另一个设计元素,进一步增加了混乱。它有很多不同的名称(例如“ Hyperthreading”,“ SMT”,“ CMP”),但它们都引用相同的基本思想:一个CPU可以同时使用多个资源并同时执行多个线程,每个线程和线程之间共享的一些资源是独立的。在典型情况下,这与上面概述的指令级并行性结合在一起。为此,我们有两组(或更多组)体系结构寄存器。然后,我们有一组执行单元,可以在必要的资源可用时立即执行指令。
然后,我们当然可以使用具有多个内核的现代系统。这里的事情很明显,对吧?我们有N个内核(目前在2到256个左右之间),每个内核都可以同时执行指令,因此我们有一个真正的并行处理的明显案例-在一个进程/线程中执行指令不会不会影响另一个执行指令。
好吧,有点。即使在这里,我们也有一些独立的资源(寄存器,执行单元,至少一个缓存级别)和一些共享资源(通常至少是最低缓存级别,并且肯定还有内存控制器和内存带宽)。
总结一下:人们喜欢在共享资源和独立资源之间进行对比的简单场景实际上在现实生活中从未发生过。在共享所有资源的情况下,我们最终会遇到类似于MS-DOS的情况,在该环境中,我们一次只能运行一个程序,并且必须停止运行一个程序才能完全运行另一个程序。有了完全独立的资源,我们有N台运行MS-DOS的计算机(甚至没有网络来连接它们),根本无法共享它们之间的任何内容(因为即使我们可以共享文件,那也就是共享资源,违反了什么都不共享的基本前提)。
每个有趣的案例都涉及独立资源和共享资源的某种组合。每台相当现代的计算机(以及很多不是现代的计算机)至少具有同时执行至少一些独立操作的能力,并且几乎任何比MS-DOS更复杂的事物都至少利用了这一点。一定程度上。
人们喜欢画的“并发”和“平行”之间的漂亮,清晰的划分是不存在的,而且几乎永远不会存在。人们喜欢归类为“并发”的内容通常仍然涉及至少一种并且通常是更多种不同类型的并行执行。他们喜欢归类为“并行”的内容通常涉及共享资源,(例如)一个进程在使用两者之间共享的资源时阻止了另一个进程的执行。
试图在“并行”和“并行”之间进行清晰区分的人们生活在幻想中的计算机实际上并不存在。
Concurrent programming
从广义上讲,是指我们定义的任务可以按任何顺序发生的环境。一个任务可以在另一个任务之前或之后发生,并且某些或所有任务可以同时执行。
Parallel programming
具体是指在不同处理器上同时执行并发任务。因此,所有并行编程都是并行的,但并非所有并行编程都是并行的。
当同时执行代码并且每次执行彼此独立时,将发生并行编程。因此,通常不会过分关注共享变量,因为这种情况不太可能发生。
但是,并发编程由共享变量的不同进程/线程执行的代码组成,因此,在并发编程中,我们必须建立某种规则来确定首先执行哪个进程/线程,我们希望这样做,以便可以确保在那里将保持一致,我们可以肯定地知道会发生什么。如果没有控制权,并且所有线程同时进行计算并将事物存储在相同的变量中,那么我们怎么知道最终会发生什么?也许一个线程比另一个线程快,也许其中一个线程甚至在执行过程中停止了运行,而另一个线程使用损坏的(尚未完全计算出的)变量继续执行不同的计算,则可能性是无限的。在这些情况下,我们通常使用并发编程而不是并行编程。
经典的任务调度可以是 串行,并行或并发。
串行:任务必须以已知的欺骗顺序一个接一个地执行,否则将无法正常工作。很简单。
并行:必须同时执行任务,否则将无法执行。
尽量避免这种情况,否则下午茶时间我们会流泪。
并发:我们不在乎。但是,我们并不是粗心的:我们已经分析过了,没关系;因此,我们可以随时使用任何可用工具执行任何任务。快乐的时光。
通常,可用调度会在已知事件(我们称为状态更改)时发生更改。
人们经常认为这与软件有关,但实际上,它是一种早于计算机的系统设计概念。软件系统的使用有点慢,甚至很少软件语言试图解决该问题。如果您有兴趣,可以尝试查找晶片机语言occam。
简而言之,系统设计可解决以下问题:
祝好运。
并发和并行性 来源
在单个处理器上的多线程进程中,处理器可以在线程之间切换执行资源,从而导致并发执行。
在共享内存多处理器环境中的同一多线程进程中,该进程中的每个线程可以同时在单独的处理器上运行,从而导致并行执行。
当进程中的线程数少于或等于处理器时,线程支持系统与操作环境一起确保每个线程在不同的处理器上运行。
例如,在具有相同数量的线程和处理器的矩阵乘法中,每个线程(和每个处理器)计算一行结果。
在许多不同的特定情况下,不同的人谈论不同种类的并发和并行性,因此需要一些抽象来掩盖其共同性质。
基本抽象是在计算机科学中完成的,其中并行性和并行性都归因于程序的属性。在这里,程序是对计算的形式化描述。这样的程序不必使用任何特定于实现的特定语言或编码。API / ABI / ISA / OS的存在与这种抽象级别无关。当然,将需要更详细的特定于实现的知识(例如线程模型)来进行具体的编程工作,基本抽象的精神不会改变。
第二个重要事实是,由于通用属性,并发和并行性可以在许多不同的抽象中共存。
对于一般区别,请参阅并发与并行性基本视图的相关答案。(也有一些包含其他来源的链接。)
并发编程和并行编程是使用某些暴露可编程性的系统来实现此类一般属性的技术。这些系统通常是编程语言及其实现。
编程语言可以通过内置语义规则公开预期的属性。在大多数情况下,此类规则指定对特定语言结构(例如表达式)的评估,从而使所涉及的计算有效地并发或并行。(更具体地说,评估所隐含的计算效果可以完美地反映这些属性。)但是,并发/并行语言语义本质上是复杂的,对于实际工作来说并不必要(将有效的并发/并行算法作为现实问题的解决方案来实现) )。因此,大多数传统语言都采用了更为保守和简单的方法:假设评估的语义是完全顺序和串行的,然后提供可选的原语以允许某些计算是并发的和并行的。这些原语可以是该语言支持的关键字或过程结构(“功能”)。它们是基于与托管环境(OS或“裸机”硬件接口)的交互来实现的,托管环境通常相对于该语言是不透明的(无法使用该语言可移植地派生)。因此,在程序员所看到的这种特殊的高级抽象中,除了这些“魔术”原语和依赖于这些原语的程序之外,并发/并行是没有什么。如果并发/并行性属性不那么令人感兴趣,程序员可以享受较少的易于出错的编程经验。
尽管基元在最高级的抽象中将复合体抽象化,但实现仍具有语言功能未暴露的额外复杂性。因此,需要一些中级抽象。一个典型的例子是线程。线程允许语言实现(运行时)支持一个或多个执行线程(或简称为线程;有时也称为进程,它不一定是操作系统中计划的任务的概念)。线程通常是由运行时抢先调度的,因此线程不需要了解其他线程。因此,只要不共享任何线程(关键资源,线程就很自然地实现并行性)):只需分解不同线程中的计算,一旦基础实现允许执行过程中计算资源的重叠,它就可以工作。线程还受共享资源的并发访问的约束:仅以任何顺序访问资源都将满足算法所需的最小约束,并且实现将最终确定何时访问。在这种情况下,可能需要执行一些同步操作。有些语言将线程和同步操作视为高级抽象的一部分,并将它们公开为原语,而其他一些语言则仅鼓励使用相对高级的原语(例如future / promises)。
在特定于语言的线程级别下,底层托管环境(通常是OS)进行多任务处理。操作系统级别的抢占式多任务用于实现(抢占式)多线程。在某些环境(如Windows NT)中,基本计划单元(任务)也是“线程”。为了通过上述线程的用户空间实现来区分它们,它们称为内核线程,其中“内核”是指操作系统的内核(但是,严格来说,对于Windows NT而言,这并不完全正确;“真正的”内核是NT执行)。内核线程并不总是1:1映射到用户空间线程,尽管1:1映射通常会减少大多数映射开销。由于内核线程非常繁重(涉及系统调用),因此无法创建/销毁/通信,用户空间中的绿色线程来克服开销问题,但以映射开销为代价。映射的选择取决于高级抽象中期望的编程范例。例如,当预期同时执行大量用户空间线程时(例如Erlang),1:1映射永远都不可行。
操作系统多任务处理的基础是处理器逻辑核心提供的ISA级多任务处理。这通常是程序员最底层的公共接口。在此级别下,可能存在SMT。这是一种由硬件实现的低级多线程的形式,但可以说,尽管有些通常只能由处理器制造商访问,但仍可以进行一些编程。请注意,硬件设计显然反映了并行性,但是也存在并发调度机制,以使内部硬件资源得到有效利用。
在上面提到的每个“线程”级别中,并发性和并行性都涉及到。尽管编程接口变化很大,但是所有接口在开始时都具有基本抽象所揭示的属性。
仅分享一个有助于突出区别的示例:
并行编程:假设您要实现合并排序算法。每次将问题分为两个子问题时,都可以有两个线程来解决。但是,为了执行合并步骤,您必须等待这两个线程完成,因为合并需要两个子解决方案。这种“强制等待”使它成为并行程序。
并发程序:假设您要压缩n个文本文件并为每个文本文件生成一个压缩文件。您可以有2个(最多n个)线程,每个线程都处理压缩文件的子集。每个线程完成后,就完成了,不必等待或执行任何其他操作。因此,由于以“任意顺序”以交错的方式执行不同的任务,因此程序是并发的,而不是并行的。
就像其他人提到的那样,每个并行程序都是并发的(实际上是并发的),但并非相反。
我将尝试以我自己的风格来解释它,它可能不是计算机术语,但它为您提供了总体思路。
让我们举个例子,说家务:打扫卫生,取出垃圾,修剪草坪等,我们也有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
依此类推
希望这能给您一个想法!现在转到其他答案中解释的技术术语;)