狠狠撸

狠狠撸Share a Scribd company logo
并行、平行与非同步
13.并行、平行与非同步
? 學習目標
– 認識并行、平行与非同步
– 使用 threading 模組
– 使用 multiprocessing 模組
– 使用 concurrent.futures模組
– 運用 async、await 與 asyncio
2
並行
? 多個流程可以並行(Concurrency)處理,
也就是從使用者的觀點來看,會是同時
「執行」各個流程
? 然而實際上,是同時「管理」多個流程
3
簡介執行緒
4
5
? 雖可以繼承 threading.Thread, 在
__init__()呼叫 super().__init__(),
並在類別中定義run()方法來實作執行緒
? 不過是不建議的,因為這會使得你的流程與
threading.Thread 產生相依性
6
7
8
? python 直譯器同時間只允許執行一個執行
緒,因此並不是真正的平行(Parallel)處
理,只不過「有時候」切換速度快到人類
感覺上像是同時處理罷了
? 執行緒適用的場合之一,就是非計算密集
的場合,因為與其等待某個阻斷作業完成,
不如趁著等待的時間來進行其他執行緒
9
10
11
? 對於計算密集的任務,使用執行緒不見得
會提高處理效率,反而容易因為直譯器必
須切換執行緒而耗費不必要的成本,使得
效率變差。
12
? 如果主執行緒中啟動了額外執行緒,預設
會等待被啟動的所有執行緒都執行完才中
止程式。
? 如果一個 Thread 建立時,指定了daemon
參數為 True,在所有的非 Daemon 的執
行緒都結束時,程式就會直接終止
? 如果需要在背景執行一些常駐任務,就可
以指定 daemon 參數為 True。
13
? 當執行緒使用 join() 加入至另一執行緒
時,另一執行緒會等待被加入的執行緒工
作完畢,然後再繼續它的動作
14
? 如果要停止執行緒,必須自行實作,讓執
行緒跑完應有的流程
15
競速、鎖定、死結
? 如果執行緒之間不需要共享資料, 或者共
享的資料是不可變動(Immutable)的型
態,事情會單純一些
? 然而,執行緒之間經常得共用一些可變動
狀態的資料…
? 要是執行緒之間需要共享的是可變動狀態
的資料,就會有可能發生競速狀況…
16
17
? 若要避免競速的情況發生,就必須資源被
變更與取用時的關鍵程式碼進行鎖定
18
19
? threading.Lock 實作了情境管理器協定,
可以搭配 with 來簡化 acquire() 與
release() 的呼叫
20
21
? 執行緒無法取得鎖定時會造成阻斷,不正
確地使用 Lock 有可能造成效能低落,另一
問題則是死結
22
23
? threading.RLock 實現了可重入鎖
(Reentrant lock)
? 同一執行緒可以重複呼叫同一個
threading.RLock 實例的 acquire()
而不被阻斷
? release()時也要有對應於 acquire()
的次數,方可以完全解除鎖定
? threading.RLock 也實作了情境管理器
協定,可搭配 with 來使用
24
? 另一個經常使用的鎖定機制是
threading.Condition
? 某個執行緒在透過 acquire() 取得鎖定之
後,若需要在特定條件符合之前等待,可
以呼叫 wait() 方法,這會釋放鎖定
? 若其他執行緒的運作促成特定條件成立,
可以呼叫同一 threading.Condition 實
例的 notify(),通知等待條件的一個執
行緒可取得鎖定
25
? 若等待中的執行緒取得鎖定,就會從上次
呼叫 wait() 方法處繼續執行
? 如果等待中的執行緒有多個,還可以呼叫
notify_all(),這會通知全部等待中的
執行緒爭取鎖定
26
27
28
? 如果需要這種一進一出,在執行緒之間交
換資料的方式,Python 標準程式庫中提供
了 queue.Queue
29
? 建立Semaphore 可指定計數器初始值
? 每呼叫一次 acquire(),計數器值遞減一,
在計數器為0 時若呼叫了 acquire(),執
行緒就會被阻斷
? 每呼叫一次 release(),計數器值遞增一,
如果 release()前計數器為 0,而且有執
行緒正在等待,在 release() 並遞增計數
器之後,會通知等待中的執行緒
30
? 可以設定一個 Barrier 並指定數量
? 如果有執行緒先來到這個柵欄,它必須等
待其他執行緒也來到這個柵欄
? 指定的執行緒數量達到,全部執行緒才能
繼續往下執行
31
32
平行
? 針對計算密集式的運算,若能在一個新的
行程(Process)平行(Parallel)運行,在
今日電腦普遍都有多個核心的情況下,就
有機會跑得更快一些。
33
? subprocess 模組可以讓你在執行 Python
程式的過程中,產生新的子行程
34
? 從 Python 3.5 開始,建議使用 run() 函
式來呼叫子行程
? subprocess.run() 執行之後會傳回
CompletedProcess 實例
? 若想要能取得標準輸出的執行結果:
35
? 如果子行程必須接受標準輸入:
36
? subprocess.run() 的底層是透過
subprocess.Popen() 實作出來的
37
? subprocess.Popen() 執行程式,會立
即傳回 Popen 實例,不會等待子行程結束
38
39
? 如果想要以子行程來執行函式,然而使用
類似 threading 模組的 API 介面,那麼
可以使用 multiprocessing 模組
40
41
? 建議在使用 multiprocessing 模組時,
最好的方式是不要共享狀態
? 然而有時行程之間難免需要進行溝通,
multiprocessing.Queue 是執行緒與行
程安全的,實作了必要的鎖定機制
42
43
44
? multiprocessing.Lock 也實作了情境
管理器協定
45
46
非同步
? Python 3.2 新增 concurrent.futures
模組,它提供了執行緒或行程高階封裝,
也便於實現非同步的任務
? 從 Python 3.5 之後,提供了async、
await 等語法,以及 asyncio 模組的支援,
如果非同步任務涉及大量的輸入輸出,可
以善用這些特性
47
使用 concurrent.futures
? 提供了 ThreadPoolExecutor 與
ProcessPoolExecutor 等高階API,分
別為執行緒與行程提供了工作者池的服務
48
49
? 對於計算密集式的任務,可以使用
ProcessPoolExecutor
50
51
? 使用 map() 方法來簡化程式的撰寫
52
Future 與非同步
? 獨立於程式主流程的任務、事件生成,以
及處理事件的方式,稱為非同步
? 使用執行緒或行程時,若想實現非同步概
念,方式之一是採用註冊回呼函式
53
54
? executor 的submit() 執行過後會傳回
Future,擁有 add_done_callback()
55
? 在下載的同時實現簡單的進度列:
56
略談 yield from 與非同步
57
? 若後續處理為數個非同步函式的話,整個
流程會馬上陷入難以理解的狀態
? Python 3.3 時新增了 yield from 語法,
Python 3.4 的 asyncio 與某些第三方程式
庫,曾基於這個語法提出了解決方案
? Python 3.5 後建議不要使用 yield from,
建議使用 async、await
58
59
yield from 與 Future
60
? 有多個非同步函式,顯然就需要個迴圈:
61
? 程式執行雖然是非同步,然而撰寫風格上
卻像是循序
? 若有人想呼叫 asyncTasks() 呢?甚至是
在流程上組合多個這類的函式?
62
63
64
async、asyncio 與並行
? 並非一定要多執行緒或多行程,才能實現
並行
? 多執行緒或多行程只是實現並行比較容易
? 只要執行環境支援,在單一行程、單一執
行緒中,也有可能實現並行
– 在遇到阻斷操作時會讓出(yield)流程控制權
給呼叫函式者,那呼叫函式的一方,就可以繼
續下個並行任務的啟動
65
? 如果在定義函式時,加上了 async 關鍵字,
呼叫該函式並不會馬上執行函式流程,而
是傳回一個 coroutine 物件
? 想要執行函式中定義的流程,可以透過
asyncio.run() 函式
66
? 透過 asyncio.get_event_loop() 建立
事件迴圈代表物件,然後透過它的
run_until_complete() 等方法來執行
67
68
? 透過 asyncio.gather() 函式,直接收
集多個 coroutine 傳回新的 coroutine
69
async、await 與非同步
? async 用來標示函式執行時是非同步,也
就是函式中定義定義了獨立於程式主流程
的任務
? 後續若要在任務完成時,做進一步的處理
也是可行的
? 從 Python 3.5 開始,yield from 已經不
建議使用,因為有了語義更明確的 await
70
71
? 就語義上,若想等待 async 函式執行完後,
再執行後續的流程,可以使用await
? async 函式的任務完成後若有傳回值,會
成為 await 的傳回值
72
73
74
非同步產生器與 async for
75
? 迭代產生器時會以阻斷方式讀取 URL 後傳
回 bytes
76
情境管理器與 async with
77
78

More Related Content

What's hot (20)

PPTX
KSDG-ASP.NET MVC 5 Overview (偽三國誌)
Bruce Chen
?
PDF
Ch02 撰寫與設定Servlet
Justin Lin
?
PDF
Servlet & JSP 教學手冊第二版 - 第 12 章:從模式到框架
Justin Lin
?
PPTX
Asp.net mvc 概觀介紹
Alan Tsai
?
PPTX
Ch13 整合 Spring MVC/Security
Justin Lin
?
PDF
TypeScript-twmvc#16
twMVC
?
PDF
以Code igniter為基礎的網頁前端程式設計
Amigo 陳兆祥
?
PDF
自订泛型、列举与标註
Justin Lin
?
PPT
Java SE 8 技術手冊第 11 章 - 執行緒與並行API
Justin Lin
?
PPTX
1. JavaScript 起步走
Justin Lin
?
PDF
Ch07 使用JSTL
Justin Lin
?
PDF
Ch13 整合Spring MVC
Justin Lin
?
PPTX
Angular.js & ASP.NET in Study4
Kyle Shen
?
PPTX
7. 錯誤處理
Justin Lin
?
PDF
Java Tutorial:Learn Java in 06:00:00
Justin Lin
?
PDF
Java SE 7 技術手冊投影片第 07 章 - 介面與多型
Justin Lin
?
PDF
础苍诲谤辞颈诲开发基础
ykdsg
?
PDF
工作坊总结
Shengyou Fan
?
PPTX
Entity Framework實戰
國昭 張
?
PPTX
JavaScript 物件導向觀念入門 v.s. TypeScript 開發實戰 (微軟實戰課程日)
Will Huang
?
KSDG-ASP.NET MVC 5 Overview (偽三國誌)
Bruce Chen
?
Ch02 撰寫與設定Servlet
Justin Lin
?
Servlet & JSP 教學手冊第二版 - 第 12 章:從模式到框架
Justin Lin
?
Asp.net mvc 概觀介紹
Alan Tsai
?
Ch13 整合 Spring MVC/Security
Justin Lin
?
TypeScript-twmvc#16
twMVC
?
以Code igniter為基礎的網頁前端程式設計
Amigo 陳兆祥
?
自订泛型、列举与标註
Justin Lin
?
Java SE 8 技術手冊第 11 章 - 執行緒與並行API
Justin Lin
?
1. JavaScript 起步走
Justin Lin
?
Ch07 使用JSTL
Justin Lin
?
Ch13 整合Spring MVC
Justin Lin
?
Angular.js & ASP.NET in Study4
Kyle Shen
?
7. 錯誤處理
Justin Lin
?
Java Tutorial:Learn Java in 06:00:00
Justin Lin
?
Java SE 7 技術手冊投影片第 07 章 - 介面與多型
Justin Lin
?
础苍诲谤辞颈诲开发基础
ykdsg
?
工作坊总结
Shengyou Fan
?
Entity Framework實戰
國昭 張
?
JavaScript 物件導向觀念入門 v.s. TypeScript 開發實戰 (微軟實戰課程日)
Will Huang
?

More from Justin Lin (20)

PPTX
Ch12 Spring 起步走
Justin Lin
?
PPTX
Ch11 簡介 JavaMail
Justin Lin
?
PPTX
Ch10 Web 容器安全管理
Justin Lin
?
PPTX
Ch09 整合資料庫
Justin Lin
?
PPTX
Ch08 自訂標籤
Justin Lin
?
PPTX
Ch07 使用 JSTL
Justin Lin
?
PPTX
Ch06 使用 JSP
Justin Lin
?
PPTX
Ch05 Servlet 進階 API、過濾器與傾聽器
Justin Lin
?
PPTX
Ch04 會話管理
Justin Lin
?
PPTX
Ch03 請求與回應
Justin Lin
?
PPTX
Ch02 撰寫與設定 Servlet
Justin Lin
?
PPTX
CH1. 簡介 Web 應用程式
Justin Lin
?
PDF
14. 進階主題
Justin Lin
?
PDF
12. 除错、测试与效能
Justin Lin
?
PDF
11. 常用內建模組
Justin Lin
?
PDF
10. 資料永續與交換
Justin Lin
?
PDF
9. 資料結構
Justin Lin
?
PDF
8. open() 與 io 模組
Justin Lin
?
PDF
7. 例外處理
Justin Lin
?
PDF
6. 類別的繼承
Justin Lin
?
Ch12 Spring 起步走
Justin Lin
?
Ch11 簡介 JavaMail
Justin Lin
?
Ch10 Web 容器安全管理
Justin Lin
?
Ch09 整合資料庫
Justin Lin
?
Ch08 自訂標籤
Justin Lin
?
Ch07 使用 JSTL
Justin Lin
?
Ch06 使用 JSP
Justin Lin
?
Ch05 Servlet 進階 API、過濾器與傾聽器
Justin Lin
?
Ch04 會話管理
Justin Lin
?
Ch03 請求與回應
Justin Lin
?
Ch02 撰寫與設定 Servlet
Justin Lin
?
CH1. 簡介 Web 應用程式
Justin Lin
?
14. 進階主題
Justin Lin
?
12. 除错、测试与效能
Justin Lin
?
11. 常用內建模組
Justin Lin
?
10. 資料永續與交換
Justin Lin
?
9. 資料結構
Justin Lin
?
8. open() 與 io 模組
Justin Lin
?
7. 例外處理
Justin Lin
?
6. 類別的繼承
Justin Lin
?
Ad

并行、平行与非同步