Python队列 - 线程绑定到单个核心
我写了一个Python脚本,主要做了以下几件事:
1. 提交搜索请求
2. 等待结果
3. 解析返回的结果(XML格式)
我使用了线程和队列模块来并行处理这些任务(设置了5个工作线程)。
在提交搜索请求的部分效果很好,因为我可以同时提交多个搜索任务,并在结果到达时处理它们。
不过,当处理XML数据(这个过程对CPU要求比较高)时,似乎所有的线程都被绑定在同一个核心上,这就造成了性能问题。
有没有人遇到过这个问题?我是不是在理解上有什么遗漏?
另外,我在考虑是否可以设置两个独立的工作队列,一个专门用来提交请求,另一个用来解析XML。目前的做法是一个工作线程同时处理这两项任务。我不太确定这样做是否会有好处。如果有人能提供帮助,我将非常感激。
以下是代码:(去掉了保密数据)
def addWork(source_list):
for item in source_list:
#print "adding: '%s'"%(item)
work_queue.put(item)
def doWork(thread_id):
while 1:
try:
gw = work_queue.get(block=False)
except Queue.Empty:
#print "thread '%d' is terminating..."%(thread_id)
sys.exit() # no more work in the queue for this thread, die quietly
##Here is where i make the call to the REST API
##Here is were i wait for the results
##Here is where i parse the XML results and dump the data into a "global" dict
#MAIN
producer_thread = Thread(target=addWork, args=(sources,))
producer_thread.start() # start the thread (ie call the target/function)
producer_thread.join() # wait for thread/target function to terminate(block)
#start the consumers
for i in range(5):
consumer_thread = Thread(target=doWork, args=(i,))
consumer_thread.start()
thread_list.append(consumer_thread)
for thread in thread_list:
thread.join()
2 个回答
在使用CPython的时候,你的线程其实不会在两个不同的核心上同时运行。你可以查一下全局解释器锁(GIL)的相关信息。
简单来说,GIL就像一个保护锁,确保在执行解释器的代码时,不会有两个线程同时在计算。因此,线程不能并行工作。不过,如果是处理输入输出(I/O)任务,线程就能正常工作,因为这些任务会被阻塞。
补充说明:如果你想充分利用多个核心,就需要使用多个进程。关于这个话题有很多文章,我记得有一篇特别好,但现在找不到了 =/。
正如Nathon所建议的,你可以使用多进程模块。还有一些工具可以帮助你在进程之间共享对象(可以看看POSH,Python对象共享)。
这是因为CPython处理线程的方式造成的副作用。网上对此有很多讨论(可以搜索一下GIL),但解决办法是使用multiprocessing
模块,而不是threading
。Multiprocessing的接口和线程模块差不多(还有同步结构,所以你仍然可以使用队列)。它的特点是给每个线程分配一个完整的进程,这样就避免了GIL和强制串行处理并行任务的问题。