我可以将子进程映射到主进程 运行 所在的同一 multiprocessing.Pool 吗?

Can I map a subprocess to the same multiprocessing.Pool where the main process is running?

我对 python3multiprocessing 世界还比较陌生,因此如果之前有人问过这个问题,我很抱歉。我有一个脚本,它从 N 个元素的列表中 运行s 对每个元素进行完整分析,将每个元素映射到不同的过程。

我知道这是次优的,事实上我想提高多处理效率。我使用 map() 到 运行 每个进程到一个 Pool() 中,它可以包含用户通过命令行参数指定的进程数。

代码如下所示:

max_processes = 7 
# it is passed by command line actually but not relevant here

def main_function( ... ):

    res_1 = sub_function_1( ... )
    res_2 = sub_function_2( ... )

if __name__ == '__main__':

    p = Pool(max_processes)
    Arguments = []

    for x in Paths.keys():
        # generation of the arguments
        ... 
        Arguments.append( Tup_of_arguments )

    p.map(main_function, Arguments)

    p.close()
    p.join()

如您所见,我的进程调用了一个主函数,该函数又依次调用许多其他函数。现在,每个 sub_functions 都是可多处理的。我可以从那些映射到主进程 运行s 的同一个池的子函数映射进程吗?

不,你不能。
该池(几乎)在工作进程中不可用。这有点取决于用于池的 start method

重生
一个新的 Python 解释器进程启动并导入模块。由于在该进程中 __name__'__mp_main__',因此 __name__ == '__main__' 块中的代码未执行,并且 worker 中不存在池对象。

分叉
将父进程的内存space复制到子进程的内存space中。这有效地导致每个工人的内存 space 中存在一个现有的 Pool 对象。
但是,该池无法使用。 worker 是在池的 __init__ 执行期间创建的,因此当 worker 被分叉时,池的初始化是不完整的。工作进程中的池副本有 none 个管理工作人员、任务和结果的线程 运行。无论如何,线程不会通过 fork.
进入子进程 此外,由于工作人员是在初始化期间创建的,因此池对象此时尚未分配任何名称。虽然它确实潜伏在工作人员的记忆中 space,但没有它的句柄。它不会通过 globals(); I only found it via gc.get_objects() 显示:<multiprocessing.pool.Pool object at 0x7f75d8e50048>
无论如何,该池对象是主进程中对象的副本

forkserver
我无法测试这个启动方法

为了解决您的问题,您可以可以 fiddle在主进程中使用队列和队列处理程序线程来从工作进程发回任务并将它们委托给池,但我能想到的所有方法都显得很笨拙。
如果您努力采用它在池中进行处理,您很可能最终会得到更易于维护的代码。

顺便说一句:我不确定允许用户通过命令行传递工人数量是否是个好主意。我建议至少通过 os.cpu_count() 给该值一个上限。