分享一个对 Python GIL 的深入研究演讲

2015-05-10 00:09:44 +08:00
 MonkLuf

为了底层管理方便,Python多线程执行时,同一时刻只能有一个线程真正在执行,这样非常影响Python多线程的并发能力。

举个例子,计算从1到1亿的所有自然数之和,用一个线程算和用两个线程算的结果:

单线程:

def xsum(a, b):
    s = 0
    while a < b:
        s += a
        a += 1
    print s
N = 100000001

xsum(1, N)

多线程:

from threading import Thread

def xsum(a, b):
    s = 0
    while a < b:
        s += a
        a += 1
    print s
N = 100000001

p1 = Thread(target=xsum, args=(1, N/2))
p2 = Thread(target=xsum, args=(N/2, N))
p1.start(); p2.start()
p1.join(); p2.join()

这两个在我的机器上的计算结果是:

$ time python single.py 
5000000050000000

real    0m5.910s
user    0m5.899s
sys 0m0.009s
$ time python par.py
3750000075000000
1249999975000000

real    0m8.661s
user    0m7.638s
sys 0m5.761s

我的机器,Core i7, 4核。多线程并发比单线程慢了46%!

这是因为GIL(Global Interpreter Lock)的存在。Python的程序在线程在执行时需要获取GIL锁才能继续,所以在同一时刻只能有一个线程在真正执行。一方面线程不能利用多核,另一方面线程竞争锁带来的抖动给实际的执行带来了很大的负载。这直接导致线程的性能非常差。

David Beazley,在PyCON'2010上做了一个精彩的演讲,深入浅出的讲解了Python GIL的机制。

网址: http://www.dabeaz.com/GIL/ ,其中那个PDF非常值得一看。

今天看完后非常震惊,跟大家分享一下 :)

2822 次点击
所在节点    分享创造
5 条回复
Septembers
2015-05-10 00:12:15 +08:00
from threading import Thread
换成
from multiprocessing import Process as Thread
其他原封不动
MonkLuf
2015-05-10 00:17:31 +08:00
@Septembers 你想表达的意思是?
decken
2015-05-10 00:29:14 +08:00
@MonkLuf 使用多进程和多线程一样方便,没有GIL限制
secondwtq
2015-05-10 10:35:51 +08:00
Python, Ruby, Lua, JavaScript 等脚本语言貌似没有一个有多线程并行的支持的(在 JVM,.Net 上面实现的另说)... 感觉在脚本语言的基础上面这个确实不太好搞
MonkLuf
2015-05-10 13:11:21 +08:00
@decken 是的,线程和进程各有使用场景,我这里想表达的是Python多线程方面的局限性。咱们不冲突。

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

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

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

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

© 2021 V2EX