以前了解过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秒。效果很明显!