如何在执行许多I / O绑定操作时最大限度地提高Python的性能?

时间:2010-06-04 03:46:37

标签: python

我有一种情况,我正在下载大量文件。现在一切都在一个主要的Python线程上运行,每隔几分钟下载多达3000个文件。问题是这样做的时间太长了。我意识到Python没有真正的多线程,但有没有更好的方法呢?我正在考虑启动多个线程,因为I / O绑定操作不应该要求访问全局解释器锁,但也许我误解了这个概念。

4 个答案:

答案 0 :(得分:16)

多线程对于加速网络上的I / O的特定目的来说很好(尽管异步编程可以提供更高的性能)。 CPython的多线程非常“真实”(本机操作系统线程) - 您可能正在考虑的是GIL,它是阻止不同线程同时运行Python代码的全局解释器锁。但所有I / O原语在等待系统调用完成时放弃GIL ,因此GIL与与I / O性能无关

对于异步编程,最强大的框架是twisted,但是如果你从未进行过这样的编程,可能需要一段时间才能掌握它。通过使用线程池可以更简单地获得额外的I / O性能。

答案 1 :(得分:5)

总是可以看一下multiprocessing

答案 2 :(得分:3)

  

有更好的方法吗?

  

我在考虑从I / O绑定操作

启动多个线程

别。

在操作系统级别,进程中的所有线程共享一组有限的I / O资源。

如果你想要真正的速度,那就像平台所容许的那样产生许多重量级的操作系统进程。操作系统非常非常适合在流程之间平衡I / O工作负载。让操作系统对此进行排序。

人们会说产生3000个过程是不好的,他们是对的。你可能只希望一次产生几百个。

真正想要的是以下内容。

  1. 一个共享消息队列,其中3000个URI排队。

  2. 几百名工人都在队列中阅读。

    每个工作人员从队列中获取一个URI并获取该文件。

  3. 工人可以继续跑步。当队列空了,他们就会坐在那里,等待工作。

    “每隔几分钟”您将3000个URI转储到队列中,以使工作人员开始工作。

    这会占用处理器上的每个资源,而且非常简单。每个工人只有几行代码。加载队列是一个特殊的“管理器”,也只是几行代码。

答案 3 :(得分:0)

Gevent非常适合这一点。

Gevent使用Greenlets(在同一个python进程中使用轻量级协同程序)为您提供异步操作,而不会影响代码可读性或在您的混合中引入抽象的“reactor”概念。