利用docker部署深度学习模型的一个最佳实践

编程狗在线

自由的编程学习平台

前言

最近团队的模型部署上线终于全面开始用上docker了,这感觉,真香!

讲道理,docker是天然的微服务,确实是能敏捷高效的解决深度学习这一块的几个痛点。

  1. 部分神经网络框架比如caffe依赖过重,安装困难。
  2. 各种网络模型未做工程化优化,部署困难。
  3. tensorflow等框架对GPU等硬件的占用难以灵活控制。

对于做应用来说,这些问题诸如对GPU的硬件的管理,对复杂依赖的部署,而这些正好就是docker的强项。而python本身表达能力强,可以以很短的代码量达成我们的目的。

部署

具体的部署步骤涉及这几个工具链:

  1. Dockerfile进行模型的镜像部署。
  2. docker-py进行container的启动和关闭。
  3. grpc和进行模型的外部通信。
  4. python的with语句表达模型的加载和资源的释放。
  5. gitlab进行内网的代码分发和版本控制。

整个接口的调用精简成面向对象的调用方式,with语句进入时启动模型,占用GPU,打开rpc调用端口,之后在调用结束后退出模型,释放资源,整个调用过程就简化成如下样子:

with Model_Docker() as sess:
    img = cv2.imread('demo.jpg')
    r = sess.run(img)
    print('result:',r,'type',type(r))

其中Model_Docker是这样的:

class CTPN_Docker(object):

    def __init__(self):
        self.client = docker.from_env()

    def get_container(self,client):
        container = client.containers.run(image = DEMO_IMAGE_NAME:TAG,
                    command = "python server.py",
                    runtime='nvidia',
                    environment = ["CUDA_VISIBLE_DEVICES=0"],
                    ports = {'8888/tcp':'8888'},
                    detach=True,
                    auto_remove = True)
        return container

    def __enter__(self):
        self.container = self.get_container(self.client)
        for line in self.container.logs(stream=True):
            if line.strip().find(b'grpc_server_start') >= 0:
                break
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.container.stop()
        print('container has stopped.')

    def run(self,img):
        assert isinstance(img,np.ndarray), 'img must be a numpy array.'
        imgstr = img.tobytes()
        shape = json.dumps(img.shape)
        stub = ctpn_pb2_grpc.ModelStub(grpc.insecure_channel('localhost:50051'))
        response = stub.predict(ctpn_pb2.rect_request(img=imgstr, shape=shape))
        return json.loads(response.message)

整个流程是这么个步骤:

  1. init方法获得docker client。
  2. get_container方法实例化一个container。
  3. with语句进入接口的enter方法,负责获取container实例和实例内模型启动结束的flag。
  4. with语句清理接口的exit方法,负责实例的关闭。
  5. run方法通过grpc调用docker内模型和返回结果。

docker-py是一个docker的python接口,docker除了cmdline的操作方式,还提供了REST的调用接口,docker-py就是其中一个很人性化的封装,具体使用可见官方文档。

container的实例化中有这几个地方需要注意:

  1. runtime需要用nvidia,与使用nvidia-docker效果一样。
  2. detach是后台模式,与-d效果一样。
  3. auto_remove是自动删除,与--rm效果类似。
  4. environment 来设定CUDA_VISIBLE_DEVICES。
  5. ports 来指定导出端口映射。

除了docker-py调用中的这些技巧,还有如下几个指令在构建过程中值得注意。

1、grpc的编译,这里没啥好说的,和grpc的官方说明文档里一样。

RUN python -m grpc_tools.protoc --python_out=. --grpc_python_out=. -I. mode.proto

2、docker image的构建,有时候构建需要添加--no-cache,避免远程资源更新了,docker构建却没重新。

docker build --no-cache -t name .

3、pip安装的时候需要添加几个参数,-r指定.txt安装,-i指定清华镜像为安装源,--no-cache-dir压缩docker镜像。

RUN pip install -r requirements_docker.txt -i https://pypi.tuna.tsinghua.edu.cn/simple --no-cache-dir

后记

这一轮AI浪潮扑腾到今天,也积累了大量可落地的框架和应用。不过在github欢快的clone代码的时候,一直注意到一些事。和web等领域不同的是,几乎所有模型几乎都是以源代码的形式分发的,很少有工程化的封装,更别说封装成库来部署了。就拿现在我在做的目标检测和文字识别的几个模型来说,yolo、fasterrcnn、ctpn和crnn等都是这样。

当然这也好理解,这些开源作品基本都是大佬在水文章之余写的,而且一个完整的模型包括训练、测试和预测,模型在公开数据集上的训练效果才是关键,工程化的问题并不是最重要的事情,不过我还是想吐槽一下。

比如fasterrcnn中训练数据是写死的,准备好训练集后得通过一个软连接将训练集和训练数据替换掉。这还不是最毒瘤的,较新的ctpn是继承自fasterrcnn,也是采用这种方法.

又比如在导入数据阶段也是各用各的法子,这些做法有往往采用多线程和多进程,结果管理不好,一大堆死线程不说,还经常把cpu跑满,用过的模型中darkflow和east都有这样的问题。

还有在写inference是,还常常遇到需要修改输入输出tensor的情况,在输入端加placeholder,稍微对tensorflow不熟,同时还需要修改一些在预测阶段有所改变的tensor。确实是很不人道。

最后想提一点,这种部署方式除了部署时灵活方便,另外一个额外的好处就是使用jupyter时也方便,在jupyter使用时最常见的问题有两个,一个是需要经常使用set_env去设置CUDA_VISIBLE_DEVICES,另一个是用完了得把notebook关掉,不然jupyter进程会一直占用GPU。

作者:丁果,对django、pyqt、opencv、tornado感兴趣。

GitHub:https://github.com/lidingke

投稿邮箱:pythonpost@163.com

欢迎点击申请成为专栏作者:Python中文社区新专栏作者计划

Python中文社区作为一个去中心化的全球技术社区,以成为全球20万Python中文开发者的精神部落为愿景,目前覆盖各大主流媒体和协作平台,与阿里、腾讯、百度、微软、亚马逊、开源中国、CSDN等业界知名公司和技术社区建立了广泛的联系,拥有来自十多个国家和地区数万名登记会员,会员来自以公安部、工信部、清华大学、北京大学、北京邮电大学、中国人民银行、中科院、中金、华为、BAT、谷歌、微软等为代表的政府机关、科研单位、金融机构以及海内外知名公司,全平台近20万开发者关注。

原文发布于微信公众号 - Python中文社区(python-china)

原文发表时间:2018-09-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏人工智能头条

机器学习数据采集入门经验分享

1234
来自专栏Kotlin入门系列

师万物博客的历程(总)

1684
来自专栏灯塔大数据

每周学点大数据 | No.77 众包算法实践——成为众包工人

编者按:灯塔大数据将每周持续推出《从零开始学大数据算法》的连载,本书为哈尔滨工业大学著名教授王宏志老师的扛鼎力作,以对话的形式深入浅出的从何为大数据说到大数据算...

44911
来自专栏恰童鞋骚年

操作系统核心原理-6.外存管理(上)磁盘基础

  计算机是处理数据的机器,而数据就需要有地方存放。在计算机中,可供数据存放的地方并不太多,除了内存之外,最主要的存储数据的媒介就是磁盘。对于大多数计算机领域的...

1571
来自专栏科研利器

如何下载文献全文&快速找到文献DOI号【史上最强总结】

之前,本公众号推送过一个免费秒下学术文献的神器 SciHub Desktop,只需要将文献的 DOI 号输入进去再点击按钮就可以立马获取 PDF 全文,这款软件...

10.1K14
来自专栏云成本管理

云成本管理方法论(二)——云使用管理

本篇文章将基于云成本管理模型对云使用管理中四个管理维度(管理对象、管理时点、判定规则和管理措施)进行更具体的分析。

4905
来自专栏人工智能LeadAI

深度学习训练时GPU温度过高?几个命令,为你的GPU迅速降温。

新买回来的不带水冷公版GPU,在满负载运行的时候,温度从室温马上飙升到85度,而且模型训练不是几分钟完事,很有可能要长期保持在高温状态下运行,让如此昂贵的GPU...

5967
来自专栏张善友的专栏

CAP理论十二年回顾:"规则"变了

CAP理论断言任何基于网络的数据共享系统,最多只能满足数据一致性、可用性、分区容忍性三要素中的两个要素。但是通过显式处理分区情形,系统设计师可以做到优化数据一致...

2929
来自专栏企鹅号快讯

PowerStager:一款拥有独特混淆技术的恶意工具正在崛起

“用指尖改变世界” ? Palo Alto Networks公司警告说,自2017年4月以来,一种恶意工具已经成为人们关注的焦点之一。这主要原因是由于它采用了相...

2247
来自专栏量子位

捡漏!用谷歌图片搜索自制深度学习数据集 | 教程

就怕前脚刚立志搞个新研究,后脚就发现没有合适的数据集可用。AI工程师从入门到放弃,可能就是这么一会的功夫。

1601

扫码关注云+社区

领取腾讯云代金券