1. 请看下面的例子:
import time from threading import Thread from multiprocessing import Process from timeit import Timer def countdown(n): while n > 0: n -= 1 def t1(): COUNT=100000000 thread1 = Thread(target=countdown,args=(COUNT,)) thread1.start() thread1.join() # COUNT = 100000000 # 100 million # countdown(COUNT) def t2(): COUNT=100000000 thread1 = Thread(target=countdown,args=(COUNT//2,)) thread2 = Thread(target=countdown,args=(COUNT//2,)) thread1.start(); thread2.start() thread1.join(); thread2.join() def t3(): COUNT=100000000 p1 = Process(target=countdown,args=(COUNT//2,)) p2 = Process(target=countdown,args=(COUNT//2,)) p1.start(); p2.start() p1.join(); p2.join() if __name__ == '__main__': t = Timer(t1) print 'countdown in one thread:',t.timeit(1) t = Timer(t2) print 'countdown use two thread:',t.timeit(1) t = Timer(t3) print 'countdown use two Process',t.timeit(1)
2. 在我的四核CPU上,用Python 2.7.6运行时得以下面的输出:
countdown in one thread: 10.5507714241 countdown use two thread: 26.195196047 countdown use two Process 5.81643362842
3. 利用双线程进行计算比单线程慢了两倍还多!!
4. 由此我们可以得到结论:
在多核CPU上,写Python代码时应该尽量避免使用Thread,用Process来替代线程。
(注,上面这句话是错误的,详见《Python GIL 系列之通过设置进程运行的CPU来提高Python程序的性能》一文)
但是多进程情况下数据的共享又是一个大问题。
5. 这种情况在Python3.2上引入新的GIL后已经有了很大的改善,但是新的GIL又会对I/O操作的响应速度产生影响,真的是一波未平,一波又起啊。
6. 更全面的对于GIL的讲解请看David Beazley 2010年在PyCon的演讲ppt
http://www.dabeaz.com/python/UnderstandingGIL.pdf
7. 我也是太疏漏寡闻了,只到最近才在网上看到这个迄今为止对GIL讲解最全面的文章。
8. 看过这篇文章之后,我不由的感慨一下:GIL是Python的阿喀琉斯之踵么?