问题起因

最近要将一个文本分割成好几个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的使用率是比较平均的,如下图:

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

Python多进程库multiprocessing中进程池Pool类的使用的更多相关文章

  1. Python多进程库multiprocessing中进程池Pool类的使用[转]

    from:http://blog.csdn.net/jinping_shi/article/details/52433867 Python多进程库multiprocessing中进程池Pool类的使用 ...

  2. Python多进程库multiprocessing创建进程以及进程池Pool类的使用

    问题起因最近要将一个文本分割成好几个topic,每个topic设计一个regressor,各regressor是相互独立的,最后汇总所有topic的regressor得到总得预测结果.没错!类似bag ...

  3. PYTHON多进程编码结束之进程池POOL

    结束昨晚开始的测试. 最后一个POOL. A,使用POOL的返回结果 #coding: utf-8 import multiprocessing import time def func(msg): ...

  4. multiprocessing中进程池,线程池的使用

    multiprocessing 多进程基本使用 示例代码1 import time import random from multiprocessing import Process def run( ...

  5. python学习笔记——multiprocessing 多进程组件 进程池Pool

    1 进程池Pool基本概述 在使用Python进行系统管理时,特别是同时操作多个文件目录或者远程控制多台主机,并行操作可以节约大量时间,如果操作的对象数目不大时,还可以直接适用Process类动态生成 ...

  6. python 进程池pool简单使用

    平常会经常用到多进程,可以用进程池pool来进行自动控制进程,下面介绍一下pool的简单使用. 需要主动是,在Windows上要想使用进程模块,就必须把有关进程的代码写if __name__ == ‘ ...

  7. Python多进程并发操作进程池Pool

    目录: multiprocessing模块 Pool类 apply apply_async map close terminate join 进程实例 multiprocessing模块 如果你打算编 ...

  8. [转]Python多进程并发操作中进程池Pool的应用

    Pool类 在使用Python进行系统管理时,特别是同时操作多个文件目录或者远程控制多台主机,并行操作可以节约大量的时间.如果操作的对象数目不大时,还可以直接使用Process类动态的生成多个进程,十 ...

  9. Python多进程并发操作中进程池Pool的应用

    Pool类 在使用Python进行系统管理时,特别是同时操作多个文件目录或者远程控制多台主机,并行操作可以节约大量的时间.如果操作的对象数目不大时,还可以直接使用Process类动态的生成多个进程,十 ...

随机推荐

  1. 联想RD450带Read10服务器操作系统密码忘记

    联想RD450带Read10服务器操作系统密码忘记 可以用U盘PE进入重写密码 按F1进入BIOS界面设置如下 进入BOOT选项卡,设置U盘第一启动,也就是图中 Boot Option #1 设置为 ...

  2. 异常解决 Unable to write generated Java files for schemas: null

    错误是在使用cxf调用其他系统接口时报出的.而且问题很诡异,只有服务器调用时才报错,本地直接写main方法直接调用却正常的.以下是异常的堆栈: ERROR c.k.p.webservice.WebSe ...

  3. 记一次SQL性能优化,查询时间从4000ms优化到200ms.

    以下这句SQL是从PLM中获取代办工作流的.没优化前SQL语句执行一次大概4000ms(4秒). select ch.change_number changeNumber, f.text change ...

  4. spring-boot的三种启动方式[z]

    https://blog.csdn.net/u011425751/article/details/79507386 有段时间没有写博客了,也在努力的从传统单机开发向分布式系统过度,所以再次做一些笔记, ...

  5. Java Token的原理和生成使用机制

    在此之前我们先了解一下什么是Cookie.Session.Token 1.什么是Cookie? cookie指的就是浏览器里面能永久存储数据的一种数据存储功能.cookie由服务器生成,发送给浏览器, ...

  6. CITROEN C8 BSI HC12 Mileage Correction with Digiprog3

    CITROEN C8 BSI HC12 odometer correction pinout to Digiprog III Digiprog 3 mileage programmer. The BS ...

  7. Java 数组元素合并并去重

    public class TestList { public static void main(String[] args) { Set<Integer> set = new TreeSe ...

  8. spring web参数传递

    spring boot 参数相关 ******************************************   @RequestParam 这个注解用来绑定单个请求数据,既可以是url中的 ...

  9. 延迟执行(Invoke 函数)和消息发送(SendMessage 函数)

    Invoke 函数需要继承 MonoBehaviour 类后才能使用. Invoke(string str,float a):a 秒后执行名为 str 函数(只会调用一次). Invoke(strin ...

  10. 1131 Subway Map DFS解法 BFS回溯!

    In the big cities, the subway systems always look so complex to the visitors. To give you some sense ...