Re: [問題] 請問 Coroutine & 一般 callback 合作的問題

作者: zerof (貓橘毛發呆雕像)   2023-02-07 02:00:12
: 我也可以用 multi-process 而不是 thread 來解啊
: 解法不只一種,而且我不認為問題出在 GIL
: 畢竟我的 thread 有三十多個,我也真嫌多了
: 用了 Coroutine 就合併回一個,但卻是三十多個 task
: 我覺得這也蠻好的
: Coroutine 既然是個潮流就來了解一下,有別的解法就先放一邊吧..
: 真要 C 我何不回 C 的世界,寫純 C..
你要不要看看 Chrome 開起來的時候平常是起幾個 Threads ?
Coroutine 是潮流? 你不是寫 C 嗎怎麼沒用過 libtask ?
這也難怪前面被嗆先回去讀 OS , Preemptive/Cooperative multitasking 是不是
都沒聽過 ?
如果問題不是出在 GIL ,那問題是出在你的 code 架構不對?
我確實是蠻好奇的啦,如果你可以斷定不是出在 GIL ,難道 PyQT 的 QThread 是寫
來好看的?
我想你從頭到尾沒有搞清楚 GIL 所以根本不明白 GUI 為什麼會 freezing
threading 本身就是 preemptive 的, GIL threads 在 context switching 的時候
會有 Locking 的問題,反過來說, GUI 要執行的 main thread 無法保證總是搶得到
GIL ,而產生 freeze 的現象;當你 threads 開得多,裡面又都是跑 python code
的時候就會非常的明顯。
Python 連 serial/smbus 的 libraries 都是 blocking I/O ,最底層摸到 sockets
的時候的確是會 release GIL ,但回過頭來就還是 preemptive 的本質:你沒辦法保
證 GUI 用的 thread 一定會搶到 GIL 。
這問題換到用 asyncio 並不會被解決,本質上的差別。 asycnio 底層用的 sockets
是 non-blocking 的,你用同樣的 libraries 來跑,一樣會遇到 GIL 的問題,而且
更嚴重。(GUI 一個 loop, asyncio 一個 loop)
loop.run_in_executor 的本質是 concurrent.futures 底下的 ThreadPoolExecutor
,當然你也可以改用 ProcessPoolExecutor ,這跟你原本的 threads 改成 Process
一樣,唯一的差別是 Executor 用的是 Worker model。
回過頭來說,照你原本 30 threads 的版本,可以先試著用 pypy 跑看看能不能加速
Python code 執行的速度,減輕 GIL 的影響 (沒錯, pypy 也是有 GIL);另外的選
項用 Cython 把 threads 用 release_gil 加速。
上面兩個選項都是最小改動,要完全避免 GUI freezing 的話就是把 threads 移到
另一個 Process,變成 Thread(GUI) <-> Process (Threads) 的架構,但如果你在
各個 threads 之間有 sharing data , IPC 的成本不見得會比較低。
當然你也可以寫 C 啦,能用的東西多得是,會不會而已。
BTW , asyncio 真的不好嗎?當然不是。但 Python 的 async 有傳染性,而且受限於
GIL ,sync -> async 不實際, async -> sync 更是自找麻煩。
糯米摻黏米又怎麼會好呢? 要寫 GUI 不如左轉 nodejs 吧
作者: leolarrel (真.粽子無雙)   2023-02-07 10:39:00
總算有個懂OS/底層的人發文了
作者: agogoman (cocorosie)   2023-02-07 20:47:00
推這篇
作者: lycantrope (阿寬)   2023-02-07 21:36:00
作者: celestialgod (天)   2023-02-08 20:12:00
推 這篇概念清楚 解釋詳盡
作者: Falldog (Yo)   2023-02-10 16:30:00
推推

Links booklink

Contact Us: admin [ a t ] ucptt.com