Python多进程库multiprocessing中进程池Pool类的使用详解


Posted in Python onNovember 24, 2017

问题起因

最近要将一个文本分割成好几个topic,每个topic设计一个regressor,各regressor是相互独立的,最后汇总所有topic的regressor得到总得预测结果。没错!类似bagging ensemble!只是我没有抽样。文本不大,大概3000行,topic个数为8,于是我写了一个串行的程序,一个topic算完之后再算另一个topic。可是我在每个topic中用了GridSearchCV来调参,又要选特征又要调整regressor的参数,导致参数组合一共有1782种。我真是低估了调参的时间,程序跑了一天一夜最后因为忘记import一个库导致最终的预测精度没有算出来。后来想到,既然每个topic的预测都是独立的,那是不是可以并行呢?

Python中的多线程与多进程

但是听闻Python的多线程实际上并不能真正利用多核,所以如果使用多线程实际上还是在一个核上做并发处理。不过,如果使用多进程就可以真正利用多核,因为各进程之间是相互独立的,不共享资源,可以在不同的核上执行不同的进程,达到并行的效果。同时在我的问题中,各topic相互独立,不涉及进程间的通信,只需最后汇总结果,因此使用多进程是个不错的选择。

multiprocessing

一个子进程

multiprocessing模块提供process类实现新建进程。下述代码是新建一个子进程。

from multiprocessing import Process

def f(name):
  print 'hello', name

if __name__ == '__main__':
  p = Process(target=f, args=('bob',)) # 新建一个子进程p,目标函数是f,args是函数f的参数列表
  p.start() # 开始执行进程
  p.join() # 等待子进程结束

上述代码中p.join()的意思是等待子进程结束后才执行后续的操作,一般用于进程间通信。例如有一个读进程pw和一个写进程pr,在调用pw之前需要先写pr.join(),表示等待写进程结束之后才开始执行读进程。

多个子进程

如果要同时创建多个子进程可以使用multiprocessing.Pool类。该类可以创建一个进程池,然后在多个核上执行这些进程。

import multiprocessing
import time

def func(msg):
  print multiprocessing.current_process().name + '-' + msg

if __name__ == "__main__":
  pool = multiprocessing.Pool(processes=4) # 创建4个进程
  for i in xrange(10):
    msg = "hello %d" %(i)
    pool.apply_async(func, (msg, ))
  pool.close() # 关闭进程池,表示不能在往进程池中添加进程
  pool.join() # 等待进程池中的所有进程执行完毕,必须在close()之后调用
  print "Sub-process(es) done."

输出结果如下:

Sub-process(es) done.
PoolWorker-34-hello 1
PoolWorker-33-hello 0
PoolWorker-35-hello 2
PoolWorker-36-hello 3
PoolWorker-34-hello 7
PoolWorker-33-hello 4
PoolWorker-35-hello 5
PoolWorker-36-hello 6
PoolWorker-33-hello 8
PoolWorker-36-hello 9

上述代码中的pool.apply_async()是apply()函数的变体,apply_async()是apply()的并行版本,apply()是apply_async()的阻塞版本,使用apply()主进程会被阻塞直到函数执行结束,所以说是阻塞版本。apply()既是Pool的方法,也是Python内置的函数,两者等价。可以看到输出结果并不是按照代码for循环中的顺序输出的。

多个子进程并返回值

apply_async()本身就可以返回被进程调用的函数的返回值。上一个创建多个子进程的代码中,如果在函数func中返回一个值,那么pool.apply_async(func, (msg, ))的结果就是返回pool中所有进程的值的对象(注意是对象,不是值本身)。

import multiprocessing
import time

def func(msg):
  return multiprocessing.current_process().name + '-' + msg

if __name__ == "__main__":
  pool = multiprocessing.Pool(processes=4) # 创建4个进程
  results = []
  for i in xrange(10):
    msg = "hello %d" %(i)
    results.append(pool.apply_async(func, (msg, )))
  pool.close() # 关闭进程池,表示不能再往进程池中添加进程,需要在join之前调用
  pool.join() # 等待进程池中的所有进程执行完毕
  print ("Sub-process(es) done.")

  for res in results:
    print (res.get())

上述代码输出结果如下:

Sub-process(es) done.
PoolWorker-37-hello 0
PoolWorker-38-hello 1
PoolWorker-39-hello 2
PoolWorker-40-hello 3
PoolWorker-37-hello 4
PoolWorker-38-hello 5
PoolWorker-39-hello 6
PoolWorker-37-hello 7
PoolWorker-40-hello 8
PoolWorker-38-hello 9

与之前的输出不同,这次的输出是有序的。

如果电脑是八核,建立8个进程,在Ubuntu下输入top命令再按下大键盘的1,可以看到每个CPU的使用率是比较平均的,如下图:

Python多进程库multiprocessing中进程池Pool类的使用详解

在system monitor中也可以清楚看到执行多进程前后CPU使用率曲线的差异。

Python多进程库multiprocessing中进程池Pool类的使用详解

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
RC4文件加密的python实现方法
Jun 30 Python
使用Python读写文本文件及编写简单的文本编辑器
Mar 11 Python
利用Python命令行传递实例化对象的方法
Nov 02 Python
python利用rsa库做公钥解密的方法教程
Dec 10 Python
浅谈flask截获所有访问及before/after_request修饰器
Jan 18 Python
python取代netcat过程分析
Feb 10 Python
Django+Ajax+jQuery实现网页动态更新的实例
May 28 Python
Python动态生成多维数组的方法示例
Aug 09 Python
实时获取Python的print输出流方法
Jan 07 Python
Python制作动态字符图的实例
Jan 27 Python
Form表单及django的form表单的补充
Jul 25 Python
python 机器学习的标准化、归一化、正则化、离散化和白化
Apr 16 Python
pip安装Python库时遇到的问题及解决方法
Nov 23 #Python
python清理子进程机制剖析
Nov 23 #Python
Python3 加密(hashlib和hmac)模块的实现
Nov 23 #Python
Python2.7基于笛卡尔积算法实现N个数组的排列组合运算示例
Nov 23 #Python
深入理解Python3 内置函数大全
Nov 23 #Python
Python内置函数delattr的具体用法
Nov 23 #Python
Python 内置函数memoryview(obj)的具体用法
Nov 23 #Python
You might like
PHP+DBM的同学录程序(5)
2006/10/09 PHP
PHP GD库生成图像的几个函数总结
2014/11/19 PHP
PHP+AJAX实现投票功能的方法
2015/09/28 PHP
jquery text,radio,checkbox,select操作实现代码
2009/07/09 Javascript
javascript算法题 求任意一个1-9位不重复的N位数在该组合中的大小排列序号
2012/07/21 Javascript
Mac OS X 系统下安装和部署Egret引擎开发环境
2014/09/03 Javascript
jQuery悬停文字提示框插件jquery.tooltipster.js用法示例【附demo源码下载】
2016/07/19 Javascript
基于JavaScript实现购物网站商品放大镜效果
2016/09/06 Javascript
JS之获取样式的简单实现方法(推荐)
2016/09/13 Javascript
javascript 中的事件委托详解
2016/10/25 Javascript
JavaScript中的编码和解码函数
2017/02/15 Javascript
springMVC + easyui + $.ajaxFileUpload实现文件上传注意事项
2017/04/23 Javascript
详解Vue.js Mixins 混入使用
2017/09/15 Javascript
Vue路由钩子之afterEach beforeEach的区别详解
2018/07/15 Javascript
详解node字体压缩插件font-spider的用法
2018/09/28 Javascript
node.js命令行教程图文详解
2019/05/27 Javascript
JavaScript实现图片上传并预览并提交ajax
2019/09/30 Javascript
基于Vue中的父子传值问题解决
2020/07/27 Javascript
解决vue使用vant轮播组件swipe + flex时文字抖动问题
2021/01/07 Vue.js
python循环监控远程端口的方法
2015/03/14 Python
Python制作钉钉加密/解密工具
2016/12/07 Python
python数据批量写入ScrolledText的优化方法
2018/10/11 Python
详解pytorch 0.4.0迁移指南
2019/06/16 Python
Jupyter notebook 远程配置及SSL加密教程
2020/04/14 Python
python名片管理系统开发
2020/06/18 Python
关于HTML5 Placeholder新标签低版本浏览器下不兼容的问题分析及解决办法
2016/01/27 HTML / CSS
为有想象力的人提供的生活方式商店:Firebox
2018/06/04 全球购物
英国百年闻名的优质健康产品连锁店:Holland & Barrett
2019/12/19 全球购物
StubHub中国:购买和出售全球活动门票
2020/01/01 全球购物
运动会广播稿60字
2014/01/15 职场文书
2014年3.15团委活动总结
2014/03/16 职场文书
担保书格式及范文
2014/04/01 职场文书
学用政策心得体会
2014/09/10 职场文书
音乐教师个人工作总结
2015/02/06 职场文书
详解CSS伪元素的妙用单标签之美
2021/05/25 HTML / CSS
深入理解python协程
2021/06/15 Python