以前瞭解過JAVA多線程多進程,python也學到過,但是就沒有遇到過具體的業務場景,最近要做一個文本匹配的任務,需要對70W條文本數據進行推薦相似度的計算,需要做一個全遍歷——也就是一個70W個元素的list遍歷的時候,和自身做一些相關的計算。list中的每個元素沒768維的向量,然後得出結果後,還需要排序,然後寫入文件存儲。這個場景就非常耗時,爲了減少消耗時間,在單機的環境下,就想到了並行。
python的多線程是假的多線程——由於GUI的原因,反正巴拉巴拉。。。就想着用 multiprocessing,這裏採用了簡單的Pool。開始直接上代碼:
datas=[]
for i in range(0,700000):
a = np.random.random((2,))
datas.append(a)
p=multiprocessing.Pool(4)
param=[]
for ele in tqdm(datas,desc='param:'):
t=(ele,datas)
param.append(t)
print('*'*10)
b = p.map(doSomething, param)
def doSomething(a,d):
# t1 = time.time()
# r=cdist([a],datas,"cosine")[0]#計算70W次cos值
# t2 = time.time()
# print('t2-t1:%4f' % (t2 - t1))
r=0
time.sleep(0.0001)
return r
把上面的70W次的for循環改寫成下面的多進程,運行直接報錯。錯誤在於pool.map(A,B)中的A是函數,B是函數的傳入參數,這個B只能是單個的。爲何我這裏錯了呢?這裏param是單個的呀!然而doSomething()函數有2個參數,代碼本身就有問題。改寫下面2種方式:
def do(param):
return doSomething(param[0],param[1])
def doSomething(param):
t1 = time.time()
r=cdist([param[0]],param[1],"cosine")[0]#計算70W次cos值
t2 = time.time()
print('t2-t1:%4f' % (t2 - t1))
r=0
time.sleep(0.0001)
return r
一種是函數嵌套,另一種是直接在doSomething()函數直接實現相應功能。
這裏最重要的一點就是加入要傳入多個參數的話,就必須把多個參數進行封裝,封裝成dic、tuple都行。然後再在函數裏面想辦法使用這些封裝的參數來實現功能。
最後看看耗時對比效果,這裏爲了能夠展示出效果,把裏面的計算cos的功能屏蔽掉,使用sleep()來代替——不代替的話,我這個機子要跑幾百個小時。
完整代碼:
'''
@Author : HY
@Software: PyCharm
@File : mutilprocess.py
@Time : 2019/9/18 23:45
@Desc :
'''
import time
import multiprocessing
from tqdm import tqdm
from scipy.spatial.distance import cdist
import numpy as np
def doSomething(a,d):
# t1 = time.time()
# r=cdist([a],datas,"cosine")[0]#計算70W次cos值
# t2 = time.time()
# print('t2-t1:%4f' % (t2 - t1))
r=0
time.sleep(0.0001)
return r
def do(param):
return doSomething(param[0],param[1])
if __name__ == '__main__':
datas=[]
for i in range(0,700000):
a = np.random.random((2,))
datas.append(a)
t1=time.time()
for e in tqdm(datas):
doSomething(e,datas)
t2=time.time()
print('t2-t1:%4f'%(t2-t1))
param=[]
for ele in tqdm(datas,desc='param:'):
t=(ele,datas)
param.append(t)
print('*'*10)
p=multiprocessing.Pool(4)
b = p.map(doSomething, param)
t1 = time.time()
b=p.map(do,param)
p.close()
p.join()
t2 = time.time()
print('t2-t1:%4f' % (t2 - t1))
結果:
單核CPU上需要12559秒,4核CPU上只需要362秒。效果很明顯!
參考:https://blog.csdn.net/qq_23869697/article/details/84975774