Python:为什么线程函数比非线程慢

时间:2014-04-28 15:22:35

标签: python multithreading

您好我正在尝试计算前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 个答案:

答案 0 :(得分:11)

来自:https://wiki.python.org/moin/GlobalInterpreterLock

  

在CPython中,全局解释器锁或GIL是一个互斥锁,它可以防止多个本机线程一次执行Python字节码。这种锁是必要的,主要是因为CPython的内存管理不是线程安全的。 (但是,由于存在GIL,其他功能已经增长,取决于它所强制执行的保证。)

这意味着:由于这是CPU密集型的,并且python不是线程安全的,因此它不允许您在同一进程中一次运行多个字节码。所以,你的线程互相交替,转换开销就是额外的时间。

答案 1 :(得分: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是一个使用a支持产生进程的包   API类似于线程模块。多处理包   提供本地和远程并发,有效地侧面步进   全局解释器锁通过使用子进程而不是线程。   因此,多处理模块允许程序员完全   利用给定计算机上的多个处理器。它可以在Unix上运行   和Windows。