我在更大的代码库中使用多重处理,其中一些导入语句具有副作用。如何在后台进程中运行函数而不让它继承全局导入?
# helper.py:
print('This message should only print once!')
# main.py:
import multiprocessing as mp
import helper # This prints the message.
def worker():
pass # Unfortunately this also prints the message again.
if __name__ == '__main__':
mp.set_start_method('spawn')
process = mp.Process(target=worker)
process.start()
process.join()
背景:导入TensorFlow会初始化CUDA,CUDA会保留一定量的GPU内存。因此,生成太多进程会导致 CUDA OOM 错误,即使这些进程不使用 TensorFlow。
类似问题没有答案:
是否有资源可以准确解释多处理 启动
时模块会做什么?mp.Process
超级快速版本(使用spawn context而不是fork)
fork()
exec()
创建一个新进程。在 Windows 上,它是 Create
ProcessW()
。新的 python 解释器通过启动脚本 spawn_main()
进行调用,并通过 精心设计的命令字符串 和 -c
开关传递通信管道文件描述符。启动脚本稍微清理环境,然后从其通信管道中unpickles Process
对象。最后它调用流程对象的run
方法。
那么导入模块怎么样?
Pickle 语义处理其中的一些,但是
__main__
和 sys.modules
需要一些 tlc,这是在 here 处理的(在“清理环境”期间)。
# helper.py:
print('This message should only print once!')
# main.py:
import multiprocessing as mp
def worker():
pass
def main():
# Importing the module only locally so that the background
# worker won't import it again.
import helper
mp.set_start_method('spawn')
process = mp.Process(target=worker)
process.start()
process.join()
if __name__ == '__main__':
main()
使用flask和gunicorn运行服务器,
__name__
和multiprocessing.parent_process()
都无法区分父进程和子进程,所以我必须在为子进程明确设置它后使用multiprocessing.current_process().name
。
import multiprocessing as mp
def child_process():
pass
if mp.current_process().name != "the_child":
import numpy # Or other expensive/side-effect imports
process = mp.Process(target=child_process, name="the_child")
process.start()
process.join()