如何在进行大量I/O密集型操作时最大化Python性能?

11 投票
4 回答
6008 浏览
提问于 2025-04-15 23:32

我现在遇到一个情况,就是我需要下载很多文件。目前所有的下载任务都是在一个主线程里进行的,每几分钟能下载大约3000个文件。但问题是,这样下载的时间太长了。我知道Python并不支持真正的多线程,但有没有更好的方法来解决这个问题呢?我在想是不是可以启动多个线程,因为文件的输入输出操作应该不需要访问全局解释器锁,但我可能对这个概念理解得不太对。

4 个回答

3

有没有更好的方法来做这个?

有的。

我在考虑启动多个线程,因为这是与输入输出相关的操作。

别这样。

在操作系统层面,一个进程中的所有线程共享有限的输入输出资源。

如果你想要真正的速度,应该启动尽可能多的重型操作系统进程,直到你的平台无法再承受为止。操作系统在平衡进程之间的输入输出工作负载方面非常出色。让操作系统来处理这些事情。

有人会说启动3000个进程不好,他们说得对。你可能一次只想启动几百个进程。

真正想要的是以下几点。

  1. 一个共享的消息队列,把3000个URI排队。

  2. 几百个工作者,它们都在读取这个队列。

    每个工作者从队列中获取一个URI,然后去获取文件。

这些工作者可以一直运行。当队列空了,它们就会在那儿等着工作。

“每隔几分钟”你把3000个URI放进队列,让工作者开始工作。

这样会充分利用你处理器上的每一个资源,而且这很简单。每个工作者的代码只有几行。加载队列的“管理者”也只是几行代码。

16

多线程在网络输入输出(I/O)方面是个不错的选择,可以加快速度(不过异步编程的效果会更好)。CPython的多线程是比较“真实”的(就是使用操作系统的原生线程)——你可能想到的是GIL,也就是全局解释器锁,它会阻止不同的线程同时运行Python代码。不过,当所有的I/O操作在等待系统调用完成时,它们会放弃GIL,所以GIL对I/O性能并没有影响!

对于异步编程,目前最强大的框架是twisted,但如果你之前没有接触过这种编程,可能需要花点时间才能掌握。对你来说,使用线程池来提高I/O性能可能会更简单。

5

你可以去看看这个链接:multiprocessing

撰写回答