python多进程逐对比较文档相似度+均分比较次数
程序员文章站
2022-05-02 13:19:13
...
多进程提高运算效率
最近用python做数据处理,363个文件逐对比较相似度,总共65703次。之前学习神经网络发现cpu使用率只有30%多,应该是只用了一核,这次计算密集型任务,用多进程跑下看看提速效果。先把分析对象拆成多份,让每份的数量基本均匀,然后多线程跑,风扇果然嗡嗡起来了。下面是一个小样本量的测试结果,由于每次比对的计算量不同,所以效率不会是线性提升,我做了一个计算量相同的测试,效率也不是线性提升的,不是简单的多用一核就能提高一倍效率,这个好理解。总cpu使用率相对每个cpu使用率是线性累加的。我的cpu是i7-7500U CPU @ 2.70GHz~2.90G,双核双线程四个逻辑核。三个线程基本就跑满了。对于大数据量的场景,多线程的威力就发挥得更明显了。
我有一次跑的过程中报错了,没细看,里面有pandas的内容,直觉是多进程可能不稳定,后面再跑没遇到过。
运行环境 | 进程数 | 总cpu使用率 | 每进程cpu使用率 | 耗时(s) |
---|---|---|---|---|
ubuntu子系统 | 1 | 37% | 32 | 94 |
ubuntu子系统 | 2 | 65% | 31 | 67 |
ubuntu子系统 | 3 | 96% | 30 | 60 |
ubuntu子系统 | 4 | 100% | 24 | 57 |
细致比较多进程
364个文件逐对比较,总共比较次数为66066
进程 | 起始时间戳 | 处理条数 | 耗时(s) |
---|---|---|---|
1个进程 | - | - | - |
进程1 | 1528290177.8083532 | 66066 | 19.36804223060608 |
总 | 66066 | 19.423198461532593 | |
2个进程 | - | - | - |
进程1 | 1528290066.5728095 | 33153 | 10.518495559692383 |
进程2 | 1528290066.5882878 | 32913 | 10.646009922027588 |
总 | 66066 | 10.698017120361328 | |
3个进程 | - | - | - |
进程1 | 1528289094.8444376 | 22011 | 9.382812976837158 |
进程2 | 1528289094.8605711 | 22110 | 9.47968602180481 |
进程3 | 1528289094.8762245 | 21945 | 9.627197742462158 |
总 | 66066 | 9.712886095046997 | |
4个进程 | - | - | - |
进程1 | 1528289148.3423731 | 16302 | 9.519663095474243 |
进程2 | 1528289148.3572035 | 16611 | 9.670548915863037 |
进程3 | 1528289148.376095 | 16471 | 9.6192147731781 |
进程4 | 1528289148.3954604 | 16682 | 9.710239171981812 |
总 | 66066 | 9.799142360687256 |
结论:1个进程到2个进程接近线性提升,3个进程提升微弱,4个进程反而比3个进程更慢。
多进程代码
if __name__ == '__main__':
start = time.time()
# 进程安全的列表
result = Manager().list()
# 下面均分函数的输出
shred = [(0, 49), (49, 106), (106, 182), (182, 364)]
# 将进程添加进列表
task = []
for i in shred:
task.append(Process(target=compare, args=(i[0], i[1], result)))
# 逐个启动进程,不要把join直接写在start后面,那样就成单进程了
for i in task:
i.start()
# 进程全部阻塞以后再打印列表
for i in task:
i.join()
for i in result:
print(i)
print(time.time() - start)
均分比较次数
n个文件逐对比较总共比较len(list(itertools.combinations(range(100),2)))
次,写了一个均分比较次数的函数,比较弱,但还好使。我觉得这可以作为一道面试题。
"""
"""
均分比较次数
输入:file-文件数量 shred-份数
输出:列表,元素是分段起止位置组成的元祖
"""
def find_div_pos(file, shred):
s = sum(range(file))
point = [s * i / shred for i in range(1, shred + 1)][:-1]
result = []
for p in point:
accu = file - 1
# 倒着迭代是为了更快找到切分点
# 每次都从头开始迭代影响效率,但是可以忽略
for i in range(file - 2, 0, -1):
accu += i
if abs(accu - i - p) > abs(accu - p) < abs(accu + i - 1 - p):
result.append(file - i)
break
return list(zip([0] + result, result + [file]))
re = find_div_pos(364, 4)