并行化我的Python程序

3 投票
3 回答
689 浏览
提问于 2025-04-16 14:42

我有一个用Python写的程序,它会从一个输入文件中读取一行数据,进行一些处理,然后把结果写入输出文件。我有一台四核的电脑,想要充分利用这四个核心。我觉得有两种方法可以做到这一点:

  1. 创建多个Python进程,每个进程处理总记录数的1/n。
  2. 在一个Python进程中为每条输入记录创建多个线程,每个线程处理一条记录。
  3. 在一个Python进程中创建一个线程池,每个线程执行一条输入记录。

我从来没有使用过Python的多进程功能,能不能请高手们告诉我哪种方法是最好的选择?

3 个回答

0

第一种方法是正确的答案。

首先,创建和管理多个进程比多个线程要简单得多。你可以使用 multiprocessing 模块,或者像 pyro 这样的工具来处理这些细节。其次,线程需要处理Python的全局解释器锁,这让事情变得更复杂,即使你在Java或C#的线程方面很有经验。而且最重要的是,在多核机器上的性能表现比你想象的要难以预测。如果你没有尝试过并测量两种不同的方法,你对哪种方法更快的直觉可能是错的。

顺便说一下,如果你真的在Java或C#的线程方面是专家,那你可能应该选择使用线程,但要用 JythonIronPython,而不是CPython。

0

从多个进程同时读取同一个文件是件麻烦事。有没有办法提前把文件分开呢?

虽然Python有个叫GIL的限制,但Jython和IronPython就没有这个问题。

另外,要确保一个简单的单进程操作不会已经把磁盘的读写速度用到极限。如果已经满了,那你就很难再获得什么提升了。

4

Python的参考实现(也就是CPython)有一个著名的概念叫做“全局解释器锁”(GIL),这个锁的存在意味着在同一时间内,只有一个线程可以执行Python代码。因此,在Python中,多线程的使用受到很大限制——除非你在C扩展中完成了大量的工作,并且这些扩展能够释放这个锁。

要解决这个问题,最简单的方法是使用multiprocessing模块。这个模块的使用方式和threading模块很相似,操作起来也比较简单。在你的情况下,你可以这样使用它(假设数据处理是最复杂的部分):

import multiprocessing

def process_line(line):
    # This function is executed in your worker processes.  Manipulate the
    # line and return the results.
    return manipulate(line)

if __name__ == '__main__':
    with open('input.txt') as fin, open('output.txt', 'w') as fout:
        # This creates a pool of N worker processes, where N is the number
        # of CPUs in your machine.
        pool = multiprocessing.Pool()

        # Let the workers do the manipulation and write the results to
        # the output file:
        for manipulated_line in pool.imap(process_line, fin):
            fout.write(manipulated_line)

撰写回答