python多进程中的内存复制(实例讲解)


Posted in Python onJanuary 05, 2018

比较好奇python对于多进程中copy on write机制的实际使用情况。目前从实验结果来看,python 使用multiprocessing来创建多进程时,无论数据是否不会被更改,子进程都会复制父进程的状态(内存空间数据等)。所以如果主进程耗的资源较多时,不小心就会造成不必要的大量的内存复制,从而可能导致内存爆满的情况。

示例

举个例子,假设主进程读取了一个大文件对象的所有行,然后通过multiprocessing创建工作进程,并循环地将每一行数据交给工作进程来处理:

def parse_lines(args):
 #working
 ...
def main_logic():
 f = open(filename , 'r')
 lines = f.readlines()
 f.close()
 pool = multiprocessing.Pool(processes==4)
 rel = pool.map(parse_lines , itertools.izip(lines , itertools.repeat(second_args)) , int(len(lines)/4))
 pool.close()
 pool.join()

以下是top及ps结果:

python多进程中的内存复制(实例讲解)

(四个子进程)

python多进程中的内存复制(实例讲解)

(父进程及四个子进程)

由上两张图可以看出父进程及子进程都各自占用了1.4G左右的内存空间。而大部分内存空间存储的是读数据lines,所以这样的内存开销太浪费。

优化计划

1: 在主进程初期未导入大量的py库之前创建进程,或者动态加载py库。

2:通过内存共享来减少内存的开销。

3: 主进程不再读取文件对象,交给每个工作进程去读取文件中的相应部分。

改进代码:

def line_count(file_name):
 count = -1 #让空文件的行号显示0
 for count,line in enumerate(open(file_name)): pass
 #enumerate格式化成了元组,count就是行号,因为从0开始要+1
 return count+1
def parse_lines(args):
 f = open(args[0] , 'r')
 lines = f.readlines()[args[1]:args[2]] #read some lines
 f.close() 
 #working
def main_logic(filename,process_num):
 line_count = line_count(filename)
 avg_len = int(line_count/process_num)
 left_cnt = line_count%process_num;
 pool = multiprocessing.Pool(processes=process_num)
 for i in xrange(0,process_num):
  ext_cnt = (i>=process_num-1 and [left_cnt] or [0])[0]
  st_line = i*avg_len
  pool.apply_async(parse_lines, ((filename, st_line, st_line+avg_len+ext_cnt),)) #指定进程读某几行数据
 pool.close()
 pool.join()

再次用top或者ps来查看进程的内存使用情况:

python多进程中的内存复制(实例讲解)

(四个子进程)

python多进程中的内存复制(实例讲解)

(父进程及四个子进程)

小结

对比两次的内存使用情况,改进代码后父进程及子进程所占用的内存明显减少;所有内存占用相当于原来的一半,这就是减少内存复制的效果。

关于内存使用这方面还有不少优化方法和空间,稍后继续研究。

以上这篇python多进程中的内存复制(实例讲解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python实现提取文章摘要的方法
Apr 21 Python
Python工程师面试题 与Python基础语法相关
Jan 14 Python
Window10+Python3.5安装opencv的教程推荐
Apr 02 Python
Python基于辗转相除法求解最大公约数的方法示例
Apr 04 Python
python实现在图片上画特定大小角度矩形框
Oct 24 Python
Python3实现腾讯云OCR识别
Nov 27 Python
在Pycharm terminal中字体大小设置的方法
Jan 16 Python
关于Tensorflow分布式并行策略
Feb 03 Python
详解Python修复遥感影像条带的两种方式
Feb 23 Python
Python类的动态绑定实现原理
Mar 21 Python
新手常见Python错误及异常解决处理方案
Jun 18 Python
python 日志模块logging的使用场景及示例
Jan 04 Python
使用python和Django完成博客数据库的迁移方法
Jan 05 #Python
Python3多线程爬虫实例讲解代码
Jan 05 #Python
python编写微信远程控制电脑的程序
Jan 05 #Python
使用python爬虫实现网络股票信息爬取的demo
Jan 05 #Python
简单实现python收发邮件功能
Jan 05 #Python
5款非常棒的Python工具
Jan 05 #Python
Python基于列表模拟堆栈和队列功能示例
Jan 05 #Python
You might like
php inc文件使用的风险和注意事项
2013/11/12 PHP
PHP echo,print,printf,sprintf函数之间的区别与用法详解
2013/11/27 PHP
php实现redis数据库指定库号迁移的方法
2015/01/14 PHP
Laravel框架使用Seeder实现自动填充数据功能
2018/06/13 PHP
使用Git实现Laravel项目的自动化部署
2019/11/24 PHP
PHP常用header头定义代码示例汇总
2020/08/29 PHP
Javascript 中 null、NaN和undefined的区别总结
2013/04/10 Javascript
JS的参数传递示例介绍
2014/02/08 Javascript
javascript的回调函数应用示例
2014/02/20 Javascript
jQuery实现仿QQ在线客服效果的滚动层代码
2015/10/15 Javascript
谈谈jQuery Ajax用法详解
2015/11/27 Javascript
BootstrapValidator不触发校验的实现代码
2016/09/28 Javascript
详解jquery选择器的原理
2017/08/01 jQuery
微信小程序自定义组件封装及父子间组件传值的方法
2018/08/28 Javascript
JavaScript 复制对象与Object.assign方法无法实现深复制
2018/11/02 Javascript
微信小程序MUI侧滑导航菜单示例(Popup弹出式,左侧不动,右侧滑动)
2019/01/23 Javascript
一些你可能不熟悉的JS知识点总结
2019/03/15 Javascript
在Python中操作字典之setdefault()方法的使用
2015/05/21 Python
Python验证码识别的方法
2015/07/10 Python
Python实现删除列表中满足一定条件的元素示例
2017/06/12 Python
Python入门之后再看点什么好?
2018/03/05 Python
python模块之subprocess模块级方法的使用
2019/03/26 Python
python如何实现代码检查
2019/06/28 Python
python标记语句块使用方法总结
2019/08/05 Python
如何在python中写hive脚本
2019/11/08 Python
Python测试Kafka集群(pykafka)实例
2019/12/23 Python
将python文件打包exe独立运行程序方法详解
2020/02/12 Python
英国男士时尚网站:Dandy Fellow
2018/02/09 全球购物
ToysRus日本官网:玩具反斗城
2018/09/08 全球购物
SQL面试题
2013/04/30 面试题
2014年党的群众路线活动个人整改措施
2014/10/28 职场文书
总经理岗位职责
2015/02/04 职场文书
抖音短视频(douyin)去水印工具的实现代码
2021/03/30 Javascript
教你使用一行Python代码玩遍童年的小游戏
2021/08/23 Python
MySQL视图概念以及相关应用
2022/04/19 MySQL
关于mysql中string和number的转换问题
2022/06/14 MySQL