如何并行化我的python代码

时间:2014-09-04 17:37:28

标签: python multithreading

我有一个大文件作为我的python代码的输入,它将生成相应的输出文件。但是,它需要太多时间,我想加快速度。

现在,我将大文件拆分为1000个较小的文件。我想要一个小脚本,它将启动1000个线程,每个线程使用我原来的python代码,并有自己的输出文件。

任何人都可以给我一个示例/示例代码吗?

3 个答案:

答案 0 :(得分:5)

首先,使用1000个线程几乎肯定会减慢速度,而不是加快速度。即使您的代码完全受I / O限制,1000也会推动许多平台的极限。调度程序,您将花费更多时间进行上下文切换而不是实际工作。

接下来,您需要知道您的代码是否受CPU限制(即对内存中的信息进行实际处理)或I / O绑定(即等待磁盘读写等事务)。


如果你的代码是CPU限制的,并且你可以保持CPU非常一致,你需要每个核心只有1个线程。这样,您可以通过最少量的上下文切换(以及缓存抖动来获得最大并行度,假设大多数工作都是在不可变或非共享值上完成的。)

另外(除非那些工作是在专门设计的C扩展中完成的,比如numpy),你希望这些线程处于不同的进程中,因为每个进程只有一个线程可以同时运行Python解释器,这要归功于Global口译员锁。

所以,你想要的几乎肯定是一个进程池。最简单的方法是使用concurrent.futures.ProcessPoolExecutor,可能带有max_workers参数(可能从16开始,然后尝试上下调整它以查看它是否有帮助。)


另一方面,如果你的代码主要受I / O限制,那么几十个线程是合理的,特别是如果延迟是不可预测的,而不是1000.并且同一进程中的线程将正常工作,因为一个线程可以运行Python解释器,而其他线程都在等待操作系统完成磁盘操作。

因此,在这种情况下,您需要concurrent.futures.ThreadPoolExecutor


如果您不确定,并且不知道如何查找,请首先使用线程池构建它,然后使用ActivityMonitor或任何Windows现在称为其进程管理器或您最喜欢的Linux上的300个选项可以观看它的运行情况;如果你最终得到一个100%的核心而其他核心低于25%,那么你太过CPU了,不能使用线程。幸运的是,切换到进程池是一项微不足道的更改 - 将ThreadPoolExecutor替换为ProcessPoolExecutor,并删除max_workers参数,以便Python选择最佳默认值,现在您已完成


在任何一种情况下,文档中的示例都足够好,没有理由要求其他示例代码。

答案 1 :(得分:1)

  • 如果你没有1000个处理器,千分之一没有兴趣...相反,开销很大......
  • 多线程用于更有效地管理I / O阻塞,而不是并行化处理工作。
  • 如果您的问题是来自同一设备的I / O,那么增加更多会增加其负载并增加开销(移动头部,缓存垃圾......)

您搜索的内容更多是多处理: https://docs.python.org/2/library/multiprocessing.html

答案 2 :(得分:1)

如果您决定使用multiprocessing,那么您将以非常类似的方式执行此操作。 你可以尝试这样的事情:

import Queue
from threading import Thread

file_list = ['filea', 'fileb']

def do_stuff(q):
    while True:
        try:
            file_name = q.get(False)
        except Queue.Empty:
            # Handle empty queue here
            break
        # do what ever you need here
        print file_name
        q.task_done()

q = Queue.Queue(maxsize=0)
num_threads = 2

for x in file_list:
  q.put(x)

for i in range(num_threads):
  worker = Thread(target=do_stuff, args=(q,))
  worker.setDaemon(True)
  worker.start()

q.join()