加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

【Python】Python多进程库multiprocessing中进程池Pool的返回值

发布时间:2020-12-17 01:22:48 所属栏目:Python 来源:网络整理
导读:h1 style="padding:0px;font-family:'-apple-system','SF UI Text',Arial,'PingFang SC','Hiragino Sans GB','Microsoft YaHei','WenQuanYi Micro Hei',sans-serif,SimHei,SimSun;background-color:rgb(255,255,255);"问题起因 p style="font-family:'-apple

<h1 style="padding:0px;font-family:'-apple-system','SF UI Text',Arial,'PingFang SC','Hiragino Sans GB','Microsoft YaHei','WenQuanYi Micro Hei',sans-serif,SimHei,SimSun;background-color:rgb(255,255,255);">问题起因<p style="font-family:'-apple-system',255);">最近要将一个文本分割成好几个topic,每个topic设计一个regressor,各regressor是相互独立的,最后汇总所有topic的regressor得到总得预测结果。没错!类似bagging ensemble!只是我没有抽样。文本不大,大概3000行,topic个数为8,于是我写了一个串行的程序,一个topic算完之后再算另一个topic。可是我在每个topic中用了<code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">GridSearchCV来调参,又要选特征又要调整regressor的参数,导致参数组合一共有1782种。我真是低估了调参的时间,程序跑了一天一夜最后因为忘记import一个库导致最终的预测精度没有算出来。后来想到,既然每个topic的预测都是独立的,那是不是可以并行呢?

<h1 style="padding:0px;font-family:'-apple-system',255);">Python中的多线程与多进程<p style="font-family:'-apple-system',255);">但是听闻Python的多线程实际上并不能真正利用多核,所以如果使用多线程实际上还是在一个核上做并发处理。不过,如果使用多进程就可以真正利用多核,因为各进程之间是相互独立的,不共享资源,可以在不同的核上执行不同的进程,达到并行的效果。同时在我的问题中,各topic相互独立,不涉及进程间的通信,只需最后汇总结果,因此使用多进程是个不错的选择。

<h1 style="padding:0px;font-family:'-apple-system',255);">multiprocessing<h2 style="padding:0px;font-family:'-apple-system',255);">一个子进程<p style="font-family:'-apple-system',255);">multiprocessing模块提供process类实现新建进程。下述代码是新建一个子进程。

<pre class="prettyprint" style="font-size:14px;line-height:22px;"><code class="language-python hljs has-numbering"><span class="hljs-keyword">from multiprocessing <span class="hljs-keyword">import Process

<span class="hljs-function"><span class="hljs-keyword">def <span class="hljs-title">f<span class="hljs-params">(name):
<span class="hljs-keyword">print <span class="hljs-string">'hello',name

<span class="hljs-keyword">if name == <span class="hljs-string">'main':
p = Process(target=f,args=(<span class="hljs-string">'bob',)) <span class="hljs-comment"># 新建一个子进程p,目标函数是f,args是函数f的参数列表
p.start() <span class="hljs-comment"># 开始执行进程
p.join() <span class="hljs-comment"># 等待子进程结束<ul class="pre-numbering"><li style="color:rgb(153,153,153);">1<li style="color:rgb(153,153);">2<li style="color:rgb(153,153);">3<li style="color:rgb(153,153);">4<li style="color:rgb(153,153);">5<li style="color:rgb(153,153);">6<li style="color:rgb(153,153);">7<li style="color:rgb(153,153);">8<li style="color:rgb(153,153);">9<p style="font-family:'-apple-system',255);">上述代码中<code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">p.join()的意思是等待子进程结束后才执行后续的操作,一般用于进程间通信。例如有一个读进程pw和一个写进程pr,在调用pw之前需要先写<code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">pr.join(),表示等待写进程结束之后才开始执行读进程。

<h1 style="padding:0px;font-family:'-apple-system',255);">多个子进程<p style="font-family:'-apple-system',255);">如果要同时创建多个子进程可以使用<code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">multiprocessing.Pool类。该类可以创建一个进程池,然后在多个核上执行这些进程。

<pre class="prettyprint" style="font-size:14px;line-height:22px;"><code class="language-python hljs has-numbering"><span class="hljs-keyword">import multiprocessing
<span class="hljs-keyword">import time

<span class="hljs-function"><span class="hljs-keyword">def <span class="hljs-title">func<span class="hljs-params">(msg):
<span class="hljs-keyword">print multiprocessing.current_process().name + <span class="hljs-string">'-' + msg

<span class="hljs-keyword">if name == <span class="hljs-string">"main":
pool = multiprocessing.Pool(processes=<span class="hljs-number">4) <span class="hljs-comment"># 创建4个进程
<span class="hljs-keyword">for i <span class="hljs-keyword">in xrange(<span class="hljs-number">10):
msg = <span class="hljs-string">"hello %d" %(i)
pool.apply_async(func,(msg,))
pool.close() <span class="hljs-comment"># 关闭进程池,表示不能在往进程池中添加进程
pool.join() <span class="hljs-comment"># 等待进程池中的所有进程执行完毕,必须在close()之后调用
<span class="hljs-keyword">print <span class="hljs-string">"Sub-process(es) done."<ul class="pre-numbering"><li style="color:rgb(153,153);">9<li style="color:rgb(153,153);">10<li style="color:rgb(153,153);">11<li style="color:rgb(153,153);">12<li style="color:rgb(153,153);">13<li style="color:rgb(153,153);">14<p style="font-family:'-apple-system',255);">输出结果如下:

<pre class="prettyprint" style="font-size:14px;line-height:22px;"><code class="language-plain hljs lasso has-numbering">Sub<span class="hljs-attribute">-process(es) done<span class="hljs-built_in">.
PoolWorker<span class="hljs-subst">-<span class="hljs-number">34<span class="hljs-attribute">-hello <span class="hljs-number">1
PoolWorker<span class="hljs-subst">-<span class="hljs-number">33<span class="hljs-attribute">-hello <span class="hljs-number">0
PoolWorker<span class="hljs-subst">-<span class="hljs-number">35<span class="hljs-attribute">-hello <span class="hljs-number">2
PoolWorker<span class="hljs-subst">-<span class="hljs-number">36<span class="hljs-attribute">-hello <span class="hljs-number">3
PoolWorker<span class="hljs-subst">-<span class="hljs-number">34<span class="hljs-attribute">-hello <span class="hljs-number">7
PoolWorker<span class="hljs-subst">-<span class="hljs-number">33<span class="hljs-attribute">-hello <span class="hljs-number">4
PoolWorker<span class="hljs-subst">-<span class="hljs-number">35<span class="hljs-attribute">-hello <span class="hljs-number">5
PoolWorker<span class="hljs-subst">-<span class="hljs-number">36<span class="hljs-attribute">-hello <span class="hljs-number">6
PoolWorker<span class="hljs-subst">-<span class="hljs-number">33<span class="hljs-attribute">-hello <span class="hljs-number">8
PoolWorker<span class="hljs-subst">-<span class="hljs-number">36<span class="hljs-attribute">-hello <span class="hljs-number">9<ul class="pre-numbering"><li style="color:rgb(153,153);">11<p style="font-family:'-apple-system',255);">上述代码中的<code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">pool.apply_async()是<code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">apply()函数的变体,<code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">apply_async()是<code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">apply()的并行版本,<code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">apply()是<code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">apply_async()的阻塞版本,使用<code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">apply()主进程会被阻塞直到函数执行结束,所以说是阻塞版本。<code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">apply()既是<code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">Pool的方法,也是Python内置的函数,两者等价。可以看到输出结果并不是按照代码for循环中的顺序输出的。

<h1 style="padding:0px;font-family:'-apple-system',255);">多个子进程并返回值<p style="font-family:'-apple-system',255);"><code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">apply_async()本身就可以返回被进程调用的函数的返回值。上一个创建多个子进程的代码中,如果在函数<code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">func中返回一个值,那么<code style="font-size:14px;line-height:22px;padding:4px 2px 0px;">pool.apply_async(func,))的结果就是返回pool中所有进程的<span style="font-weight:700;">值的对象(注意是对象,不是值本身)。

<pre class="prettyprint" style="font-size:14px;line-height:22px;"><code class="language-python hljs has-numbering"><span class="hljs-keyword">import multiprocessing
<span class="hljs-keyword">import time

<span class="hljs-function"><span class="hljs-keyword">def <span class="hljs-title">func<span class="hljs-params">(msg):
<span class="hljs-keyword">return multiprocessing.current_process().name + <span class="hljs-string">'-' + msg

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

<span class="hljs-keyword"&gt;for</span> res <span class="hljs-keyword"&gt;in</span> results:
    <span class="hljs-keyword"&gt;print</span> (res.get())</code></pre><ul class="pre-numbering"&gt;<li style="color:rgb(153,153);"&gt;14</li><li style="color:rgb(153,153);"&gt;15</li><li style="color:rgb(153,153);"&gt;16</li><li style="color:rgb(153,153);"&gt;17</li><li style="color:rgb(153,153);"&gt;18</li></ul><p style="font-family:'-apple-system',255);"&gt;上述代码输出结果如下:</p><pre class="prettyprint" style="font-size:14px;line-height:22px;"&gt;<code class="language-plain hljs lasso has-numbering"&gt;Sub<span class="hljs-attribute"&gt;-process</span>(es) done<span class="hljs-built_in"&gt;.</span>

PoolWorker<span class="hljs-subst">-<span class="hljs-number">37<span class="hljs-attribute">-hello <span class="hljs-number">0
PoolWorker<span class="hljs-subst">-<span class="hljs-number">38<span class="hljs-attribute">-hello <span class="hljs-number">1
PoolWorker<span class="hljs-subst">-<span class="hljs-number">39<span class="hljs-attribute">-hello <span class="hljs-number">2
PoolWorker<span class="hljs-subst">-<span class="hljs-number">40<span class="hljs-attribute">-hello <span class="hljs-number">3
PoolWorker<span class="hljs-subst">-<span class="hljs-number">37<span class="hljs-attribute">-hello <span class="hljs-number">4
PoolWorker<span class="hljs-subst">-<span class="hljs-number">38<span class="hljs-attribute">-hello <span class="hljs-number">5
PoolWorker<span class="hljs-subst">-<span class="hljs-number">39<span class="hljs-attribute">-hello <span class="hljs-number">6
PoolWorker<span class="hljs-subst">-<span class="hljs-number">37<span class="hljs-attribute">-hello <span class="hljs-number">7
PoolWorker<span class="hljs-subst">-<span class="hljs-number">40<span class="hljs-attribute">-hello <span class="hljs-number">8
PoolWorker<span class="hljs-subst">-<span class="hljs-number">38<span class="hljs-attribute">-hello <span class="hljs-number">9<ul class="pre-numbering"><li style="color:rgb(153,255);">与之前的输出不同,这次的输出是有序的。

<p style="font-family:'-apple-system',255);">如果电脑是八核,建立8个进程,在Ubuntu下输入top命令再按下大键盘的1,可以看到每个CPU的使用率是比较平均的,如下图:

<p style="font-family:'-apple-system',255);">

八核CPU使用情況

<p style="font-family:'-apple-system',255);">在system monitor中也可以清楚看到执行多进程前后CPU使用率曲线的差异。?

CPU使用情況

转自:https://blog.csdn.net/jinping_shi/article/details/52433867

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读