2017-01-31 1 views
0

Мне было интересно, есть ли способ запустить несколько потоков и назначить результаты различных потоков конкретным ключам в dict. Что-то вроде этого:Есть ли способ запустить многопоточность python с использованием словарей

from joblib import Parallel, delayed 
from math import sqrt 
dict_of_sqrt = {} 
i = {'a':1,'b':2,'c':3,'e':4} 
dict_of_sqrt[k] = Parallel(n_jobs=2)(delayed(sqrt)(v**2) for k, v in i.items()) 

Результат должен быть словарь с теми же ключами и назначены новые значения, рассчитанные в параллель:

dict_of_sqrt = {'a':1, 'b':1.41, 'c'=1.73, 'e'=2} 

Это, предполагают, чтобы быть в безопасности, потому что я пишу разные ключи (без перекрытия). Однако я не нашел примера.

+0

Обновлен вопрос. –

+0

Проверьте многопроцессорность и бассейн. Мертвый простой, но мощный. – taesu

ответ

0

Если вы выполняете операцию ввода-вывода, вы можете создавать потоки, но если вы закончите интенсивную работу с ЦП, вы должны принять во внимание GIL, поэтому я обработаю вместо этого.

Если вы используете многопроцессорную библиотеку, я думаю, что Pool - лучший объект для вас, поскольку вы хотите контролировать количество выполняемых потоков. Для выполнения процесса вы можете использовать либо map, либо apply_async с функцией обратного вызова. Вы можете прочитать больше о карте против apply_async здесь: Python multiprocessing.Pool: when to use apply, apply_async or map?

Я хотел бы использовать объект Queue для возврата данных в родительский процесс, как это многопроцессорных/поточно, но у него есть над головой идти по очереди и обработки результатов.

Вот краткий пример базового использования.

import multiprocessing 
from Queue import Empty 
from math import sqrt 
import string 



def my_sqrt(*args): 
    k, v, q = args[0] 
    q.put({k: sqrt(v)}) 

def main(): 

    p = multiprocessing.Pool(2) 
    m = multiprocessing.Manager() 
    q = m.Queue() 

    # This is just to generate data. 
    l = [(k, (v + 1)**2, q) for v, k in enumerate(string.lowercase)] 
    p.map(my_sqrt, l) 

    # Go over the Q 
    d = dict() 
    try: 
     while 1: 
      m = q.get_nowait() 
      d.update(m) 
    except Empty: 
     pass 

    print d 

if __name__ == '__main__': 
    main() 
0

Обновлено

from multiprocessing import Pool 
from time import sleep 
from random import choice 
import math 


# function that may take up to 5 seconds 
def myroot(t): 
    sleep(choice(range(5))) 
    return {t[0]:math.sqrt(t[1])} 

if __name__ == '__main__': 
    # dictionary keys -> n 
    # value should be n**2 
    d = {'a':1,'b':2,'c':3,'e':4} 
    dt = [(i,d[i]) for i in d] 
    # spawn 3 processes 
    pool = Pool(3) 
    # iterate all keys, feed them in sqr fuc 
    results = pool.map(myroot, dt) 
    # update object d, with result from each process 
    [d.update(i) for i in results] 
    print(d) 
+0

Спасибо. Мне нужны квадраты значений, а не ключи. –

+0

Вы не можете найти выше решение в соответствии с вашими потребностями? Это довольно просто. а также вы перепутали sqaured и root, то, что вы ищете, это root (n) – taesu

+0

Ответ был обновлен, вы можете его очистить – taesu

0

Вы можете иметь значения рассчитываться параллельно и возвращаются в виде пар кортежей, нового ключа и значения. В вызывающем процессе вам нужно только преобразовать его в словарь.

from math import sqrt 
from multiprocessing import Pool 

i = {'a':1,'b':2,'c':3,'e':4} 

# pass me to `starmap` 
def sqrtval(k, v): 
    return k, sqrt(v) 

# pass me to `map` 
def sqrtval_py2(kv): 
    k, v = kv 
    return k, sqrt(v) 

tup = Pool().starmap(sqrtval, i.items()) 
# tup = Pool().map(sqrtval_py2, i.items()) 

print(tup) 
print(dict(tup)) 

Python 2 не имеет метод starmap для multiprocessing.Pool, так бороться с этого sqrtval придется принять кортеж ключ/значение и использовать его в функции отображения. Также предоставляется альтернатива python 2.

Смежные вопросы