有没有办法使用字典运行python多线程

时间:2017-01-31 04:40:50

标签: python multithreading python-multithreading

我想知道是否还有运行多个线程并将不同线程的结果分配给dict中的特定键。像这样:

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}

它假设是安全的,因为我写的是不同的键(没有重叠)。但是,我还没有找到一个例子。

3 个答案:

答案 0 :(得分:0)

如果你正在进行IO操作,那么你可以使用Threads,但是如果你完成CPU密集操作,你必须考虑GIL,所以我会处理。

如果您使用的是多处理库,我认为Pool是最适合您的对象,因为您希望控制执行线程的数量。为了执行该过程,您可以使用map或apply_async和回调函数。 您可以在此处阅读有关map vs 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()

答案 1 :(得分: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)

答案 2 :(得分: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的{​​{1}}方法,所以要解决这个问题,multiprocessing.Pool必须接受一个键/值元组并在映射函数中使用它。还提供了python 2替代方案。