尽早尝试删除Python GIL会导致性能下降:为什么?


13

Python创造者Guido Van Rossum的这篇文章提到了从Python中删除GIL的早期尝试:

以前曾尝试过这种方法,但结果令人失望,这就是为什么我自己不愿意为此付出很多努力的原因。在1999年,Greg Stein(与Mark Hammond合作)生产了Python的一个fork(我相信是1.5),它删除了GIL,并用所有可变数据结构上的细粒度锁代替了它。他还提交了补丁,删除了许多我对全局可变数据结构的依赖。但是,在进行基准测试后,结果表明,即使在具有最快锁定原语的平台(当时为Windows)上,单线程执行的速度也降低了近两倍,这意味着在两个CPU上,您可以多做一点工作在没有GIL的情况下比在具有GIL的单个CPU上完成。这还不够,格雷格的补丁消失了。(请参阅格雷格关于演出的文章。)

我很难与实际结果争论,但我真的很奇怪为什么会这样。大概,从CPython中删除GIL如此困难的主要原因是由于引用计数内存管理系统。一个典型的Python程序将调用Py_INCREFPy_DECREF数千或数百万次,使其成为一个关键的竞争点,如果我们要环绕它锁。

但是,我不明白为什么添加原子基元会降低单个线程程序的速度。假设我们刚刚修改了CPython,以便每个Python对象中的refcount变量是一个原子基元。然后,当我们需要增加引用计数时,我们只是执行原子增加(获取和添加指令)。这将使Python参考计数线程安全,并且在单线程应用程序上不应有任何性能损失,因为不会发生锁争用。

但是,a,许多比我聪明的人都尝试过并且失败了,所以显然我在这里缺少任何东西。我看这个问题的方式有什么问题?


1
请注意,refcount操作将不是唯一需要同步的地方。引用中提到“所有可变数据结构上的细粒度锁”,我认为每个列表和字典对象至少包括一个互斥锁。另外,我不认为原子整数运算不像非原子等效运算那样高效,无论是否存在争用,您是否有此资料的来源?

很简单,因为原子操作要比非原子操作慢。仅仅因为它是一条指令,并不意味着它在幕后是微不足道的。见这对一些讨论
莫兹

Answers:


9

我不熟悉Greg Stein Python前叉,所以如果您愿意,可以将此比较作为推测性的历史类比。但这恰好是许多基础架构代码库从单线程实现过渡到多线程实现的历史经验。

实际上,我在1990年代研究的每个Unix实现-AIX,DEC OSF / 1,DG / UX,DYNIX,HP-UX,IRIX,Solaris,SVR4和SVR4 MP都经过了这种“更细粒度的锁定-现在变慢了!!” 问题。我遵循的DBMS(DB2,Ingres,Informix,Oracle和Sybase)也都通过了。

我听说“当我们运行单线程时,这些更改不会使我们放慢速度”。它永远不会那样解决。有条件检查“我们是否正在运行多线程?”这一简单动作。增加了实际的开销,尤其是在高度流水线化的CPU上。为了确保共享数据结构的完整性必须经常调用原子操作和偶尔的自旋锁,而且它们非常慢。第一代锁定/同步原语也很慢。最终,大多数实现团队会根据不同地方需要多少互锁保护,以各种“强度”添加几类原语。然后,他们意识到最初在锁定原语中使用的位置并不是真正正确的地方,因此他们不得不分析,设计发现的瓶颈,并系统地轮播。这些关键点中的一些最终得到了操作系统或硬件的加速,但是整个发展历时3-5年,几乎是最小的。同时,MP或MT版本在性能方面表现不佳。

否则,精打细算的开发团队则认为,这种减速基本上是生活中持久的,棘手的事实。例如,IBM在竞争后至少5年内拒绝启用SMP的AIX,并坚持认为单线程仅是更好。Sybase使用了一些相同的参数。一些团队最终出现的唯一原因是单线程性能不再能够在CPU级别上得到合理提高。他们被迫采用MP / MT或接受竞争日益激烈的产品。

活动并发是HARD。而且是骗人的。每个人都冲进去,以为“这不会那么糟”。然后他们撞上了流沙,不得不踩了下去。我已经看到至少有十几个名牌,资金雄厚的精明团队会发生这种情况。通常,选择多线程以使MP / MT产品“从性能角度回到其应有的位置”似乎至少需要五年。甚至在转变后的十年,大多数公司仍在有意义地提高MP / MT的效率/可扩展性。

因此,我的猜测是,在没有GvR的认可和支持的情况下,没有人对Python及其GIL承担长期的苦难。即使他们今天要这样做,在您说“哇!我们真的过了MT峰!”之前,它仍然是Python 4.x时间表。

也许有些魔术将Python及其运行时与所有其他有状态基础架构软件(以前已经使用过的所有语言运行时,操作系统,事务监控器和数据库管理器)区分开了。但是,如果是这样,它是独一无二的或几乎是独一无二的。其他人要删除等效于GIL的人,都花了五年多的努力,坚定的努力和投入,才能从MT-not变成MT-hot。


2
+1与相当小的开发人员团队一起花了多时间处理Tcl。在此之前,该代码是MT安全的,但存在讨厌的性能问题,主要是在内存管理中(我怀疑这是动态语言的热门区域)。除了最一般的术语外,这种经验并没有真正延续到Python上。两种语言具有完全不同的线程模型。只是……期待一个口号,期待怪异的错误……
Donal Fellows 2014年

-1

另一个疯狂的假设:在1999年,Linux和其他Unices没有像现在这样与futex(2)http://en.wikipedia.org/wiki/Futex)进行高效的同步。这些在2002年左右出现(并在2004年左右合并为2.6)。

由于所有内置数据结构都必须同步,因此锁定成本很高。Ӎσᶎ已经指出,原子操作不一定便宜。


1
您有什么要备份的吗?还是这几乎是猜测?

1
GvR报价描述了“在具有最快锁定原语的平台上(当时是Windows)的性能”,因此Linux上的慢速锁定无关紧要。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.