一个小白想法, Python 为什么不通过命令行开关切换两种 GIL 模式?

2021-10-23 22:04:15 +08:00
 O5oz6z3
最近 python 出现一个惊艳的 no-gil 设计,想必大家已经知道了。

那么对于 python GIL 这个老问题,似乎常见的说法是:
粗粒度的 GIL 降低多线程的性能,细粒度的 GIL 降低单线程的性能。

那为什么不全都要,通过命令行开关切换两种 GIL 模式?
我本身并不太懂同步原语、线程安全、并行编程这些,所以想请教一下。欢迎指正!
3851 次点击
所在节点    Python
27 条回复
sujin190
2021-10-23 23:24:50 +08:00
设计复杂度啊,大哥,两个都要那就两个都性能底,还开关,想太多了,而且 Python 强大的 C 扩展,谁给你兼容,多线程编程本来就复杂,重新设计解释器干掉 gil 不是啥难事,但是要在通用场景下取得更好性能以及对现有模块和 C 扩展有良好兼容可就难了,而且以 Python 的主要使用场景来看,干不干掉 GIL 其实意义不大,反正 Python 做出的牛逼的东西像 tensorflow 都是 C 或者 C++扩展的本来就不受 GIL 限制,否则有 ironpython 和 jython 你看如何
msg7086
2021-10-24 05:48:21 +08:00
成本。
你来写吗?
如果你不写,那可能别人也不想写,太多工程量了。
而且你都用命令行开关切换了,那不就成运行时判断了吗?
运行时判断会影响性能的,真要做的话还不如分开两套 binary 。

当然上面说的 C 扩展本来就没有 GIL 也是因素之一。
真要做 CPU 密集型操作不如写 C 扩展。
O5oz6z3
2021-10-24 06:07:11 +08:00
@sujin190 #1
@msg7086 #2
关于命令行开关,可能我说得不够清晰。我不了解 CPython ,以下举的例子可能不恰当:打个比方的话就是“单线程模式”用 `Py_Initialize()`,用普通的粗粒度 GIL 。“多线程模式”用 `Py_Initialize_threads_mode()`,采用细粒度的 GIL 优化多线程性能。

更具体的话就是指 docs.python.org/zh-cn/3/faq/library.html#can-t-we-get-rid-of-the-global-interpreter-lock 文档里提到的那个细粒度 GIL 。既然能够实现细粒度 GIL ,那么在命令行启动解释器的时候选择用哪一种 GIL ,看上去应该很容易实现?

至于那些已经存在的 C 扩展,虽然我也不太懂 C 扩展,但我猜如果本来就隐式或显式依赖 GIL ,那么似乎本来就不适合多线程并行?
而且“多线程细粒度 GIL”是可选的,如果不兼容那么回退到原来的粗粒度 GIL 就是了。

虽然我也不知道去掉 GIL 有什么意义,不过也许有利于并行计算?

至于 python 其他没有 GIL 的实现,老实说我没用过,而且看上去版本更新缓慢……
ysc3839
2021-10-24 06:11:10 +08:00
那为什么不做成编译时的开关呢?
O5oz6z3
2021-10-24 06:15:57 +08:00
@msg7086 #2
我的意思就是,如果暂时不考虑成本,这个方案理论上可行吗?
况且细粒度 GIL 似乎(很久)以前有人实现过,参考上面 #3 的链接。

至于你所说的“运行时判断”,如果我没理解错的话,是指每次解释执行字节码指令的时候,判断使用哪种 GIL ?我不是这个意思,我是指上面提到的根据命令行开关(例如`python --threads ...`)调用对应的“入口函数”(`Py_Initialize`/`Py_Initialize_threads`)。

C 扩展这点也参考上面 #3 。虽然 CPU 密集确实应该用 C 扩展来解决,但 C 扩展的缺点是,需要编译(和需要写 C 语言……)。

@ysc3839 #4
python 的编译时开关?这个我不知道是什么……
ysc3839
2021-10-24 06:21:06 +08:00
@O5oz6z3 C 语言的预处理器。
O5oz6z3
2021-10-24 06:33:08 +08:00
@ysc3839 #6
也就是和#2 楼说的一样,不用“命令行开关”,干脆用“编译时开关”,将 python 编译成细粒度 GIL 的可执行文件?
感觉也可行,也就是开关的位置其实不太重要。
那么问题就变成了:“Python 为什么不提供两种 GIL 对应的两套可执行文件?”
msg7086
2021-10-24 06:36:23 +08:00
@O5oz6z3 不考虑成本,火星都能给你送人上去。
你真不考虑成本,那都不用管 GIL 了,直接堆机房堆起来……还纠结什么性能问题,对吧。
这个前提太没有意义了。

而且就算不考虑成本,那也应该先去写 C 扩展。你看那么多年过去了,C 扩展的高性能库一大把,GIL 问题还没彻底解决,这是为什么?当然是因为写 C 扩展比较便宜简单啦……
O5oz6z3
2021-10-24 07:44:30 +08:00
@msg7086 #8
理论可行性应该是成本的前提吧?理论不可行也就不需要考虑成本了……

原来如此,看来多数情况下还是 c 扩展简单粗暴……

看到一篇介绍 wiki.python.org/moin/GlobalInterpreterLock ,看来在目前的版本设计实现细粒度的 GIL 可能还是很有难度和很大工程量。(维护两套代码可能也很麻烦)
0x0208v0
2021-10-24 11:08:16 +08:00
最近 python 出现一个惊艳的 no-gil 设计,想必大家已经知道了。
村网通本村请问楼主是哪篇文章,想学习一下
ErwinCheung
2021-10-24 11:11:09 +08:00
最近 python 出现一个惊艳的 no-gil 设计,想必大家已经知道了。
村网通本村请问楼主是哪篇文章,想学习一下
zglzy
2021-10-24 11:31:10 +08:00
盲猜一下楼主指的是不是这个:
aHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vZG9jdW1lbnQvdS8wL2QvMThDWGhEYjF5Z3hnLVlYTkJKTnpmelpzREZvc0I1ZTZCZm5YTGxlamQ5bDA=
hsfzxjy
2021-10-24 12:14:46 +08:00
我说一个观点,就是在 CPython 漫长的发展过程中 Extension 的接口会发生抽象泄漏,从而制约其底层实现的改变。具体可以看 Hyrum's Law https://www.hyrumslaw.com/

展开来说,一个有很多用户使用的接口,无论其抽象做的多好,用户的使用最终多少会透过这层接口而去依赖背后的具体实现。CPython Extension API 虽然没有暴露太多和 GIL 相关的 API ,但你很难说不存在某些扩展,其正确性依赖于「解释器里有个全局锁」这一事实。就算细粒度锁或去除 GIL 的性能和安全问题解决了,CPython 作为正统及使用最广泛的版本也不会贸然采用。这其中会有很长的验证过程。
kasheemlew
2021-10-24 14:19:17 +08:00
用 Cython 来操作也可,https://juejin.cn/post/7007043202251390984
mattx
2021-10-24 15:07:11 +08:00
sujin190
2021-10-24 15:21:00 +08:00
@O5oz6z3 #3 大哥,这个又不是一个函数调完就完,各种数据结构,各种扩展都要加入支持,你用两个不同初始化方法有个啥用
sujin190
2021-10-24 15:23:38 +08:00
@hsfzxjy #13 不是可能存在,是必然是这样啊,除非你做个扩展完全不用 python 解释器的任何数据结构,否则就必须要用 GIL 保证安全,但是你不用任何 Python 解释器的数据结构,那 Python 也认不了你的扩展啊
2i2Re2PLMaDnghL
2021-10-24 15:55:33 +08:00
@hsfzxjy 其实可以做到避免抽象泄漏的,就是让实现本身不稳定
比如 HTTP 接口,浏览器(几乎?)从未依赖于特定服务端实现
wangyzj
2021-10-25 09:27:11 +08:00
肯定可以实现
就是没有那个必要了
O5oz6z3
2021-10-25 09:43:22 +08:00
@v2exblog @ErwinCheung #10 #11
罚你们重看 /t/808955

@kasheemlew #14
我才发现我把 cython 和 c 扩展搞混了。

@wangyzj #19
我也不知道有没有必要,不过 GIL 好像有 CPU 颠簸之类的其他副作用……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/810078

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX