python的multiprocess的使用
来源:互联网 发布:网络测试仪怎么用 编辑:程序博客网 时间:2024/05/16 17:07
主要参考链接:
1)http://www.jb51.net/article/67116.htm
2)http://www.cnblogs.com/kaituorensheng/p/4445418.html
3)https://jingsam.github.io/2015/12/31/multiprocessing.html 写的很好
4)http://www.cnblogs.com/vamei/archive/2012/10/12/2721484.html
一。http://www.jb51.net/article/67116.htm的摘要
由于Python设计的限制(我说的是咱们常用的CPython)。最多只能用满1个CPU核心。这就是导致在做特征工程的时候,运行效率慢的主要原因,拿一个cpu单线程跑特征工程肯定慢。
Python提供了非常好用的多进程包multiprocessing,你只需要定义一个函数,Python会替你完成其他所有事情。借助这个包,可以轻松完成从单进程到并发执行的转换。
1、新建单一进程
如果我们新建少量进程,可以如下:
import multiprocessingimport timedef func(msg): for i in xrange(3): print msg time.sleep(1)if __name__ == "__main__": p = multiprocessing.Process(target=func, args=("hello", )) p.start() p.join() print "Sub-process done."
2、使用进程池
是的,你没有看错,不是线程池。它可以让你跑满多核CPU,而且使用方法非常简单。
注意要用apply_async,如果落下async,就变成阻塞版本了,apply()这个表示上一个线程结束之后才能进行下一个任务,也就是前面所说的阻塞。如果是apply_async(),那么就可以异步执行。
processes=4是最多并发进程数量。
import multiprocessingimport timedef func(msg): for i in xrange(3): print msg time.sleep(1)if __name__ == "__main__": pool = multiprocessing.Pool(processes=4) for i in xrange(10): msg = "hello %d" %(i) pool.apply_async(func, (msg, )) pool.close() pool.join() print "Sub-process(es) done."
3、使用Pool,并需要关注结果
更多的时候,我们不仅需要多进程执行,还需要关注每个进程的执行结果,如下:
import multiprocessingimport timedef func(msg): for i in xrange(3): print msg time.sleep(1) return "done " + msg #返回func的结果if __name__ == "__main__": pool = multiprocessing.Pool(processes=4) result = [] for i in xrange(10): msg = "hello %d" %(i) result.append(pool.apply_async(func, (msg, ))) pool.close() pool.join() for res in result: print res.get() print "Sub-process(es) done."
二。http://www.cnblogs.com/kaituorensheng/p/4445418.html
python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。Python提供了非常好用的多进程包multiprocessing,只需要定义一个函数,Python会完成其他所有事情。借助这个包,可以轻松完成从单进程到并发执行的转换。multiprocessing支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。
对于pool的讲解:
Pool
在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,十几个还好,但如果是上百个,上千个目标,手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效。
Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来它。
例7.1:使用进程池(非阻塞)
#coding: utf-8import multiprocessingimport timedef func(msg): print "msg:", msg time.sleep(3) print "end"if __name__ == "__main__": pool = multiprocessing.Pool(processes = 3) for i in xrange(4): msg = "hello %d" %(i) pool.apply_async(func, (msg, )) #维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去 print "Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~" pool.close() pool.join() #调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束 print "Sub-process(es) done."
一次执行结果
mMsg: hark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~ello
0
msg: hello
1
msg: hello
2
end
msg: hello
3
end
end
end
Sub-process(es) done.
函数解释:
- apply_async(func[, args[, kwds[, callback]]]) 它是非阻塞,apply(func[, args[, kwds]])是阻塞的(理解区别,看例1例2结果区别)
- close() 关闭pool,使其不在接受新的任务。
- terminate() 结束工作进程,不在处理未完成的任务。
- join() 主进程阻塞,等待子进程的退出, join方法要在close或terminate之后使用。
执行说明:创建一个进程池pool,并设定进程的数量为3,xrange(4)会相继产生四个对象[0, 1, 2, 4],四个对象被提交到pool中,因pool指定进程数为3,所以0、1、2会直接送到进程中执行,当其中一个执行完事后才空出一个进程处理对象3,所以会出现输出“msg: hello 3”出现在"end"后。因为为非阻塞,主函数会自己执行自个的,不搭理进程的执行,所以运行完for循环后直接输出“mMsg: hark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~”,主程序在pool.join()处等待各个进程的结束。
例7.2:使用进程池(阻塞)
#coding: utf-8import multiprocessingimport timedef func(msg): print "msg:", msg time.sleep(3) print "end"if __name__ == "__main__": pool = multiprocessing.Pool(processes = 3) for i in xrange(4): msg = "hello %d" %(i) pool.apply(func, (msg, )) #维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去 print "Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~" pool.close() pool.join() #调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束 print "Sub-process(es) done."
一次执行的结果
msg: hello
0
end
msg: hello
1
end
msg: hello
2
end
msg: hello
3
end
Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~
Sub-process(es) done.
例7.3:使用进程池,并关注结果
import multiprocessingimport timedef func(msg): print "msg:", msg time.sleep(3) print "end" return "done" + msgif __name__ == "__main__": pool = multiprocessing.Pool(processes=4) result = [] for i in xrange(3): msg = "hello %d" %(i) result.append(pool.apply_async(func, (msg, ))) pool.close() pool.join() for res in result: print ":::", res.get() print "Sub-process(es) done."
一次执行结果
msg: hello
0
msg: hello
1
msg: hello
2
end
end
end
::: donehello
0
::: donehello
1
::: donehello
2
Sub-process(es) done.
例7.4:使用多个进程池
#coding: utf-8import multiprocessingimport os, time, randomdef Lee(): print "\nRun task Lee-%s" %(os.getpid()) #os.getpid()获取当前的进程的ID start = time.time() time.sleep(random.random() * 10) #random.random()随机生成0-1之间的小数 end = time.time() print 'Task Lee, runs %0.2f seconds.' %(end - start)def Marlon(): print "\nRun task Marlon-%s" %(os.getpid()) start = time.time() time.sleep(random.random() * 40) end=time.time() print 'Task Marlon runs %0.2f seconds.' %(end - start)def Allen(): print "\nRun task Allen-%s" %(os.getpid()) start = time.time() time.sleep(random.random() * 30) end = time.time() print 'Task Allen runs %0.2f seconds.' %(end - start)def Frank(): print "\nRun task Frank-%s" %(os.getpid()) start = time.time() time.sleep(random.random() * 20) end = time.time() print 'Task Frank runs %0.2f seconds.' %(end - start) if __name__=='__main__': function_list= [Lee, Marlon, Allen, Frank] print "parent process %s" %(os.getpid()) pool=multiprocessing.Pool(4) for func in function_list: pool.apply_async(func) #Pool执行函数,apply执行函数,当有一个进程执行完毕后,会添加一个新的进程到pool中 print 'Waiting for all subprocesses done...' pool.close() pool.join() #调用join之前,一定要先调用close() 函数,否则会出错, close()执行后不会有新的进程加入到pool,join函数等待素有子进程结束 print 'All subprocesses done.'
一次执行结果
parent process
7704
Waiting for
all
subprocesses done...
Run task Lee
-6948
Run task Marlon
-2896
Run task Allen
-7304
Run task Frank
-3052
Task Lee, runs
1.59
seconds.
Task Marlon runs
8.48
seconds.
Task Frank runs
15.68
seconds.
Task Allen runs
18.08
seconds.
All subprocesses done.
三。https://jingsam.github.io/2015/12/31/multiprocessing.html
pool.apply_async
采用异步方式调用 task,pool.apply
则是同步方式调用。同步方式意味着下一个 task 需要等待上一个 task 完成后才能开始运行,这显然不是我们想要的功能,所以采用异步方式连续地提交任务。在上面的语句中,我们提交了 4 个任务,假设我的 CPU 是 4 核,那么我的每个核运行一个任务。如果我提交多于 4 个任务,那么每个核就需要同时运行 2 个以上的任务,这回带来任务切换成本,降低了效率。所以我们设置的并行任务数最好等于 CPU 核心数, CPU 核可以通过下面语句得到:
1
cpus = multiprocessing.cpu_count()
接下来我们使用 result.get()
来获取 task 的返回值:
12
for result in results:print(result.get())
在这里不免有人要疑问,为什么不直接在 for 循环中直接 result.get()
呢?这是因为pool.apply_async
之后的语句都是阻塞执行的,调用 result.get()
会等待上一个任务执行完之后才会分配下一个任务。事实上,获取返回值的过程最好放在进程池回收之后进行,避免阻塞后面的语句。
最后我们使用一下语句回收进程池:
12
pool.close()pool.join()
最后附上完整的代码如下:
12345678910111213141516171819
def task(pid):# do somethingreturn resultdef main():multiprocessing.freeze_support()pool = multiprocessing.Pool()cpus = multiprocessing.cpu_count()results = []for i in xrange(0, cpus):result = pool.apply_async(task, args=(i,))results.append(result)pool.close()pool.join()for result in results:print(result.get())
- python的multiprocess的使用
- python multiprocess 包中工具类Queue的使用
- python multiprocess 包中工具类Queue的使用
- python multiprocess
- log4js multiprocess appenders 的配置
- multiprocess Poll.map python多进程提取处理大量文本的关键词
- python os、multiprocess、 threading
- MultiProcess下Log的打印要注意的一点
- Python Multiprocess with SIGTERM supported
- 【原创】python multiprocess…
- multiprocess模块使用进程池调用apply_async()提交的函数及回调函数不执行问题
- MultiProcess进程池的设计(一)概述
- 【python】多进程锁multiprocess.Lock
- Python 多进程锁multiprocess Lock
- python+multiprocess+theano+pylucene--内存泄露解决方案
- multiprocess模块使用进程池时往Pool对象传入的函数不巧当导致进程运行速度跟单线程速度一样
- MultiProcess进程池的设计(三)主进程和子进程间的通信
- MultiProcess进程池的设计(二)Jar进程启动和关闭
- 文章标题
- RHEL7破解root密码
- Shell表达式,如${file##*/}
- 安装Android Studio 笔记
- Ubuntu14.04安装CMake3.4.1
- python的multiprocess的使用
- Android Studio下JNI编程2(接上篇,详细讲解java与c层互传参数)
- 集合中根据对象中的某一属性属性排序
- java中getAttribute和getParameter的区别
- window.print打印指定区域。
- 两种TL431的恒流源电路 分析
- 在做自动化测试之前你需要知道的
- Runloop 探秘(一)
- Eclipse常用快捷键