【Python】Python多程序庫multiprocessing中程序池Pool的返回值順序
問題起因
最近要將一個文字分割成好幾個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() # 等待子程序結束
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
上述程式碼中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."
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
輸出結果如下:
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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
上述程式碼中的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())
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
上述程式碼輸出結果如下:
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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
與之前的輸出不同,這次的輸出是有序的。
如果電腦是八核,建立8個程序,在Ubuntu下輸入top命令再按下大鍵盤的1,可以看到每個CPU的使用率是比較平均的,如下圖:
在system monitor中也可以清楚看到執行多程序前後CPU使用率曲線的差異。
轉自:https://blog.csdn.net/jinping_shi/article/details/52433867
相關推薦
【Python】Python多程序庫multiprocessing中程序池Pool的返回值順序
問題起因最近要將一個文字分割成好幾個topic,每個topic設計一個regressor,各regressor是相互獨立的,最後彙總所有topic的regressor得到總得預測結果。沒錯!類似bagging ensemble!只是我沒有抽樣。文字不大,大概3000行,top
【python】-socketServer多並發
服務 技術分享 tcp 就會 CP log 服務器 pytho 好用 多線程並發: 修改以上信息即可. 多並發:每來一個請求,服務器就會開一個線程。開啟這個線程和這個額連接進行交互。 多進程並發: ForkingTCPServer在linux上好用。 【pyth
【轉】python mysql數據庫 'latin-1' codec can't encode character錯誤問題解決
處理 tin sql數據庫 clas question ack RM can 意思 UnicodeEncodeError: ‘latin-1‘ codec can‘t encode character "UnicodeEncodeError:‘latin-1‘ co
【轉+】python為什麽推薦使用多進程
文件處理 自動切換 問題 決定 其他 意義 一個 strong 計算 最近在看Python的多線程,經常我們會聽到老手說:“Python下多線程是雞肋,推薦使用多進程!”,但是為什麽這麽說呢? 要知其然,更要知其所以然。所以有了下面的深入研究:
【leetcode】python演算法題庫
859. 親密字串 給定兩個由小寫字母構成的字串 A 和 B ,只要我們可以通過交換 A 中的兩個字母得到與 B 相等的結果,就返回 true ;否則返回 false 
【leetcode】python演算法題庫——簡單難度【2】
66. 加一 給定一個由整數組成的非空陣列所表示的非負整數,在該數的基礎上加一。 最高位數字存放在陣列的首位, 陣列中每個元素只儲存一個數字。 你可以假設除了整數 0 之外,這個整數不會以零開頭。 示例 1: 輸入: [1,2,3] 輸出: [1,2,4] 解
【leetcode】python演算法題庫——簡單難度【1】
1. 兩數之和 給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。 你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用。 示例: 給定 nums = [2, 7, 11, 15], target = 9 因為 nums[0] + nums[1] = 2
【leetcode】python演算法題庫——簡單難度【3】
118. 楊輝三角 給定一個非負整數 numRows,生成楊輝三角的前 numRows 行。 在楊輝三角中,每個數是它左上方和右上方的數的和。 示例: 輸入: 5 輸出: [ [1], [1,1], [1,2,1]
【python】python 常用的庫安裝
由於每次安裝python都要安裝很多包,因此將包安裝程式碼寫在下面,供以後安裝: pip install numpy pip install scipy pip install pillow pip install tensorflow pip install keras 清理系統垃圾 s
【python】詳解pandas庫的pd.merge_ordered與pd.merge_asof
merge_ordered: 函式允許組合時間序列和其他有序資料。 特別是它有一個可選的fill_method關鍵字來填充/插入缺失的資料。 import pandas as pd left = pd.DataFrame({'k': ['K0', 'K1', 'K1'
【python】詳解pandas庫的pd.merge函式
本篇詳細說明merge的應用,join 和concatenate的拼接方法的與之相似。 pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False
【python】詳解pymongo庫的使用
1、連線mongodb,建立client 傳入 ip 值或者 localhost ,埠是27017 import pymongo from pymongo import MongoClient client = MongoClient() #連線到本地 client = Mong
【整理】python學習筆記(5)-- pygame庫的函式和方法整理
PYGAME的方法和官方文件查詢 官方文件 http://www.pygame.org/docs/ 模組 簡介 pygame.BufferProxy An array protocol view
7、【Python】Python jpype呼叫java類庫
Python jpype 一、安裝 如果你安裝使用的是python 3.3及以上的版本,這些版本都內建了pip包管理器,你可以使用pip簡單快速的安裝jpype: pip install jpype1 二、呼叫java API 說明:在使用python jpyp
【python】詳解pandas庫的df.merge函式
本篇詳細說明merge的應用,join 和concatenate的拼接方法的與之相似。 pd.merge(left, right, how='inner', on=None, left_on=None,
【轉】python--Python中生成唯一ID的庫——UUID
原文連結https://www.douban.com/note/69073375/ 本來是要給例項新增唯一標識,想了一個偽隨機的方法: # 我想的偽隨機辦法 # 用時間戳和隨機數來生成唯一數字id import scipy
【python】離線安裝第三方庫
Anaconda 搜尋bz2安裝包: https://anaconda.org/ 某些以-C指定源安裝的包可能需要登陸 下載bz2檔案並執行命令: conda install --use-local *.bz2 pip 搜尋whl安裝包:https://pypi.o
【 專欄 】- Python 科學計算庫NumPy 完整教程
Python 科學計算庫NumPy 完整教程 NumPy 是 Python 在科學計算領域取得成功的關鍵之一,如果你想通過 Python 學習資料科學或者機器學習,就必須學習 NumPy。我認為 NumPy 的功能很強大,而且入門
【16】python使用turtle庫繪畫
畫蛇 import turtle def drawSnake(rad, angle, len, neckrad): # for i in range(len): turtle.circle(rad, angle) # 畫圓 rad:圓半徑 an
【python】詳解numpy庫與pandas庫axis=0,axis= 1軸的用法
對資料進行操作時,經常需要在橫軸方向或者數軸方向對資料進行操作,這時需要設定引數axis的值: axis = 0 代表對橫軸操作,也就是第0軸; axis = 1 代表對縱軸操作,也就是第1軸;