在 WSL2 中使用 NVIDIA Docker 進(jìn)行全棧開發(fā)和深度學(xué)習(xí) TensorFlow pytorch GPU 加速
0. 背景
0.1 起源
- 生產(chǎn)環(huán)境都是在 k8d pod 中運(yùn)行,直接在容器中開發(fā)不好嘛驹吮?
- 每次換電腦针史,都要配配配,呸呸呸
- 新電腦只安裝日常用的軟件不好嘛碟狞,環(huán)境變量配配配啄枕,各種日常軟件和開發(fā)軟件到處拉??
- 虛擬機(jī)唄,怎么調(diào)用 GPU 是個(gè)問題族沃,hyper-v 好像是可以魔改配置實(shí)現(xiàn)频祝,又得改改改。改好了本地能跑了脆淹,生產(chǎn)給你報(bào)錯(cuò)報(bào)錯(cuò)錯(cuò)錯(cuò)錯(cuò)
- 到處拉??常空,文件弄亂了怎么辦,容器直接銷毀重建就完事盖溺,分分鐘解決漓糙。電腦重裝再配環(huán)境也遭不住
0.2. 容器化開發(fā)之后
- 宿主機(jī)電腦隨便換,隨便重裝烘嘱。重裝之后我只要
上網(wǎng)
+wsl --install
+get docker
+docker compose up -d
就完事了 - 換 macOS昆禽?沒事,
docker compsoe up -d
- 換 Windows蝇庭?沒事为狸,
docker compose up -d
- 沒電腦?沒事遗契,搞臺(tái)遠(yuǎn)程機(jī)子
ssh
+docker compose up -d
- 電腦炸了辐棒?沒事,所有 git 修改都在遠(yuǎn)端有一份。開發(fā)環(huán)境換臺(tái)機(jī)子
docker compose up -d
繼續(xù)
0.3 不足
- 如果是做 k8s 開發(fā)的漾根,估計(jì)不行泰涂,起本地集群建議用 vagrant。本質(zhì)上一個(gè)容器根本無法解決這個(gè)問題
- 如果沒有機(jī)器不支持
systemd
沒法搞辐怕,比如公司只給提供開發(fā)容器環(huán)境(只能操作給你的容器)逼蒙,這個(gè)情況下目前正在解決,使用 ansible 重寫 Dockerfile 里面的腳本寄疏,擺脫容器限制是牢。主要區(qū)別就是環(huán)境安裝過程在本地還是在遠(yuǎn)端
1. 前置條件
1.1. 安裝系統(tǒng)
Windows 10 版本 2004 及更高版本(內(nèi)部版本 19041 及更高版本)或 Windows 11
跳過
1.2. 處理好網(wǎng)絡(luò)環(huán)境
安裝過程中需要訪問國(guó)際網(wǎng)絡(luò),自行處理好陕截。建議開啟 tun 模式
2. 準(zhǔn)備 WSL
2.1. 安裝 WSL
在管理員模式下打開 PowerShell 或 Windows 命令提示符
wsl --install
安裝完成驳棱,重啟電腦
2.2. 首次打開 WSL
重啟完成后,打開 powershell农曲,輸入
wsl
此時(shí)應(yīng)該會(huì)提示為 Linux 發(fā)行版創(chuàng)建“用戶名”和“密碼”
如果這里提示沒有安裝 Linux 發(fā)行版社搅,那么這里可以再次執(zhí)行
wsl --install
,會(huì)自動(dòng)安裝 Ubuntu 22.04 LTS
2.3. 設(shè)置 root 密碼
sudo passwd
2.4. 換源
切換到 root 用戶乳规,執(zhí)行下面命令換源
cat <<'EOF' > /etc/apt/sources.list
# 默認(rèn)注釋了源碼鏡像以提高 apt update 速度形葬,如有需要可自行取消注釋
deb https://mirror.nju.edu.cn/ubuntu/ jammy main restricted universe multiverse
# deb-src https://mirror.nju.edu.cn/ubuntu/ jammy main restricted universe multiverse
deb https://mirror.nju.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse
# deb-src https://mirror.nju.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse
deb https://mirror.nju.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse
# deb-src https://mirror.nju.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse
deb https://mirror.nju.edu.cn/ubuntu/ jammy-security main restricted universe multiverse
# deb-src https://mirror.nju.edu.cn/ubuntu/ jammy-security main restricted universe multiverse
# deb http://security.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse
# # deb-src http://security.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse
# 預(yù)發(fā)布軟件源,不建議啟用
# deb https://mirror.nju.edu.cn/ubuntu/ jammy-proposed main restricted universe multiverse
# # deb-src https://mirror.nju.edu.cn/ubuntu/ jammy-proposed main restricted universe multiverse
EOF
出處:南京大學(xué)鏡像站 -> https://mirror.nju.edu.cn/mirrorz-help/ubuntu/?mirror=NJU
2.5.(可選)遷移 WSL 磁盤目錄
這里以遷移到 D:\hyper-v\ubu1\ubu1.vhdx
為例
2.6. 設(shè)置默認(rèn)用戶
把 你的用戶名
替換成你設(shè)置的用戶名暮的,然后在 WSL 中執(zhí)行
sudo echo "[user]\ndefault=你的用戶名" >> /etc/wsl.conf
比如我的用戶名是 linux
笙以,那么我執(zhí)行的命令就是 sudo echo "[user]\ndefault=linux" >> /etc/wsl.conf
2.7. 導(dǎo)出磁盤鏡像
在 Windows poweshell 中執(zhí)行
wsl --export Ubuntu d:\hyper-v\ubu1\ubu1.vhdx --vhd
2.8. 刪除原系統(tǒng)
wsl --unregister Ubuntu
2.9. 導(dǎo)入新系統(tǒng)
wsl --import-in-place ubu1 d:\hyper-v\ubu1\ubu1.vhdx
3. 配置 NVIDIA Docker
3.1. 安裝 Docker
參考:docker 官網(wǎng) 和 南京大學(xué)鏡像 -> https://mirror.nju.edu.cn/mirrorz-help/docker-ce/?mirror=NJU
在 powershell 中輸入 wsl
,進(jìn)入 WSL 中冻辩,執(zhí)行
首先安裝依賴:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
信任 Docker 的 GPG 公鑰并添加倉(cāng)庫(kù):
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://mirror.nju.edu.cn/docker-ce/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
最后安裝 Docker
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
3.2. 配置普通用戶直接使用 Docker 命令
sudo gpasswd -a $USER docker
newgrp docker
3.3 安裝 NVIDIA 支持
參考:微軟 WSL 官方文檔:https://learn.microsoft.com/zh-cn/windows/wsl/tutorials/gpu-compute
通過運(yùn)行以下命令為 NVIDIA 容器工具包設(shè)置穩(wěn)定存儲(chǔ)庫(kù):
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-docker-keyring.gpg
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-docker-keyring.gpg] https://#g' | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
安裝 NVIDIA 運(yùn)行時(shí)包和依賴項(xiàng)
sudo apt-get update
sudo apt-get install -y nvidia-docker2
3.4 Docker 換源
參考:南京大學(xué)鏡像
修改配置文件
sudo nano /etc/docker/daemon.json
正常走到這一步應(yīng)該是這樣的
[圖片上傳失敗...(image-6d4115-1693540539058)]
添加一行
,"registry-mirrors": ["https://docker.nju.edu.cn/"]
[圖片上傳失敗...(image-863556-1693540539058)]
按下 ctrl+o
再按下 回車
保存文件
再按下 ctrl+x
退出編輯器
檢查一下結(jié)果源织,cat /etc/docker/daemon.json
[圖片上傳失敗...(image-412e2f-1693540539058)]
重啟 Docker
sudo systemctl restart docker
4. 拉取 & 運(yùn)行 Docker 鏡像
這個(gè)全棧開發(fā)鏡像是我自己構(gòu)建的
Dockfile 在 GitHub 倉(cāng)庫(kù)這里 https://github.com/james-curtis/code-os-debian
包含了
- zsh
- ohmyzsh
- powerlevel10k
- 中文語(yǔ)言包,gui 下微軟雅黑字體支持
- nodejs微猖、nvm
- openssh
- c++
- wslg 透?jìng)鞯?Windows 母機(jī)支持
- Python谈息、conda、pdm
temurin 8凛剥、11侠仇、17 jdk,jenv
docker cli
TensorFlow
pytorch
cuda 11.8犁珠、cudatoolkit
4.1. 拉取鏡像
由于鏡像較大逻炊,建議單獨(dú)拉取
- GPU 支持鏡像(9.94 GB):
jamescurtisfoxmail/code-os:latest-gpu
- 僅 CPU 支持鏡像(2.77 GB):
jamescurtisfoxmail/code-os:latest
這里以 GPU 支持鏡像為例
docker pull jamescurtisfoxmail/code-os:latest-gpu
4.2. 下載 compose 配置
下載 Docker compose 配置
git clone https://github.com/james-curtis/code-os-debian.git
4.3. 啟動(dòng) Docker compose
啟動(dòng) docker compose
cd code-os-debian/docker/wsl/
bash run-gpu.sh
可以看到已經(jīng)啟動(dòng)成功了
[圖片上傳失敗...(image-79c51d-1693540539058)]
5. 檢驗(yàn)成果
先進(jìn)入 Docker 容器
source .gpu-envrc
docker compose exec os zsh
[圖片上傳失敗...(image-d80d83-1693540539058)]
如果字體亂碼,應(yīng)該是沒有配置 powerlevel10k 的
MesloLGS NF
字體支持犁享。我使用的終端是
tabby
全平臺(tái)支持[圖片上傳失敗...(image-54d1cf-1693540539058)]
在項(xiàng)目中有這幾個(gè)字體余素,復(fù)制到c:\windows\fonts
中即可
[圖片上傳失敗...(image-405a4b-1693540539058)]
5.1. 檢測(cè) wslg 支持
xeyes
會(huì)顯示一個(gè)跟隨鼠標(biāo)的小眼睛
xclock
是顯示一個(gè)時(shí)鐘
[圖片上傳失敗...(image-457e0e-1693540539058)]
5.2. 檢測(cè) NVIDIA 支持
nvidia-smi
[圖片上傳失敗...(image-a6cfe9-1693540539058)]
我這里顯示出了母機(jī)的 3060,說明 Docker 已經(jīng)檢測(cè)到這張顯卡
5.3. 檢測(cè) TensorFlow支持
5.3.1 TensorFlow CPU
python3 -c "import tensorflow as tf; print(tf.reduce_sum(tf.random.normal([1000, 1000])))"
[圖片上傳失敗...(image-e85f40-1693540539058)]
打印出了張量
5.3.2 TensorFlow GPU
python3 -c "import tensorflow as tf; print(tf.config.list_physical_devices('GPU'))"
[圖片上傳失敗...(image-6bec96-1693540539058)]
可以看到 TensorFlow 也檢測(cè)到了顯卡
5.3.3 安裝 kaggle cli
pip install kaggle
登錄 kaggle 下載登錄憑據(jù)炊昆,下載到 ~/.kaggle/kaggle.json
設(shè)置權(quán)限
chmod 600 ~/.kaggle/kaggle.json
[圖片上傳失敗...(image-dfa5ec-1693540539058)]
5.3.4 檢測(cè) TensorFlow GPU 負(fù)載支持
這里我們使用 kaggle cli 下載比賽中別人提交的代碼進(jìn)行測(cè)試桨吊,https://www.kaggle.com/code/hassanamin/tensorflow-mnist-gpu-tutorial
[圖片上傳失敗...(image-9de946-1693540539058)]
復(fù)制下載命令
[圖片上傳失敗...(image-5248c4-1693540539058)]
啟動(dòng) openssh-server
sudo service ssh start
輸入密碼 linux
默認(rèn)用戶和密碼都是
linux
root
用戶名也是linux
[圖片上傳失敗...(image-f7939-1693540539058)]
打開 vscode 進(jìn)行遠(yuǎn)程連接
需要先下載遠(yuǎn)程開發(fā)插件 ms-vscode-remote.vscode-remote-extensionpack
[圖片上傳失敗...(image-f7d229-1693540539058)]
點(diǎn)擊左下角的藍(lán)標(biāo)威根,會(huì)彈出命令列表,選擇 Connect to host
[圖片上傳失敗...(image-999660-1693540539058)]
直接連接 localhost
即可
為什么可以直接通過
localhost
連接有兩個(gè)原因
- 微軟支持宿主機(jī)直接訪問 WSL 的監(jiān)聽端口
- docker compose 中設(shè)置的
network
類型是host
视乐,也就是和 WSL 公用一個(gè)網(wǎng)絡(luò)
[圖片上傳失敗...(image-5ff420-1693540539058)]
點(diǎn)擊右側(cè)的 Connect
[圖片上傳失敗...(image-ba0654-1693540539058)]
會(huì)提示選擇平臺(tái)和輸入密碼
完成之后即可進(jìn)行遠(yuǎn)程開發(fā)
進(jìn)入剛剛 kaggle 的項(xiàng)目
這里由于的剛剛我下載的目錄是 /tmp/kaggle/tf
所以這里我需要打開這個(gè)目錄
[圖片上傳失敗...(image-ceeb76-1693540539058)]
安裝插件
需要安裝的插件有
- donjayamanne.python-extension-pack
- donjayamanne.python-extension-pack
安裝完成之后需要加載窗口
選擇運(yùn)行環(huán)境
選擇 conda Python3.9 作為運(yùn)行環(huán)境
[圖片上傳失敗...(image-af6fcb-1693540539058)]
逐個(gè)單元格運(yùn)行試試效果
可以看到檢測(cè)到 GPU 了
[圖片上傳失敗...(image-e88f55-1693540539058)]
可以看到成功調(diào)用宿主機(jī)顯卡
[圖片上傳失敗...(image-efa287-1693540539058)]
不過似乎沒有使得顯卡滿載
5.4. 檢測(cè) pytorch cuda 支持
在 WSL 中執(zhí)行
python3 -c "import torch;print(torch.cuda.is_available());"
[圖片上傳失敗...(image-653558-1693540539058)]
這里我還沒有換 vscode 的終端字體洛搀,所以亂碼了,忽略即可
5.4.1 檢測(cè) pytorch GPU 負(fù)載支持
對(duì)于 pytorch佑淀,這里使用 https://www.kaggle.com/code/lyhue1991/pytorch-gpu-examples留美,作為測(cè)試 demo
[圖片上傳失敗...(image-2940b3-1693540539058)]
[圖片上傳失敗...(image-91b197-1693540539058)]
[圖片上傳失敗...(image-4975d1-1693540539058)]
[圖片上傳失敗...(image-be1737-1693540539058)]
可以看到成功調(diào)度 GPU
6. 檢查 nodejs
node -v
nvm list
[圖片上傳失敗...(image-d3eeba-1693540539058)]
7. 檢查 java
java -version
javac -version
jenv versions
[圖片上傳失敗...(image-2cc208-1693540539058)]
8. 檢查 c++
g++ -v
gcc -v
[圖片上傳失敗...(image-265ca3-1693540539058)]
9. 容器卷
在 Dockerfile 中有寫到
# =========== 配置 容器卷 =============
VOLUME [ "/mnt/workspace", "/mnt/data" ]
這兩個(gè)目錄都是持久化的,也就是 docker 容器銷毀之后伸刃,只有這兩個(gè)目錄下的文件不會(huì)清理(重啟不影響)
其中 /mnt/workspace
是映射到 WSL 中的谎砾,IO 性能比較差
/mnt/data
是沒有映射的容器卷,IO 性能較好捧颅,建議項(xiàng)目都放到該目錄下
至于 /home/linux
用戶目錄下的文件可以自己創(chuàng)建并映射容器卷