【Tensorflow1.x和Keras】Flask作为网页后端批量接收同步上传的图片 分别使用多线程和多进程加载并使用训练好的模型进行预测(推荐使用多线程)

后端使用多线程预测

我们使用多线程进行预测时只需要执行一次网络参数的初始化,从而达到 “拥有较快检测速度”的目标,但是主进程会一直占用GPU资源,这是因为目前GPUDevice中的Allocator属于ProcessState,它本质上是一个跟随着进程的全局单例。在进程中使用GPU的第一个会话初始化它,并分配显存资源,在进程关闭时释放进程占用的资源,不然这个进程会一直占用这些资源。为了不让预测后程序中的tf一直占用显存,我们选择在子进程中进行预测,因为子进程中使用的GPU资源会随着子进程结束而释放。如果在主进程中直接使用predict函数,即使predict函数执行结束也会一直占用着显存,直到主进程结束才能释放它占有的GPU资源。这样做有一个好处,就是我们在网页后端主进程的Keras开始时会加载一个全局session,我们在这个session中初始化模型权重,这样它的所有子线程都可以使用这个session,因为多线程是在一个主进程中运行的,这样的话我们只需要在主进程开始时创建一个session,并初始化模型权重,就可以使用这个模型在这个进程的所有子线程中使用,每次预测都不需要重新加载模型权重。

还有一个不可忽视的问题是,flask默认情况下使用的是多线程模式解决高并发问题,而在不同线程中默认的graph是不一样的(其实单纯使用Tensorflow时,不同线程的session也会不一样,那时候我们要为不同线程指定同一个session,但是Keras在主进程中创建了一个全局session,能覆盖所有子线程,所以使用Keras时不需要担心子线程的session不同,我们只需要担心graph不同就可以)。出于TensorFlow的session对象是支持多线程的,我们可以在同一个会话(session)中创建多个线程并行执行,因此,通过创建一个全局图(global graph)并将其设置为在每个子线程中使用。关于此问题在stackflow上的参考链接,代码实现如下:

创建一个全局默认的图,并在Keras的全局session下创建一个model,这个model在创建后就立刻使用训练好的参数初始化网络参数。

其中load_model()函数用于加载模型。

从文件数组中读取出每张图像,并为这张图像的分类预测创建一个线程。我们需要等所有线程都执行完毕,才能返回结果,所以这里使用wait函数等待所有线程结束再return。在多线程指定的函数中,我们向predict中传入已经加载好的全局model,所以不需要再次初始化模型权重,这样可以节省大量的时间。在最终测试中,使用多线程预测12张图像仅需4秒(因为我的电脑显存只有2GB,所以会比较慢一些)。

后端使用多进程预测

实践表明,Keras维护的session不是进程安全的,即我们需要在我们创建的子进程中重新建立一个属于子进程的session,并为其分配GPU资源,否则在主进程中的session将会被他的子进程共享,最终导致死锁,程序会出现一些“莫名奇妙的bug”,比如说无限初始化模型权重。

为每个子进程都建立一个属于他的session,这意味着每个子进程都要重新加载网络,并初始化模型权重,这是十分耗费时间的,起码在我的电脑上,模型加载训练好的权重需要30秒左右,这就意味着一张图像的处理最快也要30多秒,这是不可接受的,好在,我们的目的达成了,采用多进程的程序会预测一次释放一次GPU资源。代码实现如下:

开始时我们只创建一个全局默认的图,一个图可以在多个session中执行,而一个session只能同时执行一个图,因为多进程不能共享session,所以不能共享网络模型参数,不能使用同一个model。

在这里我们采用执行完一个子进程才能执行下一个子进程的策略,不然程序会同时为多个子进程分配GPU显存,这样程序会报“显存不足”的错误。可以看到上面报错的内容是“不能创建session”,下面的提示是“内存错误”,不能创建session的原因就是不能分配给session足够多的GPU显存。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值