python使用deco进行多进程编程

装饰并发

一个简化的Python并行运算模型。仅需最少的现有串行程序修改,DECO就能自动并行化Python程序,

使用pip安装

pip install deco

通常用法

使用DECO简单得就像是在你的Python程序里查找或者创建两个函数一样简单。第一个函数是我们想要并发运行的,并且使用@concurrent装饰。第二个函数是调用@concurrent并且使用@synchronized装饰的。第二个函数的装饰是可选的,但提供了一些非常酷的好处。让我们来看一个例子。

@concurrent # We add this for the concurrent function
def process_lat_lon(lat, lon, data):
  #Does some work which takes a while
  return result

@synchronized # And we add this for the function which calls the concurrent function
def process_data_set(data):
  results = defaultdict(dict)
  for lat in range(...):
    for lon in range(...):
      results[lat][lon] = process_lat_lon(lat, lon, data)
  return results

就这样,为了并行化这个程序只有两行代码的修改。现在这个程序运行时将会使用机器上的所有cpu核心,使它运行地明显变快。

它做了什么

  • @concurrent装饰器使用multiprocessing.pool来并发调用目标函数。
  • 索引是基于自动处理的函数参数的变种,这是进程池做不到的
  • @synchronized装饰器自动插入同步性事件
  • 在同步性事件期间,它也自动重构了@concurrent函数调用的结果赋值。

局限性

  • @concurrent只能给那些运行时间长于~1ms的函数提速
    • 如果他们需要的时间更少,你的代码将会运行地更慢!
  • @synchronized装饰器只能在"简单"函数上生效,确保函数符合下面的条件
    • 仅仅调用,或者分配@concurrent函数的结果到像下面这样的可索引对象:
      • concurrent(...)
      • result[key] = concurrent(...)
    • 没有间接读取由调用@concurrent函数分配的对象

它是如何工作的

对工作机制的深入探讨,我们写了一篇论文。你可以在这里找到

作为一个概述,DECO只主是给Python的multiprocessing.pool做了智能封装。当@concurrent被 应用在一个函数时,它使用pool.apply_async调用来替代这个函数。此外,当参数被传给pool.apply_async时,DECO使用代 理来替换索引可变对象,便它能检测这些对象的变化。这些调用的结果之后可以通过在并发函数上调用wait()和唤起一个同步事件来获取。这些事件可以在调 用@concurrent函数的函数上使用@synchronized装饰器来自动放置在你的代码里。此外,当使用@synchronized,你可以直接赋值并发函数的调用结果到索引可变对象。DECO重构这些赋值自动发生在下一个同步事件期间。所有这一切意味着在许多情况下,使用DECO的并行编程完全像串行编程一样简单。

原文地址:https://github.com/alex-sherman/deco

简单的示例:

#!/usr/bin/env python
# encoding: utf-8

"""
@version: ??
@author: Licamla
@license: 
@contact: licamla@live.cn
@project: test
@software: PyCharm Community Edition
@file: test.py
@time: 16-5-15 下午8:23
"""
import os

import time
from deco import concurrent, synchronized

temp_dict = {}
for i in range(20):
    temp_dict[i] = '{}pid'.format(i)


@concurrent
def test_concurrent(input_):
    print(input_, os.getpid())
    time.sleep(5)
    return input_, os.getpid()


@synchronized
def test_synchronized():
    result = {}
    for k, v in temp_dict.items():
        result[k] = test_concurrent(v)
    return result


if __name__ == '__main__':
    print(test_synchronized())

运行结果:

0pid 18689
1pid 18690
2pid 18692
3pid 18691
4pid 18693
5pid 18694
6pid 18695
7pid 18696
8pid 18693
9pid 18689
10pid 18690
11pid 18696
12pid 18691
13pid 18692
14pid 18695
15pid 18694
16pid 18689
17pid 18690
18pid 18693
19pid 18692
{0: ('0pid', 18689), 1: ('1pid', 18690), 2: ('2pid', 18692), 3: ('3pid', 18691), 4: ('4pid', 18693), 5: ('5pid', 18694), 6: ('6pid', 18695), 7: ('7pid', 18696), 8: ('8pid', 18693), 9: ('9pid', 18689), 10: ('10pid', 18690), 11: ('11pid', 18696), 12: ('12pid', 18691), 13: ('13pid', 18692), 14: ('14pid', 18695), 15: ('15pid', 18694), 16: ('16pid', 18689), 17: ('17pid', 18690), 18: ('18pid', 18693), 19: ('19pid', 18692)}

 

本文地址:http://my.oschina.net/soarwilldo/blog/675441

转载于:https://my.oschina.net/soarwilldo/blog/675441

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值