五月31日
update: 更新了Step 7&8的路径问题
之前写的时候,没有注意到在pycharm的帮助文档中Configuring Remote Interpreters via Docker的一段话:
Docker Machine on Linux does not share user home folder, and any other folders as well. Thus, for running, debugging and profiling applications, the user should add shared folders with the project sources to the VirtualBox Docker virtual machine manually. These shared folders on VM should be mapped one to one to the folders on the host Linux machine, i.e. (host) /home/user <=> /home/user(VM) or (host) /home/my/project <=> /home/my/project (VM)
所以Pycharm docker只把当前工作目录映射到container里面,如果你要读取你host机器上的数据的话需要手动添加目录,具体做法我写在 steps 8 中。
————————————————–分割线—————————————————————-
Problem Formulation
在上回
Docker–深度学习环境配置一站式解决方案 – 知乎专栏中,我简要介绍了Docker的概念,如何使用别人上传到Docker Hub的镜像Image,以及如何利用NVIDIA的Docker插件在Docker container中调用本地GPU。根据我的实验表明,利用上一篇文章中的方法,运行效率和原生环境一致,nvidia-docker插件并不影响GPU的计算速度以及数据传输。
但是我在上篇中只介绍了利用命令行和notebook开发的方法,只适合跑demo和实验,对于有多个模块并行开发的大型Python工程可能不太方便。这一篇中,我想介绍如何在本机运行的pycharm里直接调用Docker container里面的Python解释器,这样一来,你既可以充分利用现有的Docker image资源,同时能够发挥Pycharm IDE里的强大功能(比如自动补全,断点调试等等)。
如果觉得有用,请各位看官老爷点赞转发 :) 。
Objective
在上一篇的基础上,我有一个安装了所有深度学习框架的Docker image。现在我想在Pycharm中完成我的所有python代码,点击运行的时候,Pycharm可以调用那个image的python interpreter来执行我的代码。同时我还希望它能自动调用GPU,自动代码补全,而且我还很懒,不想修改任何本机环境。
Ingredients
Ubuntu intel架构,Docker, nvidia-docker插件, 我写的docker image
请参考前作 Docker–深度学习环境配置一站式解决方案 – 知乎专栏
Pycharm
熟悉Python开发的人应该都听说过这个IDE,我就不过多介绍了,只想说JetBrains不亏是被Google选中的公司,他们自己开发和维护的许多项目都堪称业界良心。需要注意的是我接下来要介绍的功能需要Pycharm Pro版。什么?没钱?没问题,都说了是业界良心,只要你有一个academic email都可以到这免费申请:Free for Students: Professional Developer Tools from JetBrains。
docker-compose是Docker里的另一个强大功能,简单来说就是你有了Image和你的App后,通过一个compose文件可以告诉Docker每次以什么方式开启你的container。在这里我们只要利用其中一个很小的功能,即每次我在Pycharm中运行一个python文件的时候,run 一个我指定的image,并利用这个运行的container里的python解释器来运行我Pycharm里的Python代码,代码运行结束后container自动退出。当然,我们做深度学习的还是希望container能调用GPU,所以用的是nvidia-docker-compose。
Steps
- (Optional)更新系统
在Ubuntu中,如果要安装什么,我习惯先跑两个命令更新系统:sudo apt-get -y update sudo apt-get -y upgrade
- 安装 nvidia-docker-compose
如果你已经如上篇所述在你的主机上安装好Docker,nvidia-docker以及cuda驱动,那么你只要通过以下命令pip install nvidia-docker-compose
就可以安装nvidia-docker-compose和原生的docker-compose,注意我这里的pip是anaconda2版本,所以docker-compose会被安装在 ~/anaconda2/bin/docker-compose 中,我没有测试过其它版本的pip。
生成compose文件
安装nvidia-docker-compose好后,按顺序执行以下命令,就可以在你的home目录下创建一个目录compose,cd mkdir compose cd compose touch docker-compose.yml
用你的editor打开docker-compose.yml,把下面的内容复制进去,保存。
version: '2' services: dl: image: yiminglin/dl-image
这段话的意思是这个每次运行这个compose文件,我就启用一个service名叫dl,dl只指定了我要run的image是哪个。
在当前compose目录中,运行nvidia-docker-compose -G
会发现文件夹中多了一个nvidia-docker-compose.yml,里面的内容如下:
services: dl: devices: - /dev/nvidia0 - /dev/nvidiactl - /dev/nvidia-uvm - /dev/nvidia-uvm-tools image: yiminglin/dl-image volumes: - nvidia_driver_375.51:/usr/local/nvidia:ro version: '2' volumes: nvidia_driver_375.51: external: true
可以看到它只是把我们写的compose文件丰富了一下,加入了nvidia的一些服务。
- Pycharm Docker Setting
在pycharm中新建一个工程,进入File->Setting->Build,Excution,Deployment找到Docker,然后按加号添加一个Docker服务器。注意把Certificates folder 清空,Docker Compose excitable选择你第2步安装的docker-compose
- Pycharm工程中添加remote intepreter
在Setting里选择你的Project Interpreter,点击右边的齿轮,选择 Add Remote
选择最后一个Docker Compose,按加号添加第3步生成的nvidia-docker-compose.yml文件
按ok,可以看到Project Interpreter 里多了一个可选的解释器:Remote Python 2.7.12 Docker Compose (dl at [/home/yiming/compose/nvidia-docker-compose.yml])
按ok后可能需要等待一段时间让pycharm导入所有的skeletons和制作索引。 - 测试script
在你设置好的project里面新增一个python script测试一下你的Docker container中的interpreter吧!import tensorflow as tf a = tf.constant(2) sess = tf.InteractiveSession() print "tensorflow version:", tf.__version__ print "tensorflow output:", sess.run(a) sess.close()
看到代码补全了吗,有没有很激动??
Pycharm的输出验证了我们的操作确实调用了GPU:2017-05-26 14:56:01.468368: I tensorflow/core/common_runtime/gpu/gpu_device.cc:887] Found device 0 with properties: name: GeForce GTX 1060 3GB major: 6 minor: 1 memoryClockRate (GHz) 1.7085 pciBusID 0000:01:00.0 Total memory: 2.94GiB Free memory: 2.25GiB 2017-05-26 14:56:01.468385: I tensorflow/core/common_runtime/gpu/gpu_device.cc:908] DMA: 0 2017-05-26 14:56:01.468393: I tensorflow/core/common_runtime/gpu/gpu_device.cc:918] 0: Y 2017-05-26 14:56:01.468408: I tensorflow/core/common_runtime/gpu/gpu_device.cc:977] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 1060 3GB, pci bus id: 0000:01:00.0) tensorflow version: 1.1.0 tensorflow output: 2
如果在脚本还没退出的时候在命令行中运行:
docker ps
可以看见Pycharm确实run了一个新的docker container, 启动的service就是我们在docker-compose.yml里面指定的 dl 服务,script跑完后该container会自动退出。
- 更改环境变量 (for caffe and opencv)
经过上一步后,pycharm已经能调用你在docker image里面通过pip安装在python文件夹里的packages,但是由于在我的image里面,caffe,caffe2和OpenCV是放在不同目录下的,要让我们的python解释器到docker container里的目录里去找命令,需要我们做手动更改点击pycharm主视图的左下角的Docker,在选择/compose_dl_1(如果没有则先运行Docker服务),再在右边选择Environment variables,选择第一个PYTHONPATH,按最右边的铅笔图标,把value改成
/opt/project:/opt/caffe/python:/opt/caffe2/build:~/opencv/build
按下OK,最后记得按右下角的Save,重启Pycharm。大功告成,phew,现在把测试代码丰富一下,看看我们的新解释器你不能找到Opencv和caffeimport tensorflow as tf import cv2 import caffe import caffe2 a = tf.constant(2) sess = tf.InteractiveSession() print "tensorflow version:", tf.__version__ print "tensorflow output:", sess.run(a) sess.close()
- (optional) Bind your local paths to the container
On Linux, the container is created in an isolated environment and does not share folders with your host machine. If you’d like to load data using the absolute paths, you will have to manually bind the paths on your host to the container created.
Similar to step 7, select Volume Bindings in the properties of container /compose_dl_1, click the green “+” and add the bindings you need. Since everything is in the home folder in my case, I just bind the home folder to the same place in the container as indicated in the third row in the screenshot below.
For debugging, carry out the same operations to the container
/pycharm_helpers_PY-171.4424.42.
Bonus
这里提供一个完整的Ubuntu装机脚本,对于新装好的Ubuntu只要就可以准备好本教程所有需要的essentials,安装好docker,nvidia-docker, cuda等,下载脚本后只需要一行命令
bash new_ubuntu.sh
Closing thoughts
如果python是深度学习开发的lingua franca,那么Docker应该可以算是开发环境的一个lingua franca,用来搭建代码到硬件的桥梁。开发环境的配置应该是所有理工学生的基本功,但令我惊讶的是,哪怕博士生和博后,配置一个环境也要花上好几天,极其低效。我觉得对docker的利用可以大大减少这些重复劳动,无论你来自industrial还是academic背景。对于industry,针对cloud servers发布的image可以大大减轻甲方系统管理的负担。对于academic的人来说,别人为了测试你发布的源码所花的时间越少,你的work越有可能获得citation。如果你跟我一样被封闭的MATLAB宠坏了,又想进工业界,还是好好磨练基本功吧。
References
Configuring Remote Interpreters via Docker Compose
Connect nvidia-docker as remote python interpreter in Pycharm · Issue #303 · NVIDIA/nvidia-docker
How To Use PyCharm Docker Integration with GPU-enabled Containers