代码之家  ›  专栏  ›  技术社区  ›  Kurt

Linux上使用taskset的多核系统上的Python全局解释器锁(GIL)解决方案?

  •  18
  • Kurt  · 技术社区  · 17 年前

    http://blip.tv/file/2232410 .

    既然GIL限制我们基本上只在一个CPU上执行Python程序,我的想法是,为什么不接受这一点,简单地使用Linux上的taskset来设置程序与系统上某个核心/CPU的关联性(特别是在多核系统上运行多个Python应用程序的情况下)?

    因此,最终我的问题是:有没有人尝试过在Linux上将taskset与Python应用程序一起使用(特别是在Linux系统上运行多个应用程序时,以便多个内核可以与绑定到特定内核的一两个Python应用程序一起使用),如果有,结果如何?值得做吗?它是否会使某些工作负载变得更糟?我计划这样做并测试它(基本上看程序是否需要更多或更少的时间运行),但我很想听听其他人对你的体验。

    另外:David Beazley(在链接视频中发表演讲的人)指出,一些C/C++扩展手动释放GIL锁,并且这些扩展是否针对多核(即科学或数字数据分析等)进行了优化然后,扩展将被有效地削弱,因为它仅限于一个内核(因此可能会显著降低您的程序的速度),而不是在数字运算中获得多核的好处。另一方面,如果您不使用这样的扩展

    我不使用多处理模块的原因是(在本例中)程序的一部分严重受限于网络I/O(HTTP请求)因此,拥有一个工作线程池是一个很好的方法,可以从一个盒子中挤出性能,因为一个线程发出HTTP请求,然后等待I/O放弃GIL,而另一个线程可以完成它的任务,因此,程序的这一部分可以轻松地运行100多个线程,而不会对CPU造成太大的损害,并让我实际使用可用的网络带宽。至于stacklesspython/etc,我对重写程序或替换Python堆栈不太感兴趣(可用性也是一个问题)。

    7 回复  |  直到 14 年前
        1
  •  9
  •   ynimous    17 年前

    另一个解决办法是: http://docs.python.org/library/multiprocessing.html

    注1:这是 Python语言的局限性,但CPython实现的局限性。

    注2:关于亲和性,您的操作系统本身应该没有问题。

        2
  •  7
  •   Van Gale    17 年前

    我从未听说有人使用taskset来提高Python的性能。这并不意味着在你的案例中不可能发生,但一定要公布你的结果,这样其他人就可以批评你的基准测试方法并提供验证。

    但就我个人而言,我会使用消息队列将I/O线程与CPU绑定线程分离。这样,您的前端现在完全是网络I/O绑定的(一些具有HTTP接口,一些具有消息队列接口),非常适合您的线程情况。然后,CPU密集型进程可以使用多处理,也可以是等待工作到达消息队列的单个进程。

    eventlets 因为,即使它们对性能没有帮助,它们也应该提高可伸缩性。您的后端现在已经可以扩展,因为您可以根据需要在任意数量的机器+CPU上运行消息队列。

        3
  •  3
  •   John Conde    14 年前
        4
  •  1
  •   wr.    17 年前

    多年来,我发现以下经验法则已经足够了:如果工作线程依赖于某个共享状态,那么我会为每个核心使用一个多处理进程(CPU绑定),为每个核心使用一个固定的工作线程池(I/O绑定)。操作系统将负责将不同的Python进程分配给内核。

        5
  •  1
  •   Merijn    17 年前

    Python GIL是每个Python解释器的。这意味着,在进行多处理时,避免出现问题的唯一方法是启动多个解释器(即使用单独的进程而不是线程进行并发),然后使用其他IPC原语在进程之间进行通信(如套接字)。也就是说,当使用线程阻止I/O调用时,GIL不是问题。

    前面提到的GIL的主要问题是不能同时执行两个不同的python代码线程。阻塞I/O调用上的线程阻塞被阻塞,因此不会执行python代码。这意味着它没有阻塞GIL。如果在单独的python线程中有两个CPU密集型任务,那么GIL将终止python中的多处理(如前所述,只有CPython实现)。因为GIL阻止CPU#1执行一个python线程,而CPU#0正忙于执行另一个python线程。

        6
  •  1
  •   nobody nobody    17 年前

    在GIL从Python中删除之前,可以使用co例程代替线程。据我所知,这一战略已经由两家成功的初创公司实施,至少在一个案例中使用了Greenlet。

        7
  •  0
  •   Leo Pepe    14 年前

    您可以使用多处理模块,它不是为每个任务创建线程,而是创建另一个cpython compier进程来解释您的代码。 这将使您的应用程序能够利用多核系统。 我在这种方法中看到的唯一问题是,通过在内存上创建一个完整的新进程堆栈,您将有相当大的开销。( http://en.wikipedia.org/wiki/Thread_(computing)#How_threads_differ_from_processes )

    Python多处理模块: http://docs.python.org/dev/library/multiprocessing.html

    “我不使用多处理模块的原因是(在本例中)程序的一部分受到严重的网络I/O限制(HTTP请求),因此拥有一个工作线程池是一个很好的方法来压缩性能…”

    关于这一点,我想你也可以有一个流程池: http://docs.python.org/dev/library/multiprocessing.html#using-a-pool-of-workers

    狮子座

    推荐文章