目的与方案

进行深度学习相关的开发,使用基于 Linux 的环境是大多数人的首选。然而大多数同学往往没有独立的 Linux 服务器;公用 Linux 服务器常常受限于权限等问题,不适合做个性化的配置,适合做验证后的大模型训练(或许);如果用个人主机装双系统,还得再费精力去维护一个工作用的 Linux 环境(浏览器、文档、网络、笔记软件、通讯软件,想想都已经头大了),而且切换系统还需要重启;如果用虚拟机,性能损耗是没法避免的,想要在虚拟机中支持 CUDA 那更是复杂。

除此之外,深度学习的各种环境配置有多头疼就不必多说了,cuDNN、TF、PyTorch 版本匹配,每一次 install 之前还要检查“换源了吗”,如果想要多版本共存那苦恼又多了一分。

以下,介绍一种 WSL2+Docker 方案,不仅解决以上痛点,还具有以下特性:

  1. 用 Windows 平台下的 WSL2 子系统实现环境隔离:Linux 生产环境与 Windows 学习环境隔离
  2. 子系统与宿主机的通信可以通过网络端口映射、文件磁盘链接形式进行(所以 Jupyter Notebook、FTP、SSH 之类的都完美支持),不过默认不带图形界面(一些可视化结果考虑离线渲染查看吧)
  3. 注意 WSL2 的 CUDA 支持推出时间并不久,但好在目前用下来没有什么大 bug
  4. 用 Docker 实现深度学习环境一键配置(是真的一键),同时本次使用的 Deepo 包支持 LEGO 式的自定义模块
  5. Docker 环境的备份、迁移非常方便,复制粘贴就能搭建一套完全一样的环境,适合 teamwork
整体架构(感觉是最近画得最漂亮的图了)

看起来很套娃,但实际配置起来发现相当顺滑,而且层层隔离让人心情舒畅。总之,核心思路就在这张图里了,如果还想看下配置过程中的踩坑记录还可以继续往下滑。

显卡驱动

非常简单,在 NVIDIA 官网 找到对应自己显卡的最新驱动即可。注意这是整个方案唯一需要安装的驱动程序,不要在 WSL 或者 Docker 中再配置驱动了。

NVIDIA 官网

WSL

WSL 是一种 Windows 下的 Linux 子系统,新版本 WSL2 主要是提升了文件系统性能。具体安装步骤参考 微软官方文档。首先使用wsl --install安装 WSL 所需的所有组件,重启,然后在 Microsoft Store 中搜索需要的 Linux 发行版(如 Ubuntu 18.04)进行安装。

目前 Win10 2004 之后的版本以及 Win11 都可以直接安装,不需要加入 Windows Insider 计划。但值得一提的是,有一台 20H2 版本的 Windows 在后续的安装中一直出错,升级到 21H2 之后问题解决,这里不排除是系统版本的原因。

Linux 推荐使用 Ubuntu 18.04,当然也可以安装多个 WSL 子系统。注意一下安装位置以免磁盘空间不足,不过后续也可以进行整体迁移。

此外,可以尝试一下 Windows 最新的终端,名字就叫“终端”,相对现代化的 UI 以及支持多个环境中切换,在 官网这里 可以找到。

WSL2 安装完成

常见问题

  1. 重启 WSL?

    net stop LxssManager

    net start LxssManager

  2. WSL 内的文件在哪?

    Windows 资源管理器地址栏输入\\wsl$可以找到 WSL 文件;相反,在 WSL 中访问/mnt/c/可以看到 Windows C 盘。

  3. 如何对 WSL 整体迁移?

    依次执行 export 到文件、注销原系统、import 到新位置,参考 这篇博客

CUDA Toolkit

为了在 WSL 中运行 CUDA,还需要安装一个 toolkit,参考 NVIDIA 官网教程 的 4.2.6 节内容。但是如果使用 Docker 进行开发的话,又可以省掉这一步骤,直接安装 NVIDIA 的容器支持包即可。

Docker

参考 NVIDIA 官网教程 的 4.2.1、4.2.2 节内容进行 Docker 和相关支持的安装。注意,这里官网只在 WSL 内安装 Docker,事实上微软推荐的做法是在 Windows 中安装 Docker Desktop,可以参考 微软在这里的说法(这样的话注意勾选 Docker 中的 WSL2 支持)。

回到教程,4.2.3 节以后的部分则是支持 CUDA 的容器的验证,Docker 的基本操作这里就不再赘述。官方几个案例的镜像都比较大,这里提供一种更方便的方法:docker run -it --gpus all centos。运行任何一个你熟悉的 Linux 环境(这里 CentOS 大约 200MB),加上 --gpus all 参数,然后执行 nvidia-smi 即可。

这一步可能会在网络问题上折腾很久,多尝试换源、挂代理吧。

Docker 内成功检测显卡

常见问题

  1. 重启 Docker?

    sudo service docker stop

    sudo service docker start

  2. Docker 常用命令?

    推荐 一张脑图整理 Docker 常用命令

  3. Docker 中查看 Linux 版本?

    要用cat /etc/issue命令,cat /proc/version 或 uname -a 查到的是宿主机的系统。

Deepo

Deepo 是一个乐高式的开放框架,集成了大多数主流的深度学习环境。完整版ufoym/deepo大约 21G,单独 PyTorch 版本大约 6G,jupyter notebook也是可选项,可以在官网查看各种发布版本。

Deepo 镜像

注意,创建容器的时候还可以用-v参数指定一下文件目录挂载、用-p命令指定端口映射。举例来说,如果想用ufoym/deepo镜像创建一个名为cv的容器,启动 GPU,将容器的/data挂载到宿主机的/home/data,创建完之后接入bash终端运行,一个典型的命令是 docker run --gpus all -it --name="cv" -v /home/data:/data ufoym/deepo bash.

至此,整个环境就搭建完了。可以再学习一下 docker 的commitsave 命令,进行环境的备份和分享。

IDE

除了 Jupyter Notebook,个人还是习惯使用 Vscode 进行开发,为了接入层层套娃之后的环境,IDE 也需要进行一些设置。

涉及到的插件是 Remote-WSL、Remote-Containers。首先保证 WSL 中的 docker 服务、容器都运行正常,然后在 VSCode 中先选择 “Open Folder in WSL” 进 WSL,然后选择 “Attach to Running Container…” 进入容器。需要注意,容器内的 VSCode 插件都需要单独安装一次。

得益于 TensorBoard 的插件支持以及 Docker 插件的端口映射管理,TensorBoard 用起来也非常丝滑。

最终效果