多处理forkvs spawn

如何解决多处理forkvs spawn

我正在从python doc中阅读两者的描述:

生成

父进程将启动一个全新的python解释器进程。子进程将仅继承运行进程对象run()方法所需的那些资源。特别是,父进程中不必要的文件描述符和句柄将不会被继承。与使用fork或forkserver相比,使用此方法启动进程相当慢。 [在Unix和Windows上可用。 Windows和macOS上的默认设置。]

叉子

父进程使用os.fork()派生Python解释器。子进程开始时实际上与父进程相同。父进程的所有资源均由子进程继承。请注意,安全地分叉多线程进程是有问题的。 [仅在Unix上可用。 Unix上的默认设置。]

我的问题是:

  1. 分叉是否快得多,因为它不会尝试识别要复制的资源?
  2. 是不是因为fork复制了所有内容,与spawn()相比,它会“浪费”更多的资源?

解决方法

在 3 multiprocessing start methods 之间有一个权衡:

  1. fork 速度更快,因为它对父进程的整个虚拟内存进行写时复制,包括初始化的 Python 解释器、加载的模块和内存中构造的对象。

    但是 fork 不会复制父进程的线程。因此,在父进程中由其他线程持有的锁(在内存中)被卡在子进程中而没有拥有线程来解锁它们,当代码试图获取它们中的任何一个时,准备好导致死锁。此外,任何带有分叉线程的本机库都将处于损坏状态。

    复制的 Python 模块和对象可能有用,或者它们可能不必要地使每个分叉的子进程膨胀。

    子进程还“继承”操作系统资源,例如打开的文件描述符和打开的网络端口。这些也可能导致问题,但 Python 可以解决其中的一些问题。

    所以fork 速度快、不安全,而且可能很臃肿。

    但是,这些安全问题可能不会造成麻烦,具体取决于子进程的作用。

  2. spawn 从头开始​​一个 Python 子进程,没有父进程的内存、文件描述符、线程等。从技术上讲,spawn fork 当前进程的副本,然后子进程立即调用exec 用新的 Python 替换自身,然后要求 Python 加载目标模块并运行目标可调用。

    因此spawn 是安全、紧凑且速度较慢的,因为 Python 必须加载、初始化自身、读取文件、加载和初始化模块等。

    但是,与子进程所做的工作相比,它可能不会明显变慢

  3. forkserver 分叉当前 Python 进程的副本,该副本将缩减为近似全新的 Python 进程。这成为“分叉服务器”过程。然后每次启动子进程时,它都会要求 fork 服务器 fork 一个子进程并运行其目标可调用。

    那些子进程一开始都是紧凑的,没有卡住的锁。

    forkserver 更复杂,而且没有很好的文档记录。 Bojan Nikolic's blog post 详细介绍了 forkserver 及其用于预加载某些模块的秘密 set_forkserver_preload() 方法。小心使用未记录的方法,尤其是。在 bug fix in Python 3.7.0 之前。

    所以forkserver 是快速、紧凑且安全的,但它更复杂且没有很好的文档记录

[文档在所有这些方面都不是很好,所以我结合了来自多个来源的信息并做出了一些推论。对任何错误发表评论。]

,
  1. 分叉是否快得多,因为它不会尝试识别要复制的资源?

是的,速度更快。内核可以克隆整个过程,并且仅复制修改的内存页作为一个整体。无需将资源用于新进程并从头启动解释器。

  1. 是不是因为fork复制了所有内容,与spawn()相比,它会“浪费”更多的资源?

现代内核上的前叉仅执行"copy-on-write",并且仅影响实际更改的内存页面。需要注意的是,“写入”已经仅包含对CPython中的对象进行迭代。那是因为对象的引用计数增加了。

如果您的进程运行很长时间,并且正在使用许多小对象,则这可能意味着您浪费了比spawn更多的内存。有趣的是,我记得Facebook声称通过将Python进程从“ fork”切换为“ spawn”,内存使用量大大减少了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-