顺序代码(seq.py
),
import time
def countDown(n):
while n > 0:
n -= 1
n = 50000000
start = time.time()
countDown(n)
end = time.time()
print(end-start)
是,
$ python3.6 seq.py
4.209718227386475
$ python3.6 seq.py
4.007786750793457
$ python3.6 seq.py
4.0265843868255615
$
线程版本(usingThreads.py
),
from threading import Thread
import time
def countDown(n):
while n > 0:
n -= 1
n = 50000000
t1 = Thread(target=countDown, args=(n//2,))
t1.daemon = True
t2 = Thread(target=countDown, args=(n//2,))
t2.daemon = True
start = time.time()
t1.start()
t2.start()
t1.join()
t2.join()
end = time.time()
print(end-start)
是,
$ python3.6 usingThreads.py
4.1083903312683105
$ python3.6 usingThreads.py
4.093154668807983
$ python3.6 usingThreads.py
4.092989921569824
$ python3.6 usingThreads.py
4.116031885147095
$
$ nproc
4
$
Python解释器不应允许CPU绑定线程释放GIL。
期望usingThreads.py
的执行时间超过seq.py
,因为,
1)任何一个线程一次都在执行,尽管有4个核心
2)尝试通过thread2从thread1获取GIL失败所花费的时间(反之亦然)应该会延迟执行。
修改
使用n=500000000
$ python3.6 seq.py
40.22602105140686
$ python3.6 seq.py
40.510098457336426
$ python3.6 seq.py
40.04688620567322
$
$ python3.6 usingThreads.py
40.91394829750061
$ python3.6 usingThreads.py
42.30081081390381
$ python3.6 usingThreads.py
41.328694581985474
问题:
为什么usingThread.py
的效果优于seq.py
?
答案 0 :(得分:0)
这两个版本的代码执行的工作量相同,因此花费的时间几乎相同(均为50000000次)。
gil使得它们不会并行运行(因此线程版本不会更快)但是上下文切换的开销相对较小,所以你得到了几乎相同的结果。
这里有一个解释http://www.dabeaz.com/python/UnderstandingGIL.pdf
他正在使用与你相同的例子,在这个演示中,当他使用一台cpus超过1的计算机时,他得到了一个较慢的线程版本,他解释得很好,当你使用超过1个cpu时,你会得到更多的开销(更多尝试上下文切换)会使你的程序变慢