我正在尝试弄清楚 Python 中的多线程编程。这是我想比较串行和并行速度的简单任务。导入线程导入队列导入时间导入 ma...
我正在尝试弄清楚 Python 中的多线程编程。这是我想比较串行和并行速度的简单任务。
import threading
import Queue
import time
import math
def sinFunc(offset, n):
result = []
for i in range(n):
result.append(math.sin(offset + i * i))
return result
def timeSerial(k, n):
t1 = time.time()
answers = []
for i in range(k):
answers.append(sinFunc(i, n))
t2 = time.time()
print "Serial time elapsed: %f" % (t2-t1)
class Worker(threading.Thread):
def __init__(self, queue, name):
self.__queue = queue
threading.Thread.__init__(self)
self.name = name
def process(self, item):
offset, n = item
self.__queue.put(sinFunc(offset, n))
self.__queue.task_done()
self.__queue.task_done()
def run(self):
while 1:
item = self.__queue.get()
if item is None:
self.__queue.task_done()
break
self.process(item)
def timeParallel(k, n, numThreads):
t1 = time.time()
queue = Queue.Queue(0)
for i in range(k):
queue.put((i, n))
for i in range(numThreads):
queue.put(None)
for i in range(numThreads):
Worker(queue, i).start()
queue.join()
t2 = time.time()
print "Serial time elapsed: %f" % (t2-t1)
if __name__ == '__main__':
n = 100000
k = 100
numThreads = 10
timeSerial(k, n)
timeParallel(k, n, numThreads)
#Serial time elapsed: 2.350883
#Serial time elapsed: 2.843030
有人能向我解释一下发生了什么吗?我习惯使用 C++,使用该模块的类似版本可以看到我们期望的速度提升。
其他答案提到了 GIL 是 cpython 中的问题。但我觉得缺少了一些信息。当您在线程中运行的代码受 CPU 限制时,这会导致性能问题。就您这里的情况而言,在线程中进行许多计算很可能会导致性能急剧下降。
但是,如果你正在做一些更依赖 IO 的事情,比如从网络应用程序中的多个套接字读取数据,或者调用子进程,那么你就可以通过线程来提高性能。上面代码的一个简单示例是向 shell 添加一个非常简单的调用:
import os
def sinFunc(offset, n):
result = []
for i in xrange(n):
result.append(math.sin(offset + i * i))
os.system("echo 'could be a database query' >> /dev/null; sleep .1")
return result
该调用可能确实存在,例如等待文件系统。但您可以看到,在此示例中,线程将开始证明其有益,因为当线程等待 IO 时可以释放 GIL,其他线程将继续处理。即便如此,当更多线程开始因创建和同步它们的开销而变得无用时,仍然存在一个最佳点。
对于 CPU 密集型代码,你可以使用 multiprocessing
摘自文章: http://www.informit.com/articles/article.aspx?p=1850445&seqNum=9
...线程更适合 I/O 密集型应用程序(I/O 释放 GIL,允许更多并发)...
关于线程与进程的类似问题参考:
https://.com/a/1227204/496445
https://.com/a/990436/496445