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