Обновить словарь списков в многопроцессорной - PullRequest
0 голосов
/ 23 октября 2019

Я хочу вычислить среднее количество элементов, которые разделяют все возможные пары в списке списков. Следующий скрипт прекрасно работает

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

Как я могу ускорить этот расчет?

1 Ответ

0 голосов
/ 24 октября 2019
  1. Если только это не для иллюстрации игрушечного примера, мне интересно, почему вы удосуживаетесь ускорить вычисление 60 усек.
  2. Вы открываете только один дочерний процесс, который выполняет всю работу, поэтому прирост производительности не долженможно ожидать.
  3. Даже если вы открываете больше, накладные расходы на открытие многопроцессорной обработки + труба значительно больше по сравнению с крошечными 60-ю единицами расчета.

  4. Использование многопроцессорной обработки эффективно, когда:

  5. ваш базовый расчет намного медленнее, чем накладные расходы mp.
  6. , когда у вас есть предварительно созданный рабочий пул, ожидающий соединениякакой-то расчет. В этой конфигурации (в основном на серверах) вы платите только за связь (которая, кстати, тоже длиннее, чем ваши 60 пользователей).

Итак, в итоге, для такого короткого расчета,остаться с одним процессом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...