python中的并行性不正常

时间:2011-12-06 17:01:36

标签: python multithreading google-app-engine python-2.7 python-multithreading

我正在使用python 2.7在gae上开发应用程序,ajax调用从API请求一些数据,单个请求可能需要大约200毫秒,但是当我打开两个浏览器并在非常接近的时间发出两个请求时超过了它的两倍,我已经尝试将所有东西都放在线程中,但它不起作用..(这种情况发生在应用程序在线时,而不仅仅是在开发服务器上)

所以我写了这个简单的测试来看看这是否是python中的问题(如果忙等待),这里是代码和结果:

def work():
    t = datetime.now()
    print threading.currentThread(), t
    i = 0
    while i < 100000000:
        i+=1
    t2 = datetime.now()
    print threading.currentThread(), t2, t2-t

if __name__ == '__main__': 
    print "single threaded:"
    t1 = threading.Thread(target=work)
    t1.start()
    t1.join()

    print "multi threaded:"
    t1 = threading.Thread(target=work)
    t1.start()
    t2 = threading.Thread(target=work)
    t2.start()
    t1.join()
    t2.join()

mac os x,核心i7(4核,8个线程)的结果,python2.7:

single threaded:
<Thread(Thread-1, started 4315942912)> 2011-12-06 15:38:07.763146
<Thread(Thread-1, started 4315942912)> 2011-12-06 15:38:13.091614 0:00:05.328468

multi threaded:
<Thread(Thread-2, started 4315942912)> 2011-12-06 15:38:13.091952
<Thread(Thread-3, started 4323282944)> 2011-12-06 15:38:13.102250
<Thread(Thread-3, started 4323282944)> 2011-12-06 15:38:29.221050 0:00:16.118800
<Thread(Thread-2, started 4315942912)> 2011-12-06 15:38:29.237512 0:00:16.145560

这太令人震惊!!如果单个线程需要5秒才能完成这个..我认为同时启动两个线程将花费相同的时间来完成这两个任务,但它需要几乎三倍的时间...这使得整个线程的想法毫无用处,如按顺序执行它们会更快!

我在这里错过了什么..

3 个答案:

答案 0 :(得分:9)

关于PyCon 2010中此问题的

David Beazley gave a talk。 正如其他人已经说过的那样,对于某些任务,使用特别是多核的线程可能导致性能低于单个线程执行的相同任务。 Beazley发现,这个问题与多个具有"GIL battle"

的核心有关

enter image description here

为避免GIL争用,您可以在单独的进程中运行任务而不是单独的线程,从而获得更好的结果。 multiprocessing模块提供了一种方便的方法,尤其是因为多处理API与线程API非常相似。

import multiprocessing as mp
import datetime as dt
def work():
    t = dt.datetime.now()
    print mp.current_process().name, t
    i = 0
    while i < 100000000:
        i+=1
    t2 = dt.datetime.now()
    print mp.current_process().name, t2, t2-t

if __name__ == '__main__': 
    print "single process:"
    t1 = mp.Process(target=work)
    t1.start()
    t1.join()

    print "multi process:"
    t1 = mp.Process(target=work)
    t1.start()
    t2 = mp.Process(target=work)
    t2.start()
    t1.join()
    t2.join()

产量

single process:
Process-1 2011-12-06 12:34:20.611526
Process-1 2011-12-06 12:34:28.494831 0:00:07.883305
multi process:
Process-3 2011-12-06 12:34:28.497895
Process-2 2011-12-06 12:34:28.503433
Process-2 2011-12-06 12:34:36.458354 0:00:07.954921
Process-3 2011-12-06 12:34:36.546656 0:00:08.048761

PS。正如zeekay在评论中所指出的那样,GIL之战对于CPU限制任务来说是非常严重的。它不应该是IO绑定任务的问题。

答案 1 :(得分:4)

CPython解释器不允许运行多个线程。阅读GIL http://wiki.python.org/moin/GlobalInterpreterLock

因此,在带有线程的CPython中,某些任务无法以高效的方式同时完成。

如果你想在GAE中做并行操作,那么就可以通过单独的请求来启动它们。

此外,您可能需要咨询Python并行wiki http://wiki.python.org/moin/ParallelProcessing

答案 2 :(得分:1)

我会看看时间在哪里。例如,假设服务器每200ms只能回答一个查询。那么你无能为力,你每200ms只会收到一个回复​​,因为这是服务器可以为你提供的。