import time
import threading
import multiprocessing
def fn():
'''since all 3 functions were identical you can just use one ...'''
x = 0
while x < 100000000:
x += 1
def TEST_THREADS():
new_thread1 = threading.Thread(target = fn , args = ())
new_thread2 = threading.Thread(target = fn, args = ())
new_thread1.start()
new_thread2.start()
new_thread1.join()
new_thread2.join()
def TEST_NORMAL():
fn()
fn()
def TEST_MULTIPROCESSING():
new_thread1 = multiprocessing.Process(target = fn , args = ())
new_thread2 = multiprocessing.Process(target = fn, args = ())
new_thread1.start()
new_thread2.start()
new_thread1.join()
new_thread2.join()
if __name__ == "__main__":
'''It is very important to use name == __main__ guard code with threads and multiprocessing'''
import timeit
print ("Time to Run 1x: %0.2fs"%(timeit.timeit(fn,number=1),))
print ("NORMAL:%0.2fs"%(timeit.timeit(TEST_NORMAL,number=1),))
print ("Threaded: %0.2fs"%(timeit.timeit(TEST_THREADS,number=1),))
print ("Multiprocessing: %0.2fs"% (timeit.timeit(TEST_MULTIPROCESSING,number=1),))
我发现了有关GIL和线程的有趣演示: http://www.dabeaz.com/python/NewGIL.pdf 所以我写了类似的代码,但是得到了奇怪的结果:
Time to Run 1x: 11.60s
NORMAL:23.15s
Threaded: 23.43s
Multiprocessing: 1.19s
如您所见,线程方法的运行速度比普通方法快一倍或相等(0.28秒不是太多)。 我发现了一些文章和类似的问题,但是到处都是演示文稿,结果却很慢。
我做错了什么还是新的Python版本改进了GIL?
但是,多处理也变得疯狂,并且工作速度比其他方法快20倍!可以吗
答案 0 :(得分:1)
在现代Python中,GIL并没有以前那么糟糕(以前,您可能希望CPU绑定的线程代码运行得明显慢一些),因此您的观察结果大致上就是您期望的。
从个人经验来看,CPython 2.7上的许多CPU绑定线程可以使用接近两个CPU内核,并且完成的工作量不到内核工作量的75%。自从他们rewrote the GIL in CPython 3.2以来,那笔开销基本上消失了;您仍然没有从线程中获得任何收益,但是最终使用了1-1.1内核的计算能力,并完成了95-100%的内核工作。基本上,GIL不再有意义地降低代码速度,但是它仍然可以防止您受益于使用不基于第三方GIL释放扩展程序(例如numpy
)的CPU绑定代码进行线程化。