pool.map()如何在内部分配工作?

4

我对multiprocessing库还比较陌生,在使用其与map()一起操作的Pool模块时,有一个问题。假设我有4个工作线程和6项任务需要完成。我的做法是(使用multiprocessing.dummy,因为我想要生成线程而不是进程)。

from multiprocessing.dummy import Pool as ThreadPool

def print_it(num):
    print num

def multi_threaded():
    tasks = [1, 2, 3, 4, 5, 6]
    pool = ThreadPool(4)
    r = pool.map(print_it, tasks)
    pool.close()
    pool.join()

multi_threaded()

我希望了解Pool.map() 如何处理任务?有以下三个选项:
  1. 它首先生成4个线程,完成前4个任务,并让线程死亡。然后为剩余的任务生成2个新线程?
  2. 它生成4个线程,将4个任务分配给它们,一旦某个线程完成其任务,就将新任务分配给同一线程。
  3. 其他方式。
这些洞察力会很有帮助,因为它将帮助我在生产中更有效地使用Pool.map()。

我所知道的几乎所有池都会执行(2)。但我不熟悉这个特定的库,通常我在使用Python + 多线程时经历的主要是令人失望的经历。我认为有一些有限智能的解决方案是完全可能的。祝你好运,期待详细的答案。 - peterh
你可以通过让 print_it 函数也 sleep 来进行测试,看看会发生什么。在 Python 3.6 中进行这个测试,似乎新任务会在有空闲线程处理时立即启动。 - quamrana
为什么不阅读源代码并自己看看呢?ThreadPool类是普通的multiprocessing.pool.Pool的子类,它覆盖了一些东西(如果您想要查看,可以在文件底部看到它的定义)。 - Blckknght
1个回答

1

这取决于您如何定义您的池。

就像您在示例中所做的那样,发生了(2)。当您初始化池时(在Pool__init__()中发生-不需要提交任务即可发生),依赖池的线程或进程会立即启动并等待任务。当任务到达并执行后,线程或进程不会退出,它们只是回到等待状态等待更多的工作到来。

但是您可以以不同的方式定义它。您可以向您的池添加maxtasksperchild参数。一旦一个工作程序完成了这个任务数量,它就会退出,并且新的工作程序会立即启动(无需先给它一个任务,它会在工作程序退出后立即启动)。这由池类Pool._maintain_pool()Pool._repopulate_pool()函数管理。

如果您希望您的工作人员在启动时运行无限期,那么继续做您现在所做的即可。如果您希望您的工作人员在启动时退出并在完成一定数量的任务之后(即使只有一个任务),则使用maxtasksperchild。如果您不想在需要它们之前启动进程或线程,请不要使用Pool。在需要时启动线程或进程,并自行管理它们。

希望这可以帮到您。


这是一个非常棒的答案。谢谢你。 - Pranjal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接