python多进程使用

最近在部署模型的时候发现需要多进程功能充分利用机器性能,提高推理的效率。因此研究了一下python的多进程操作,发现只需要短短的几行代码,非常方便,在此记录一下。

利用processing包的进程池可以非常方便地构建,下面便是processing包使用的基础信息:

在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。多进程是实现并发的手段之一,需要注意的问题是:

1、很明显需要并发执行的任务通常要远大于核数

2、一个操作系统不可能无限开启进程,通常有几个核就开几个进程

3、进程开启过多,效率反而会下降(开启进程是需要占用资源的,而且开启多余核数目的进程也无法做到并行)

例如当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态生成多个进程,十几个还好,但如果是上百个上千个,手动的去限制进程数量却又过于繁琐,此时可以发挥进程池的功效。

我们就可以通过一个进程池来控制进程数目,比如http的进程模式,规定最小进程数和最大进程数。。。

ps:对于远程过程调用的高级应用程序而言,比如使用进程池,Pool可以提供指定数目的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,就重用进程池中的进程。

创建进程池的类:如果指定numprocess为3,则进程池会从无到有创建三个进程,然后至始至终使用这三个进程去执行所有任务,不会开启其他进程

Pool([numprocess [,initializer [, initargs]]]):创建进程池

参数介绍

numprocess:要创建的进程数,如果省略,将默认使用cpu_count()的值
initializer:是每个工作进程启动时要执行的可调用对象,默认为None
initargs:是要传给initializer的参数组

方法介绍:

p.apply(func[, args[, kwargs]]):在一个池工作进程中执行func(*args,**kwargs),然后返回结果。需要强调的是,此操作并不会在所有池工作进程中并执行func函数。如果要通过不同参数并发地执行func函数,必须从不同线程调用p.apply()函数或者使用p.apply_async()
p.apply_async(func [func [, args [, kwargs]]]):在一个池工作进程中执行func(*args,**kwargs),然后返回结果。此方法的结果是AsynResult类的实例,callback是可调用对象,接收输入参数。当func的结果变为可用时,将理解传递给callback。callback禁止执行任何阻塞操作,否则将接收其他异步操作中的结果。

p.close():关闭进程池,防止进一步操作。如果所有操作持续挂起,他们将在工作进程终止前完成
p.join():等待所有工作进程退出,此放大只能在close()或reminate()之后调用

代码示例:

def mission(param):
    '''
    任务
    :param param:
    :return:
    '''
    id, content = param
    t_start = time.time()
    log.info("开始执行子进程:{}".format(id))
    update_sql = ("update video set status='DOING' where id={}".format(id))
    db.execute(update_sql, commit=True)
    #执行进程任务
    try:
        # val = os.system("./sh")
        print('文本内容:{}'.format(content))
        time.sleep(random.random()*2)
        t_stop = time.time()
        log.info("进程{}执行完成, 执行用时{}".format(param, t_stop-t_start))
        #更新数据库任务状态,已完成状态
        update_sql = ("update video set status='DONE' where id={}".format(id))
        db.execute(update_sql, commit=True)
    except Exception as e:
        log.error('error:{}'.format(e))
        update_sql = ("update video set status='FAILED' where id={}".format(id))
        db.execute(update_sql, commit=True)

log = Logger('../test.log').logger
# sql_log = Logger('../sql.log').logger

def main(items, pool):
    '''
    启动进程
    :return:
    '''
    res = []
    if not items:
        log.info("未查询到任务,休眠2s")
        time.sleep(2)
        return res
    for i in items:
        res.append(pool.apply_async(func=mission, args=(i,), callback=cb()))

    return res

我的代码功能中misson就是每一个进程需要执行的任务,然后在main函数中将所有等待执行的任务加入到进程池中,开始执行。

需要注意的点:

p.join()是等待本次所有任务执行完成后退出进程,后续如果启动进程需重新启动,如果需要持续添加任务的时候不用加。

在调试的时候进程的日志需要打印出来,不然很难发现哪个步骤出了问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值