使用多个参数的字典使旧代码单线程代码适应多处理

Posted

技术标签:

【中文标题】使用多个参数的字典使旧代码单线程代码适应多处理【英文标题】:Adapting old code single-thread code to multiprocessing using a dictionary for multiple arguments 【发布时间】:2019-12-02 00:02:13 【问题描述】:

我有以下函数来并行化一些任务:

def parallelize(func, variable_args, proc_count=None):
    if proc_count is None:
        proc_count = multi.cpu_count()

    warnings.warn('You have n_cpu CPU. Tasks will be distributed over all.'.format(n_cpu=proc_count))

    pool = multi.Pool(processes=proc_count)
    result = pool.map(func, variable_args)
    pool.close()
    pool.join()
    return result

我有一堆看起来像这样的旧函数:

def some_old_function(that_,takes_,lots_of_,arguments_):
    do_stuff_single_thread()

到目前为止,我为“并行化”这些函数所做的工作是将它们重新编码为如下所示:

def some_old_function(dict_arg):
     that_ = dict_arg['that']
     takes_= dict_arg['takes_']
     ...
     do_stuff_single_thread()

最后调用:

parallelize(some_old_function, list_of_dict_args)

我之所以写,是因为我担心必须有一种比我上面选择的方式更“pythonic”的方式来做到这一点。

感谢我收到的任何建议。

【问题讨论】:

【参考方案1】:

这是完全可用的。鉴于池工作者只接受一个参数,如果您在工作者内部调用的函数需要多个参数,则必须将其设为某种数据结构。

您也可以使用元组而不是字典,然后使用星号运算符。这使得调用更容易:

Python 2.7.16 (default, Apr 11 2019, 01:11:37) 
Type "help", "copyright", "credits" or "license" for more information.
>>> def test(a,b,c):
...     print a, b, c
... 
>>> args = (1, 2, 3)
>>> test(*args)
1 2 3

在这种情况下,您不必手动解压缩字典。但是您必须确保元组中的参数顺序正确且数量正确...

【讨论】:

【参考方案2】:

另一种涉及较少重写的方法是将您的单个参数的可迭代项(所有that_s、所有takes_s、所有lots_s 等各一个)、zip 放在一起,然后使用Poolstarmap 方法,将tuples 解包为顺序位置参数。

或者,与其重新编码 some_old_function,不如制作一个简单的包装器,将 dict 解包为“真实”函数,例如

def some_old_function_wrapper(kwargs):
    return some_old_function(**kwargs)

您仍会像当前设计一样传递您的 list_of_dicts,但 some_old_function 将保持不变,并且您将让 Python 进行解包(这将比逐个参数查找的显式参数更快、更清晰)。

【讨论】:

以上是关于使用多个参数的字典使旧代码单线程代码适应多处理的主要内容,如果未能解决你的问题,请参考以下文章

多线程编程

java多线程

API的理解和使用——单线程架构

为什么 Redis 是单线程的?

多线程比单线程慢

Javascript单线程实现