我想计算在列表列表中分隔所有可能对的元素的平均数量。以下脚本运行良好
from itertools import combinations
from operator import itemgetter
from collections import defaultdict
lst = [['A','D','B',],['A','M','N','B'],['A','C','B']]
elms = set(x for l in lst for x in l)
def test1():
d = defaultdict(list)
for i in lst:
combs = list(combinations(i, 2))
combs_sorted = [sorted(i) for i in combs]
for j in combs_sorted:
a = i.index(j[0])
b = i.index(j[1])
d[tuple(j)].append(abs((a+1)-b))
return(d)
d = test1()
d = {k: sum(v)/len(v) for k, v in d.items()}
for k,v in d.items():
print(k,v)
并且结果是期望的结果。
('A', 'D') 0.0
('A', 'B') 1.3333333333333333
('B', 'D') 2.0
('A', 'M') 0.0
('A', 'N') 1.0
('M', 'N') 0.0
('B', 'M') 3.0
('B', 'N') 2.0
('A', 'C') 0.0
('B', 'C') 2.0
但是,当列表和元素的数量显著增长时,该脚本会非常缓慢。我试着按照这个答案使用多处理
import multiprocess as mp
def init2(child_conn):
d = defaultdict(list)
for i in lst:
combs = list(combinations(i, 2))
combs_sorted = [sorted(i) for i in combs]
for j in combs_sorted:
a = i.index(j[0])
b = i.index(j[1])
d[tuple(j)].append(abs((a+1)-b))
child_conn.send(d)
def test2():
parent_conn, child_conn = mp.Pipe(duplex=False)
p = mp.Process(target=init2, args=(child_conn,))
p.start()
d = parent_conn.recv()
p.join()
return(d)
d = test1()
d = {k: sum(v)/len(v) for k, v in d.items()}
for k,v in d.items():
print(k,v)
但这个脚本似乎比前一个还要慢。
import time
t = time.process_time()
test1()
print(time.process_time() - t)
6.0000000000004494e-05
t = time.process_time()
test2()
print(time.process_time() - t)
0.017596
如何加快计算速度?
- 除非这只是一个玩具示例,否则我想知道你为什么要加快60 usec的计算
- 您只打开了一个子进程来完成所有的工作,因此不应该期望获得任何性能提升
-
即使你打开更多,打开多处理+管道的开销也比你计算的60 usec要大得多。
-
在以下情况下使用多处理是有效的:
- 您的基本计算比mp开销慢得多
- 当您有一个预先创建的工人池,等待通信来进行一些计算时。使用这种配置(主要在服务器上找到(,您只需支付通信费用(顺便说一句,通信时间也比您的60个usec长(
所以底线是,对于如此短的计算,只使用一个过程。