2

我有 2 个简单的函数(在一个范围内循环),它们可以单独运行而没有任何依赖关系。我正在尝试使用 Python 多处理模块和多线程模块运行这 2 个函数。

当我比较输出时,我看到多进程应用程序比多线程模块多花 1 秒..

我读到多线程效率不高,因为全局解释器锁......

基于上述陈述 -
1.如果两个进程之间没有依赖关系,最好使用多进程吗?
2.如何计算我可以在我的机器上运行的进程/线程数以获得最大效率..
3.还有,有没有办法通过使用多线程来计算程序的效率......

多线程模块...

from multiprocessing import Process

import thread
import platform

import os
import time
import threading
class Thread1(threading.Thread):
    def __init__(self,threadindicator):
        threading.Thread.__init__(self)
        self.threadind = threadindicator

    def run(self):
        starttime = time.time() 
        if self.threadind == 'A':
            process1()
        else:
            process2()
        endtime = time.time()
        print 'Thread 1 complete : Time Taken = ', endtime - starttime

def process1():
    starttime = time.time() 
    for i in range(100000):
        for j in range(10000):
            pass        
    endtime = time.time() 

def process2():
    for i in range(1000):
        for j in range(1000):
            pass

def main():

    print 'Main Thread'
    starttime = time.time()
    thread1 = Thread1('A')
    thread2 = Thread1('B')
    thread1.start()
    thread2.start()
    threads = []
    threads.append(thread1)
    threads.append(thread2)

    for t in threads:
        t.join()
    endtime = time.time()
    print 'Main Thread Complete , Total Time Taken = ', endtime - starttime


if __name__ == '__main__':
    main()

多进程模块

from multiprocessing import Process
import platform

import os
import time

def process1():
#     print 'process_1 processor =',platform.processor()
    starttime = time.time() 
    for i in range(100000):
        for j in range(10000):
            pass
    endtime = time.time()
    print 'Process 1 complete : Time Taken = ', endtime - starttime 


def process2():
#     print 'process_2 processor =',platform.processor()
    starttime = time.time()
    for i in range(1000):
        for j in range(1000):
            pass
    endtime = time.time()
    print 'Process 2 complete : Time Taken = ', endtime - starttime

def main():
    print 'Main Process start'
    starttime = time.time()
    processlist = []

    p1 = Process(target=process1)
    p1.start()
    processlist.append(p1)

    p2 = Process(target = process2)
    p2.start()
    processlist.append(p2)

    for i in processlist:
        i.join()
    endtime = time.time()
    print 'Main Process Complete - Total time taken = ', endtime - starttime

if __name__ == '__main__':
    main()
4

1 回答 1

7

如果你的机器上有两个可用的 CPU,你有两个不需要通信的进程,并且你想同时使用它们来使你的程序更快,你应该使用 multiprocessing 模块,而不是 threading 模块。

全局解释器锁 (GIL) 可防止 Python 解释器通过使用多个线程来有效利用多个 CPU,因为一次只能有一个线程执行 Python 字节码。因此,多线程不会提高应用程序的整体运行时间,除非您有numpy长时间阻塞的调用(例如等待 IO)或释放 GIL(例如,会为一些昂贵的调用执行此操作)。但是,多处理库会创建单独的子进程,因此会创建多个解释器副本,因此它可以有效地利用多个 CPU。

但是,在您给出的示例中,您有一个进程完成得非常快(在我的机器上不到 0.1 秒),而另一个进程大约需要 18 秒才能完成。确切的数字可能因您的硬件而异。在这种情况下,几乎所有的工作都发生在一个进程中,所以无论如何你实际上只使用一个 CPU。在这种情况下,生成进程与线程的开销增加可能会导致基于进程的版本变慢。

如果您让两个进程都执行 18 秒的嵌套循环,您应该会看到多处理代码运行得更快(假设您的机器实际上有多个 CPU)。在我的机器上,我看到多处理代码在 18.5 秒内完成,多线程代码在 71.5 秒内完成。我不确定为什么多线程花费的时间超过大约 36 秒,但我的猜测是 GIL 会导致某种线程争用问题,这会减慢两个线程的执行速度。

至于您的第二个问题,假设系统上没有其他负载,您应该使用与系统上 CPU 数量相等的进程数。您可以通过lscpu在 Linux 系统、sysctl hw.ncpuMac 系统或dxdiag从 Windows 上的“运行”对话框运行来发现这一点(可能还有其他方法,但我总是这样做)。

对于第三个问题,确定从额外进程中获得多少效率的最简单方法就是测量程序的总运行时间,time.time()按您的原样使用,或者time在 Linux 中使用实用程序(例如time python myprog.py)。理想的加速应该等于您正在使用的进程数,因此在 4 个 CPU 上运行的 4 进程程序应该最多比具有 1 个进程的同一程序快 4 倍,假设您从额外进程中获得最大收益。如果其他流程对您的帮助不大,那么它将不到 4 倍。

于 2013-10-11T21:22:05.920 回答