併發與並行(concurrency vs parallesim)

最近對計算機中併發(concurrency)和並行(parallesim)這兩個詞的區別很迷惑,將搜索到的相關內容整理以下。golang

http://www.vaikan.com/docs/Concurrency-is-not-Parallelism/#slide-7

定義:

併發 Concurrency編程

將相互獨立的執行過程綜合到一塊兒的編程技術。多線程

並行 Parallelism併發

同時執行(一般是相關的)計算任務的編程技術。app

 

併發 vs. 並行ide

併發是指同時處理不少事情。

而並行是指同時能完成不少事情。

二者不一樣,但相關。

一個重點是組合,一個重點是執行。

併發提供了一種方式讓咱們可以設計一種方案將問題(非必須的)並行的解決。函數

併發是一種將一個程序分解成小片斷獨立執行的程序設計方法。

通訊是指各個獨立的執行任務間的合做。

這是Go語言採用的模式,包括Erlang等其它語言都是基於這種SCP模式:

C. A. R. Hoare: Communicating Sequential Processes (CACM 1978)

 

第二種:ui

https://laike9m.com/blog/huan-zai-yi-huo-bing-fa-he-bing-xing,61/this

「併發」指的是程序的結構,「並行」指的是程序運行時的狀態

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

並行(parallesim)

這個概念很好理解。所謂並行,就是同時執行的意思,無需過分解讀。判斷程序是否處於並行的狀態,就看同一時刻是否有超過一個「工做單位」在運行就行了。因此,單線程永遠沒法達到並行狀態

要達到並行狀態,最簡單的就是利用多線程和多進程。可是 Python 的多線程因爲存在著名的 GIL,沒法讓兩個線程真正「同時運行」,因此其實是沒法到達並行狀態的。

併發(concurrency)

要理解「併發」這個概念,必須得清楚,併發指的是程序的「結構」。當咱們說這個程序是併發的,實際上,這句話應當表述成「這個程序採用了支持併發的設計」。好,既然併發指的是人爲設計的結構,那麼怎樣的程序結構才叫作支持併發的設計?

正確的併發設計的標準是:使多個操做能夠在重疊的時間段內進行(two tasks can start, run, and complete in overlapping time periods)

這句話的重點有兩個。咱們先看「(操做)在重疊的時間段內進行」這個概念。它是否就是咱們前面說到的並行呢?是,也不是。並行,固然是在重疊的時間段內執行,可是另一種執行模式,也屬於在重疊時間段內進行。這就是協程

使用協程時,程序的執行看起來每每是這個樣子:

task1, task2 是兩段不一樣的代碼,好比兩個函數,其中黑色塊表明某段代碼正在執行。注意,這裏從始至終,在任何一個時間點上都只有一段代碼在執行,可是,因爲 task1 和 task2 在重疊的時間段內執行,因此這是一個支持併發的設計。與並行不一樣,單核單線程能支持併發。

 

併發和並行的關係

Different concurrent designs enable different ways to parallelize.

這句話來自著名的talk: Concurrency is not parallelism。它足夠concise,以致於不須要過多解釋。可是僅僅引用別人的話老是不太好,因此我再用以前文字的總結來講明:併發設計讓併發執行成爲可能,而並行是併發執行的一種模式

最後,關於Concurrency is not parallelism這個talk再多說點。自從這個talk出來,直接引爆了一堆討論併發vs並行的文章,而且無一例外提到這個talk,甚至有的文章直接用它的slide裏的圖片來講明。

 

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.

最關鍵的一點是,計算機在不一樣層次上都使用了並行技術。以前我討論的實際上僅限於 Task-Level 這一層,在這一層上,並行無疑是併發的一個子集。可是並行並不是併發的子集,由於在 Bit-Level 和 Instruction-Level 上的並行不屬於併發——好比引文中舉的 32 位計算機執行 32 位數加法的例子,同時處理 4 個字節顯然是一種並行,可是它們都屬於 32 位加法這一個任務,並不存在多個任務,也就根本沒有併發。

因此,正確的說法是這樣:
並行指物理上同時執行,併發指可以讓多個任務在邏輯上交織執行的程序設計

按照我如今的理解,併發針對的是 Task-Level 及更高層,並行則不限。這也是它們的區別。

相關文章
相關標籤/搜索