Python:为何线程函数比非线程慢
你好,我正在尝试计算前10000个质数。
我先是用单线程的方式计算,然后再把计算分成1到5000和5001到10000两部分。我原本以为使用多线程会让速度明显变快,但结果却是这样的:
--------Results--------
Non threaded Duration: 0.012244000000000005 seconds
Threaded Duration: 0.012839000000000017 seconds
实际上,没什么太大的区别,反而是多线程的函数稍微慢了一点。
这是怎么回事呢?
这是我的代码:
import math
from threading import Thread
def nonThreaded():
primeNtoM(1,10000)
def threaded():
t1 = Thread(target=primeNtoM, args=(1,5000))
t2 = Thread(target=primeNtoM, args=(5001,10000))
t1.start()
t2.start()
t1.join()
t2.join()
def is_prime(n):
if n % 2 == 0 and n > 2:
return False
for i in range(3, int(math.sqrt(n)) + 1, 2):
if n % i == 0:
return False
return True
def primeNtoM(n,m):
L = list()
if (n > m):
print("n should be smaller than m")
return
for i in range(n,m):
if(is_prime(i)):
L.append(i)
if __name__ == '__main__':
import time
print("--------Nonthreaded calculation--------")
nTstart_time = time.clock()
nonThreaded()
nonThreadedTime = time.clock() - nTstart_time
print("--------Threaded calculation--------")
Tstart_time = time.clock()
threaded()
threadedTime = time.clock() - Tstart_time
print("--------Results--------")
print ("Non threaded Duration: ",nonThreadedTime, "seconds")
print ("Threaded Duration: ",threadedTime, "seconds")
2 个回答
4
你可以使用 multiprocessing 模块,它的效果如下:
('Non threaded Duration: ', 0.016599999999999997, 'seconds')
('Threaded Duration: ', 0.007172000000000005, 'seconds')
...只需对你的代码做这些小改动(把'Thread'改成'Process'):
import math
#from threading import Thread
from multiprocessing import Process
def nonThreaded():
primeNtoM(1,10000)
def threaded():
#t1 = Thread(target=primeNtoM, args=(1,5000))
#t2 = Thread(target=primeNtoM, args=(5001,10000))
t1 = Process(target=primeNtoM, args=(1,5000))
t2 = Process(target=primeNtoM, args=(5001,10000))
t1.start()
t2.start()
t1.join()
t2.join()
通过创建真正的操作系统进程,而不是使用线程,你就能解决@Luis Masuelli提到的GIL问题。
multiprocessing 是一个支持创建进程的工具包,它的使用方式和线程模块类似。这个包可以在本地和远程同时运行,从而有效地绕过了全局解释器锁(GIL),因为它使用的是子进程而不是线程。这样,multiprocessing 模块就能让程序员充分利用机器上的多个处理器。它可以在Unix和Windows系统上运行。
12
来源: https://wiki.python.org/moin/GlobalInterpreterLock
在CPython中,全局解释器锁(GIL)是一种互斥锁,它阻止多个本地线程同时执行Python字节码。这个锁的存在主要是因为CPython的内存管理不是线程安全的。(不过,由于GIL的存在,其他一些功能也开始依赖于它提供的保证。)
这意味着:因为Python在处理CPU密集型任务时不是线程安全的,所以它不允许在同一个进程中同时运行多个字节码。因此,你的线程会交替执行,而这种切换的开销就是你额外花费的时间。