锁定与性能的Python成本,(多线程是否有意义?)

时间:2012-08-15 08:53:03

标签: python multithreading performance gil

我正在开发一个项目,其中我的代码的吞吐量非常重要,经过一些考虑我选择使我的程序成为线程。

主线程和子线程都添加和删除两个共享词典。 考虑到python中锁定的性能,我一直在寻找关于某些输入的互联网,这是一个缓慢的操作等等。

所以我得到的是因为python实际上根本没有线程(想想GIL只能在一个核心上运行)如果我需要在我的应用程序中获得高性能我是否有任何东西可以通过使其成为线程来获胜处理IO?

修改

实际问题是(经过深刻的评论后)

多线程在python中是否有意义,因为有GIL?

2 个答案:

答案 0 :(得分:9)

IMO,锁定解决方案对性能产生很大影响,主要是当多线程真正等待它时。

获取和发布无竞争锁定的成本应该是微不足道的。

This thread显示了对此的测试。

  

好的,这是获取和释放无竞争锁的成本   在Linux下,使用Python 3.2:

$ python3 -m timeit \
  -s "from threading import Lock; l=Lock(); a=l.acquire; r=l.release" \
  "a(); r()"

10000000 loops, best of 3: 0.127 usec per loop
     

这是调用虚拟Python函数的代价:

$ python3 -m timeit -s "def a(): pass" "a(); a()"

1000000 loops, best of 3: 0.221 usec per loop
     

这是调用一个简单的C函数(返回的成本)   假单身人士):

$ python3 -m timeit -s "a=bool" "a(); a()"

10000000 loops, best of 3: 0.164 usec per loop
     

另外,请注意,实际上使用锁作为上下文管理器   你可能想象的更慢,而不是更快:

$ python3 -m timeit -s "from threading import Lock; l=Lock()" \
  "with l: pass"

1000000 loops, best of 3: 0.242 usec per loop
     

至少在Linux下,似乎没有太大的空间   至少可以说,锁定性能得到了改善。

     

PS:RLock现在和Lock一样快:

$ python3 -m timeit \
  -s "from threading import RLock; l=RLock(); a=l.acquire; r=l.release" \
  "a(); r()"

10000000 loops, best of 3: 0.114 usec per loop

答案 1 :(得分:4)

首先,锁定任何语言都是性能瓶颈。尽可能减少锁定;例如,不要使用共享目录,而是创建一个树,让每个线程在该树的不同分支中工作。

由于您将进行大量I / O操作,因此您的性能问题将存在,并且线程不一定会改善问题。首先研究事件驱动的体系结构:

GIL不太可能是你的问题;例如,每当线程进入C代码时(几乎可以肯定在任何I / O调用期间),它都会被释放。如果 成为瓶颈,请转到多个流程。例如,在我管理的大型Intranet集群中,我们运行每2个线程中的6个进程以充分利用所有CPU核心(其中2个进程负载非常轻)。

如果您认为需要多个进程,请使用multiprocessing module或轻松启动服务器的多个实例(每个实例都在另一个端口上侦听),并使用负载均衡器(如haproxy)将流量引导至每个服务器。