日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

转一篇关于并发和并行概念的好文,附带大神评论

發(fā)布時間:2023/11/29 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 转一篇关于并发和并行概念的好文,附带大神评论 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

轉(zhuǎn)自:https://laike9m.com/blog/huan-zai-yi-huo-bing-fa-he-bing-xing,61/

還在疑惑并發(fā)和并行?

OK,如果你還在為并發(fā)(concurrency)和并行(parallesim)這兩個詞的區(qū)別而感到困擾,那么這篇文章就是寫給你看的。搞這種詞語辨析到底有什么意義?其實沒什么意義,但是有太多人在混用錯用這兩個詞(比如遇到的某門課的老師)。不論中文圈還是英文圈,即使已經(jīng)有數(shù)不清的文章在討論并行vs并發(fā),卻極少有能講清楚的。讓一個講不清楚的人來解釋,比不解釋更可怕。比如我隨便找了個網(wǎng)上的解釋:

前者是邏輯上的同時發(fā)生(simultaneous),而后者是物理上的同時發(fā)生.

并發(fā)性(concurrency),又稱共行性,是指能處理多個同時性活動的能力,并發(fā)事件之間不一定要同一時刻發(fā)生。

并行(parallelism)是指同時發(fā)生的兩個并發(fā)事件,具有并發(fā)的含義,而并發(fā)則不一定并行。

來個比喻:并發(fā)和并行的區(qū)別就是一個人同時吃三個饅頭和三個人同時吃三個饅頭。

看了之后,你懂了么?不懂,更暈了。寫出這類解釋的人,自己也是一知半解,卻又把自己腦子里模糊的影像拿出來寫成文章,讓讀者閱畢反而更加疑惑。當然也有可能他確實懂了,但是寫出這種文字也不能算負責。至于本文,請相信,一定是準確的,我也盡量做到講解清晰。

OK,下面進入正題,concurrency vs parallesim

讓我們大聲朗讀下面這句話:

“并發(fā)”指的是程序的結(jié)構(gòu),“并行”指的是程序運行時的狀態(tài)

即使不看詳細解釋,也請記住這句話。下面來具體說說:

并行(parallesim)

這個概念很好理解。所謂并行,就是同時執(zhí)行的意思,無需過度解讀。判斷程序是否處于并行的狀態(tài),就看同一時刻是否有超過一個“工作單位”在運行就好了。所以,單線程永遠無法達到并行狀態(tài)

要達到并行狀態(tài),最簡單的就是利用多線程和多進程。但是 Python 的多線程由于存在著名的 GIL,無法讓兩個線程真正“同時運行”,所以實際上是無法到達并行狀態(tài)的。

并發(fā)(concurrency)

要理解“并發(fā)”這個概念,必須得清楚,并發(fā)指的是程序的“結(jié)構(gòu)”。當我們說這個程序是并發(fā)的,實際上,這句話應(yīng)當表述成“這個程序采用了支持并發(fā)的設(shè)計”。好,既然并發(fā)指的是人為設(shè)計的結(jié)構(gòu),那么怎樣的程序結(jié)構(gòu)才叫做支持并發(fā)的設(shè)計?

正確的并發(fā)設(shè)計的標準是:使多個操作可以在重疊的時間段內(nèi)進行(two tasks can start, run, and complete in overlapping time periods)

這句話的重點有兩個。我們先看“(操作)在重疊的時間段內(nèi)進行”這個概念。它是否就是我們前面說到的并行呢?是,也不是。并行,當然是在重疊的時間段內(nèi)執(zhí)行,但是另外一種執(zhí)行模式,也屬于在重疊時間段內(nèi)進行。這就是協(xié)程。

使用協(xié)程時,程序的執(zhí)行看起來往往是這個樣子:

task1, task2 是兩段不同的代碼,比如兩個函數(shù),其中黑色塊代表某段代碼正在執(zhí)行。注意,這里從始至終,在任何一個時間點上都只有一段代碼在執(zhí)行,但是,由于 task1 和 task2 在重疊的時間段內(nèi)執(zhí)行,所以這是一個支持并發(fā)的設(shè)計。與并行不同,單核單線程能支持并發(fā)。

經(jīng)常看到這樣一個說法,叫做并發(fā)執(zhí)行。現(xiàn)在我們可以正確理解它。有兩種可能:

  • 原本想說的是“并行執(zhí)行”,但是用錯了詞
  • 指多個操作可以在重疊的時間段內(nèi)進行,即,真的并行,或是類似上圖那樣的執(zhí)行模式。
  • 我的建議是盡可能不使用這個詞,容易造成誤會,尤其是對那些并發(fā)并行不分的人。但是讀到這里的各位顯然能正確區(qū)分,所以下面為了簡便,將使用并發(fā)執(zhí)行這個詞。

    第二個重點是“可以在重疊的時間段內(nèi)進行”中的“可以”兩個字。“可以”的意思是,正確的并發(fā)設(shè)計使并發(fā)執(zhí)行成為可能,但是程序在實際運行時卻不一定會出現(xiàn)多個任務(wù)執(zhí)行時間段 overlap 的情形。比如:我們的程序會為每個任務(wù)開一個線程或者協(xié)程,只有一個任務(wù)時,顯然不會出現(xiàn)多個任務(wù)執(zhí)行時間段重疊的情況,有多個任務(wù)時,就會出現(xiàn)了。這里我們看到,并發(fā)并不描述程序執(zhí)行的狀態(tài),它描述的是一種設(shè)計,是程序的結(jié)構(gòu),比如上面例子里“為每個任務(wù)開一個線程”的設(shè)計。并發(fā)設(shè)計和程序?qū)嶋H執(zhí)行情況沒有直接關(guān)聯(lián),但是正確的并發(fā)設(shè)計讓并發(fā)執(zhí)行成為可能。反之,如果程序被設(shè)計為執(zhí)行完一個任務(wù)再接著執(zhí)行下一個,那就不是并發(fā)設(shè)計了,因為做不到并發(fā)執(zhí)行。

    那么,如何實現(xiàn)支持并發(fā)的設(shè)計?兩個字:拆分

    之所以并發(fā)設(shè)計往往需要把流程拆開,是因為如果不拆分也就不可能在同一時間段進行多個任務(wù)了。這種拆分可以是平行的拆分,比如抽象成同類的任務(wù),也可以是不平行的,比如分為多個步驟。

    并發(fā)和并行的關(guān)系

    Different concurrent designs enable different ways to parallelize.

    這句話來自著名的talk:?Concurrency is not parallelism。它足夠concise,以至于不需要過多解釋。但是僅僅引用別人的話總是不太好,所以我再用之前文字的總結(jié)來說明:并發(fā)設(shè)計讓并發(fā)執(zhí)行成為可能,而并行是并發(fā)執(zhí)行的一種模式

    最后,關(guān)于Concurrency is not parallelism這個talk再多說點。自從這個talk出來,直接引爆了一堆討論并發(fā)vs并行的文章,并且無一例外提到這個talk,甚至有的文章直接用它的slide里的圖片來說明。比如這張:

    以為我要解釋這張圖嗎?NO。放這張圖的唯一原因就是萌萌的gopher。

    再來張?zhí)貙?#xff1a;

    之前看到知乎上有個關(guān)于go為什么流行的問題,有個答案是“l(fā)ogo萌”當時我就笑噴了。

    好像跑題了,繼續(xù)說這個 talk。和很多人一樣,我也是看了這個 talk 才開始思考 concurrency vs parallesim 的問題。為了研究那一堆推小車的 gopher 到底是怎么回事,我花費了相當多的時間。實際上后來我更多地是通過網(wǎng)上的只言片語(比如SO的回答)和自己的思考弄清了這個問題,talk 并沒有很大幫助。徹底明白之后再回過頭來看這個 talk,確實相當不錯,Andrew Gerrand 對這個問題的理解絕對夠深刻,但是太不新手向了。最大問題在于,那一堆 gopher 的例子不夠好,太復(fù)雜。Andrew Gerrand 花了大把時間來講述不同的并發(fā)設(shè)計,但是作為第一次接觸這個話題的人,在沒有搞清楚并發(fā)并行區(qū)別的情況下就去研究推小車的 gopher,太難了。“Different concurrent designs enable different ways to parallelize” 這句總結(jié)很精辟,但也只有那些已經(jīng)透徹理解的人才能領(lǐng)會,比如我和看到這里的讀者,對新手來說就和經(jīng)文一樣難懂。總結(jié)下來一句話,不要一開始就去看這個視頻,也不要花時間研究推小車的gopher。Gopher is moe, but confusing.

    2015.8.14 更新

    事實上我之前的理解還是有錯誤。在《最近的幾個面試》這篇文章里有提到。最近買了《七周七并發(fā)模型》這本書,發(fā)現(xiàn)其中有講,在此摘錄一下(英文版 p3~p4):

    Although there’s a tendency to think that parallelism means multiple cores,?modern computers are parallel on many different levels. The reason why individual cores have been able to get faster every year, until recently, is that they’ve been using all those extra transistors predicted by Moore’s law in parallel, both at the bit and at the instruction level.

    Bit-Level Parallelism
    Why is a 32-bit computer faster than an 8-bit one? Parallelism. If an 8-bit computer wants to add two 32-bit numbers, it has to do it as a sequence of 8-bit operations. By contrast, a 32-bit computer can do it in one step, handling each of the 4 bytes within the 32-bit numbers in parallel. That’s why the history of computing has seen us move from 8- to 16-, 32-, and now 64-bit architectures. The total amount of benefit we’ll see from this kind of parallelism has its limits, though, which is why we’re unlikely to see 128-bit computers soon.

    Instruction-Level Parallelism
    Modern CPUs are highly parallel, using techniques like pipelining, out-of-order execution, and speculative execution.
    As programmers, we’ve mostly been able to ignore this because, despite the fact that the processor has been doing things in parallel under our feet, it’s carefully maintained the illusion that everything is happening sequentially. This illusion is breaking down, however. Processor designers are no longer able to find ways to increase the speed of an individual core. As we move into a multicore world, we need to start worrying about the fact that instructions aren’t handled sequentially. We’ll talk about this more in Memory Visibility, on page ?.

    Data Parallelism
    Data-parallel (sometimes called SIMD, for “single instruction, multiple data”) architectures are capable of performing the same operations on a large quantity of data in parallel. They’re not suitable for every type of problem, but they can be extremely effective in the right circumstances. One of the applications that’s most amenable to data parallelism is image processing. To increase the brightness of an image, for example, we increase the brightness of each pixel. For this reason, modern GPUs (graphics processing units) have evolved into extremely powerful data-parallel processors.

    Task-Level Parallelism
    Finally, we reach what most people think of as parallelism—multiple processors. From a programmer’s point of view, the most important distinguishing feature of a multiprocessor architecture is the memory model, specifically whether it’s shared or distributed.

    最關(guān)鍵的一點是,計算機在不同層次上都使用了并行技術(shù)。之前我討論的實際上僅限于 Task-Level 這一層,在這一層上,并行無疑是并發(fā)的一個子集。但是并行并非并發(fā)的子集,因為在 Bit-Level 和 Instruction-Level 上的并行不屬于并發(fā)——比如引文中舉的 32 位計算機執(zhí)行 32 位數(shù)加法的例子,同時處理 4 個字節(jié)顯然是一種并行,但是它們都屬于 32 位加法這一個任務(wù),并不存在多個任務(wù),也就根本沒有并發(fā)。

    所以,正確的說法是這樣:
    并行指物理上同時執(zhí)行,并發(fā)指能夠讓多個任務(wù)在邏輯上交織執(zhí)行的程序設(shè)計

    按照我現(xiàn)在的理解,并發(fā)針對的是 Task-Level 及更高層,并行則不限。這也是它們的區(qū)別。


    ?

    評論內(nèi)容:

    ?

    實際上個人覺得從計算機體系發(fā)展的角度來介紹更為合適,也更容易理解。
    從Instruction-Level Parallelism來說,這個其實和Task-Level Parallelism是息息相關(guān)的。從早期的計算機來看,任何一個嚴格意義上的Task-Level Parallelism必然是對應(yīng)著Instruction-Level Parallelism的,而Instruction-Level Parallelism必然要依賴于硬件的。這種觀點是很容易接受的,因為這種計算機實質(zhì)上屬于批處理系統(tǒng),執(zhí)行時不存在外部干預(yù),并且不存在程序設(shè)計語言,只有指令。
    任何屬于馮諾依曼結(jié)構(gòu)的計算機,其中的CPU(或者說核)必然是串行執(zhí)行指令的。所以在任何單CPU機器上,是不存在嚴格意義上,或者說狹義上的并行的--在指令級別的嚴格意義上的并行,是指在一個足夠小的時刻,可以允許大于一條的指令在執(zhí)行。
    因此在早期的計算機中,實現(xiàn)嚴格意義上的并行只能采取增加計算機數(shù)量的方法。在這種情況下,Task-Level Parallelism和Instruction-Level Parallelism幾乎沒有區(qū)別。
    想要在這種計算機上同時運行多道程序,歷史上采用的技術(shù)就是--多任務(wù)。
    (這里說句題外話,如果大家看過早起計算機如何編寫指令,如何輸入指令,如何輸出--簡單來說,就是從搬紙帶到搬磁帶的進化,那么看gopher的那些關(guān)于并行并發(fā)的圖會好理解很多。這些圖簡直就是在向當時的搬磚工,啊不對計算機先驅(qū)們致敬啊。)
    這里需要介紹一下為什么會有多任務(wù)。正如我們知道的,程序從大致可以分為計算密集型和IO密集型兩個極端,而商業(yè)程序大多比較偏向IO密集型,所以早期的計算機在很有限的計算資源下,就已經(jīng)出現(xiàn)了IO和計算能力不匹配的問題,即在IO上花的時間要遠遠大于計算的時間。當然這個問題當時并沒有導(dǎo)致并發(fā)方案的出現(xiàn),而是導(dǎo)致了一種硬件的并行--比如IBM 1401這樣的數(shù)據(jù)處理專用機的出現(xiàn)。當然之后在第三代計算機中出現(xiàn)了SPOOLing技術(shù)就不再需要這樣的機器了。
    回到多任務(wù)上來。IO操作耗時較長,也并不需要占用CPU,但這時候CPU即使沒有在執(zhí)行指令卻也必須等待輸入完畢,導(dǎo)致了CPU的空閑。在那個年代,計算資源大多是按時間售賣的,這種空閑是一種極大的浪費。那么我們?yōu)槭裁床荒茏孋PU在等待IO的這段時間里也去執(zhí)行指令呢?這就很自然的引出了多任務(wù)(Multitasking)的概念了。這個概念的理念很好理解,即當一個程序進行IO或者其他耗時卻不占用CPU的操作時,將這個程序切換出去,去執(zhí)行另一個程序的指令。之后等之前的程序IO完畢了,再切換回來繼續(xù)執(zhí)行,以此防止計算資源的浪費。這種切換即上下文切換(context switch)。
    事實上,這就是一種并發(fā)了。在那個時代的計算機上,因為計算資源的限制很可能導(dǎo)致單個任務(wù)的完成時間明顯大于預(yù)期,導(dǎo)致并發(fā)帶來的"并行感"還不是太強烈。但是在現(xiàn)代計算機上,這很容易造成一種兩個任務(wù)同時執(zhí)行的錯覺。
    因此我們可以很容易的看出,這里的并發(fā)本質(zhì)上是一種多個操作者對于計算資源的共享使用,它的目的是達到減少的資源閑置導(dǎo)致的浪費--因此,自然會涉及到計算資源如何分配等問題,這就引申出調(diào)度和鎖等概念。事實上,如果將“計算”兩字去掉,這個描述就可以擴展到計算機中任何對于資源的共享使用,包括了各種層級的方方面面,比如在中文件,內(nèi)存頁面中,進程線程中等。

    當然,以上的并發(fā)是從一種常見的實現(xiàn)的角度來描述的。正如博主所說,我們可以用真正的并行來實現(xiàn)并發(fā),比如在雙核CPU上每個核里跑一個獨立的進程。我們也可以在一個單核的CPU上通過程序調(diào)度來實現(xiàn)這兩個進程的并發(fā)。

    而嚴格意義上的并行,在指令水平,必然只能指同一時刻有多于一條指令處于執(zhí)行階段,因此就必須得“We move into a multicore world”才行。。即使例子中的pipelining,對于單核的CPU也并非實現(xiàn)并行,而只是讓每個時刻,IF, ID, EX, MA, WB這五個步驟對應(yīng)的回路單元都不會閑置而已--事實上這個理念就是并發(fā)了,正如博主所說的“并發(fā)設(shè)計往往需要把流程拆開,是因為如果不拆分也就不可能在同一時間段進行多個任務(wù)了。這種拆分可以是平行的拆分,比如抽象成同類的任務(wù),也可以是不平行的,比如分為多個步驟。”--因此,并發(fā)并不僅限于程序設(shè)計的
    Task-Level上,它是關(guān)于資源共享和使用問題的解決方法的一種抽象。

      • 把加法看成多個任務(wù)的話,也可以說有并發(fā)了。所以其實本質(zhì)在于站在哪個層次來看。?

        • 非常對,把加法這個任務(wù)分成多個子任務(wù)就可以視作并發(fā)了。其實主要還是因為這兩個詞都有狹義和廣義的解釋的原因。如果從廣義上來說,并行必然是并發(fā),因為廣義的并發(fā)的高度抽象定義可以說是,多個問題或者問題的幾個部分在一個重疊的時間段內(nèi)被解決。
          不過個人還是喜歡用并發(fā)來表示通過調(diào)度器以及上下文切換等實現(xiàn)的多任務(wù)或者其他類似的技術(shù)和手段(其實是不知道用什么詞代替好),用并行來表示嚴格的物理上的并行。

    ?

    轉(zhuǎn)載于:https://www.cnblogs.com/mysic/p/5633860.html

    總結(jié)

    以上是生活随笔為你收集整理的转一篇关于并发和并行概念的好文,附带大神评论的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。