我们经常要将数组映射为另一个数组,但效率太低。
例如 map( func, data_list ) 或者 [ func(e) for e in data_list ]
def func(element):
# 进行函数映射
return element
data_list = ["element 1", "element 2", "element 3", "element n"]
res_list1 = [func(e) for e in data_list] # 方法1
res_list2 = map(func, data_list) # 方法2
但是由于没有开启多进程并行处理,当数据量非常大时,效率太低,因此我们考虑设计一个多进程数组映射方法。
效果:
使用jieba分词,对5万条文本进行分词处理,普通方法用时800s,而采用6进程并行处理只有290s。
对比 | 普通 | 多进程 |
用时 | 800 | 290 |
进程数 | 1 | 6 |
步骤:
初始变量:数据集data_list;映射函数func
假设开启n个进程处理。
1、先将data_list分割为n份
2、利用mutiprocessing对每一份处理
3、按原始顺序收集每一进程返回的结果
代码:
直接调用multiRun(jobList, func, params, coreNum)方法
其中params是个hashset数据结构,用于传参,不需要的话赋予{}值即可。
# 分割数组
def divJobList(jobList, coreNum=1):
res = []
length = len(jobList)
left = length % coreNum
right = coreNum - left
step = int(length / coreNum)
for i in range(right):
res.append(jobList[:step])
jobList = jobList[step:]
step += 1
for i in range(left):
res.append(jobList[:step])
jobList = jobList[step:]
return res
# 映射函数
def func(params):
jobList = params['jobList']
return [e for e in jobList] # 这里是你要对jobList实现的方法:
# 子任务
def subRun(idx, returnDict, func, params):
returnDict[idx] = func(params)
# 主任务
def multiRun(jobList, func, params, coreNum=1):
pool = Pool(coreNum)
returnDict = Manager().dict()
groupJobList = divJobList(jobList, coreNum)
for idx in range(coreNum):
newParams = params.copy()
newParams['jobList'] = groupJobList[idx]
pool.apply_async(func=subRun, args=(idx, returnDict, func, newParams))
pool.close()
pool.join()
res = []
for idx in range(coreNum):
res += returnDict[idx]
return res
在另一篇讲了jieba多进程分词
https://blog.csdn.net/qq_28969139/article/details/96611096
有兴趣可以看看