呢篇文會延續返Part 1講嘅內容,都係target一啲advance少少同有接觸Python嘅讀者。Part 1提到大部份嘅tasks都係離唔開兩樣嘢,IO-bound & CPU-bound。後者其實唔使特別多講,因為主要係牽涉兩樣嘢,一係你有幾多資源去做運算,另外就係本身script夠唔夠efficient。
呢度我想討論嘅topic係前者多啲,上一部份有提到如果要解決IO-bound task係可以用Multi-threading,多線程。呢次喺度想補充多一個Python入邊嘅Solution - async (非同步)。
Python入邊,synchronous code係比較直接,其實就係我哋初學者去學寫嘅Script,但係本身因為Python GIL嘅設計,對於處理IO-bound task其實好冇效率。而asynchronous code (asyncio) 就係Python入邊可以實踐concurrency。
Async / Await
「非同步編程」主要係指喺同一個thread底下,可以同時處理多個 I/O 相關任務(例如網絡請求、讀寫檔案)。一個程式喺等緊 I/O 嘅時候,其實冇用 CPU 資源,咁就可以將 CPU 用嚟做其他嘢,而唔使等嗰個 I/O 完成先繼續。
Python 裏面最常用「asyncio」 呢個package去做非同步處理。
用「async」關鍵字declare一個「協程(coroutine)」,再用「await」去等待另一個協程完成,就可以喺唔同任務之間輪流運行。
Multi-threading
多線程指喺同一個進程裡面,可以開多個線程,理論上同時執行唔同嘅任務。不過,Python 有「GIL(Global Interpreter Lock)」嘅限制:
喺同一個 Python Interpreter入邊,只可以有一條線程(thread)同時間執行 Python bytecode。
喺CPU-bound task,多線程唔會真正並行(parallel)。
但如果個程式大部分時間都係做 I/O-bound task,多線程依然有效,因為一條線程等緊 I/O,就可以切換去另一條線程做嘢。
When to use which?
如果大部分任務都係 I/O-bound,而且對「async/await」語法較熟,可以用 asyncio。可讀性高,而且資源佔用相對較低。
如果你套程式/函式庫唔方便改寫成非同步,可以選擇多線程。
兩種方法對 I/O-bound 來講都可以提升concurrency。
可能大家睇到而家都未完全明晒究竟呢兩個分別係啲咩,以前我喺度學嘅時候睇過一個好得意嘅例子:
synchronous就好似你去嗌麥當勞食好多個餐,你去咗電子機叫完然後卡喺度拎埋餐,之後係咁repeat;
Multi-threading就好似你叫好多個朋友喺唔同嘅電子機度分別各自各order ,咁樣就可以快好多;
async就好似你撳完一部機即刻走去第二部機落order,之後再返嚟俾錢同拎返張單,最後一次過拎餐。
最後要講嘅就係呢篇文最主要其實係解決I/O-bound task嘅solution,所以大家唔好混淆我以上講嘅概念同解決方法可以處理到CPU-bound task,呢度都會attach埋sample code,希望幫到大家去優化本身嘅trading system 。