環(huán)境:CUDA 與 PyTorch 配置實(shí)戰(zhàn))
1. 為什么我最終把 AI 開發(fā)環(huán)境整體搬進(jìn)了 WSL21.1 從雙系統(tǒng)到 WSL2 的折騰史最早做深度學(xué)習(xí)那會(huì)兒我的方案是 Windows 加 Ubuntu 雙系統(tǒng)。每次要跑訓(xùn)練就得重啟切到 Linux 下面調(diào)代碼調(diào)完想查個(gè)資料又得切回 Windows一天下來光重啟就浪費(fèi)不少時(shí)間。后來試過純 Linux 主機(jī)顯卡驅(qū)動(dòng)、桌面環(huán)境、輸入法各種小毛病不斷日常辦公體驗(yàn)確實(shí)不如 Windows 順手。再后來虛擬機(jī)也試過VMware 和 VirtualBox 都跑過但 GPU 直通要么不支持要么配置極其折騰性能損耗也大跑個(gè)小模型都費(fèi)勁。直到 WSL2 成熟之后我才真正找到了一個(gè)平衡點(diǎn)。WSL2 本質(zhì)上是跑在輕量級(jí)虛擬化層上的完整 Linux 內(nèi)核不是以前 WSL1 那種系統(tǒng)調(diào)用翻譯層。這意味著它兼容原生 Linux 的 ELF 二進(jìn)制文件Docker 能跑CUDA 也能跑。微軟和 NVIDIA 合作把 GPU 直通做進(jìn)了 WSL2 的內(nèi)核里Windows 主機(jī)上的 NVIDIA 顯卡驅(qū)動(dòng)可以直接被 WSL2 里的 Linux 發(fā)行版調(diào)用不需要在 Linux 里再單獨(dú)裝一遍驅(qū)動(dòng)。這一點(diǎn)是質(zhì)變。我現(xiàn)在的主力方案就是Windows 11 負(fù)責(zé)日常辦公、瀏覽器、微信、OfficeWSL2 里的 Ubuntu 22.04 負(fù)責(zé)所有 AI 開發(fā)工作包括 PyTorch 訓(xùn)練、CUDA 編譯、數(shù)據(jù)處理腳本。兩邊文件系統(tǒng)互通剪貼板共享VS Code 直接遠(yuǎn)程連進(jìn) WSL2 寫代碼體驗(yàn)幾乎和原生 Linux 一樣但省去了雙系統(tǒng)切換的所有麻煩。1.2 這套方案到底適合誰如果你符合下面任意一條這套方案大概率能幫你省下大量時(shí)間主力機(jī)器是 Windows但需要 Linux 環(huán)境跑 PyTorch、TensorFlow 等框架有 NVIDIA 顯卡想讓 WSL2 里的代碼直接調(diào)用 GPU 做訓(xùn)練或推理不想折騰雙系統(tǒng)也不想忍受傳統(tǒng)虛擬機(jī)的性能損耗和 GPU 配置難題需要同時(shí)用 Windows 辦公軟件和 Linux 開發(fā)工具鏈想用 VS Code 或 Cursor 這類編輯器直接連進(jìn) Linux 環(huán)境寫代碼反過來說如果你用的是 AMD 顯卡想做 ROCm 開發(fā)或者需要特定的 Linux 桌面環(huán)境做圖形界面開發(fā)WSL2 目前的支持還不算完美這種情況可能還是原生 Linux 更合適。但對(duì)于絕大多數(shù)做深度學(xué)習(xí)、CUDA 編程、Python 開發(fā)的人來說WSL2 已經(jīng)是相當(dāng)成熟的方案了。1.3 整體架構(gòu)一句話說清Windows 主機(jī)裝好 NVIDIA 驅(qū)動(dòng)WSL2 里裝 Ubuntu 22.04Ubuntu 里裝 CUDA Toolkit 和 PyTorch代碼通過 VS Code Remote 連接編寫訓(xùn)練時(shí) GPU 直接由 Windows 驅(qū)動(dòng)接管。整個(gè)鏈路里WSL2 負(fù)責(zé)提供 Linux 用戶空間和內(nèi)核Windows 負(fù)責(zé)硬件驅(qū)動(dòng)和 GPU 調(diào)度兩者通過微軟的 GPU 虛擬化層通信。理解這個(gè)架構(gòu)后面所有配置步驟的邏輯就都通了。2. 環(huán)境準(zhǔn)備從零開始的完整配置流程2.1 Windows 側(cè)的前置檢查與 WSL2 啟用在動(dòng)手之前先確認(rèn)幾件事。第一Windows 版本必須是 Windows 10 版本 2004 及以上或者 Windows 11。第二確認(rèn) CPU 支持虛擬化在任務(wù)管理器性能標(biāo)簽頁里看“虛擬化”是否顯示“已啟用”。如果沒啟用需要進(jìn) BIOS 打開 Intel VT-x 或 AMD-V。確認(rèn)無誤后以管理員身份打開 PowerShell執(zhí)行下面這條命令wsl --install這條命令會(huì)自動(dòng)完成幾件事啟用“適用于 Linux 的 Windows 子系統(tǒng)”可選功能、啟用“虛擬機(jī)平臺(tái)”功能、下載并安裝 WSL2 內(nèi)核更新包、把 WSL2 設(shè)為默認(rèn)版本、安裝 Ubuntu 發(fā)行版。執(zhí)行完重啟電腦即可。如果你之前已經(jīng)裝過 WSL想確認(rèn)版本可以運(yùn)行wsl --list --verbose輸出里 VERSION 列顯示 2 就對(duì)了。如果顯示 1用wsl --set-version 發(fā)行版名 2轉(zhuǎn)換。注意有些機(jī)器上wsl --install會(huì)因?yàn)榻M策略或系統(tǒng)精簡(jiǎn)原因失敗這時(shí)候需要手動(dòng)在“啟用或關(guān)閉 Windows 功能”里勾選“適用于 Linux 的 Windows 子系統(tǒng)”和“虛擬機(jī)平臺(tái)”重啟后再執(zhí)行安裝命令。2.2 Ubuntu 22.04 的安裝與初始化我選 Ubuntu 22.04 LTS 而不是 24.04原因是 22.04 的 CUDA 和 PyTorch 生態(tài)兼容性經(jīng)過大量驗(yàn)證踩坑最少。安裝命令wsl --install -d Ubuntu-22.04安裝完成后會(huì)提示創(chuàng)建用戶名和密碼這個(gè)用戶名和密碼是 Linux 系統(tǒng)內(nèi)的和 Windows 賬戶無關(guān)。創(chuàng)建完成后就進(jìn)入了 Ubuntu 的終端。第一件事是更新軟件源sudo apt update sudo apt upgrade -y然后裝一些基礎(chǔ)工具后面編譯和調(diào)試都會(huì)用到sudo apt install -y build-essential git curl wget vim python3-pip python3-venv這里有個(gè)經(jīng)驗(yàn)WSL2 默認(rèn)的 apt 源在國(guó)內(nèi)訪問速度一般可以換成國(guó)內(nèi)鏡像源。編輯/etc/apt/sources.list把a(bǔ)rchive.ubuntu.com和security.ubuntu.com替換成清華或阿里的鏡像地址更新速度能從幾十 KB 提升到幾 MB。2.3 Windows 顯卡驅(qū)動(dòng)的確認(rèn)這一步是 GPU 直通的關(guān)鍵。WSL2 里的 CUDA 不依賴 Linux 側(cè)的 NVIDIA 驅(qū)動(dòng)而是直接調(diào)用 Windows 主機(jī)上的驅(qū)動(dòng)。所以你要做的是在 Windows 上安裝最新版的 NVIDIA 顯卡驅(qū)動(dòng)而不是在 WSL2 里裝驅(qū)動(dòng)。去 NVIDIA 官網(wǎng)下載對(duì)應(yīng)你顯卡型號(hào)的 Game Ready 或 Studio 驅(qū)動(dòng)安裝完成后在 Windows 命令行運(yùn)行nvidia-smi能看到顯卡信息和驅(qū)動(dòng)版本就說明 Windows 側(cè)沒問題。記住這個(gè)驅(qū)動(dòng)版本號(hào)后面裝 CUDA Toolkit 時(shí)要參考它支持的 CUDA 版本上限。注意千萬不要在 WSL2 里執(zhí)行apt install nvidia-driver-xxx這會(huì)把 Linux 側(cè)的驅(qū)動(dòng)裝進(jìn)去和 Windows 驅(qū)動(dòng)沖突導(dǎo)致 GPU 無法調(diào)用。WSL2 里只需要裝 CUDA Toolkit不需要裝驅(qū)動(dòng)。2.4 驗(yàn)證 GPU 是否已經(jīng)直通進(jìn) WSL2在 WSL2 終端里運(yùn)行nvidia-smi如果輸出和 Windows 側(cè)一致說明 GPU 直通已經(jīng)生效。如果提示 command not found說明 CUDA Toolkit 還沒裝但驅(qū)動(dòng)層面其實(shí)已經(jīng)通了裝完 Toolkit 就能用。如果提示找不到設(shè)備檢查 Windows 驅(qū)動(dòng)版本是否太舊或者 WSL2 內(nèi)核是否需要更新運(yùn)行wsl --update。這一步是整個(gè)方案的地基地基沒打好后面全是坑。我見過太多人卡在這里反復(fù)在 WSL2 里裝驅(qū)動(dòng)結(jié)果越裝越亂。3. CUDA 與 PyTorch 的安裝版本匹配是核心3.1 CUDA Toolkit 的版本選擇邏輯CUDA 版本選擇不是越新越好而是要看三個(gè)東西的交叉點(diǎn)Windows 驅(qū)動(dòng)支持的最高 CUDA 版本、PyTorch 官方支持的 CUDA 版本、你的顯卡算力是否被支持。先看 Windows 驅(qū)動(dòng)支持的最高版本運(yùn)行nvidia-smi右上角會(huì)顯示CUDA Version: 12.x這是驅(qū)動(dòng)能支持的上限。然后去 PyTorch 官網(wǎng)看當(dāng)前穩(wěn)定版支持的 CUDA 版本通常有 11.8、12.1、12.4 幾個(gè)選項(xiàng)。取兩者的交集再選一個(gè)較新的穩(wěn)定版本。以我目前的配置為例驅(qū)動(dòng)支持到 CUDA 12.4PyTorch 2.4 支持 CUDA 12.1 和 12.4我選 12.1因?yàn)樯鷳B(tài)兼容性更好很多第三方庫對(duì) 12.1 的支持更成熟。安裝 CUDA Toolkit 推薦用 NVIDIA 官方倉庫的方式比 runfile 更干凈wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-keyring_1.1-1_all.deb sudo dpkg -i cuda-keyring_1.1-1_all.deb sudo apt update sudo apt install -y cuda-toolkit-12-1注意這里用的是wsl-ubuntu倉庫不是普通的ubuntu2204倉庫這是專門為 WSL2 準(zhǔn)備的包依賴關(guān)系不一樣。3.2 環(huán)境變量的配置細(xì)節(jié)裝完之后需要配置環(huán)境變量編輯~/.bashrc在末尾加上export PATH/usr/local/cuda-12.1/bin:$PATH export LD_LIBRARY_PATH/usr/local/cuda-12.1/lib64:$LD_LIBRARY_PATH然后source ~/.bashrc生效。驗(yàn)證nvcc --version能輸出版本信息就說明 CUDA Toolkit 裝好了。注意LD_LIBRARY_PATH這一行很多人會(huì)漏掉導(dǎo)致編譯時(shí)找不到 CUDA 動(dòng)態(tài)庫。另外如果你裝了多個(gè) CUDA 版本通過修改 PATH 里的路徑來切換不要用update-alternatives在 WSL2 里那個(gè)方式容易出問題。3.3 PyTorch 安裝的三種方式對(duì)比PyTorch 安裝方式主要有三種pip 直接裝、conda 裝、源碼編譯。我的建議是優(yōu)先用 pip 配合虛擬環(huán)境原因如下表安裝方式優(yōu)點(diǎn)缺點(diǎn)適用場(chǎng)景pip venv輕量、版本可控、官方 wheel 直接下載需要手動(dòng)管理虛擬環(huán)境絕大多數(shù)場(chǎng)景conda依賴管理強(qiáng)、科學(xué)計(jì)算包全體積大、有時(shí)和系統(tǒng) CUDA 沖突需要大量科學(xué)計(jì)算庫源碼編譯可定制、支持最新特性耗時(shí)長(zhǎng)、容易失敗需要特定優(yōu)化或最新功能我一般用 venvpython3 -m venv ~/venvs/torch source ~/venvs/torch/bin/activate pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121這里的cu121對(duì)應(yīng) CUDA 12.1必須和前面裝的 CUDA Toolkit 版本一致否則會(huì)出現(xiàn)版本不匹配的警告甚至運(yùn)行錯(cuò)誤。3.4 驗(yàn)證 PyTorch 能否調(diào)用 GPU裝完后寫個(gè)最簡(jiǎn)單的驗(yàn)證腳本import torch print(PyTorch version:, torch.__version__) print(CUDA available:, torch.cuda.is_available()) print(CUDA version:, torch.version.cuda) print(GPU count:, torch.cuda.device_count()) print(GPU name:, torch.cuda.get_device_name(0))如果CUDA available輸出 True說明整條鏈路打通了。如果輸出 False按下面順序排查先確認(rèn)nvidia-smi在 WSL2 里能跑再確認(rèn) PyTorch 版本和 CUDA 版本是否匹配最后檢查是不是裝成了 CPU 版本的 PyTorch用pip list | grep torch看版本號(hào)后面有沒有cu121后綴。4. 開發(fā)工作流的搭建與優(yōu)化4.1 VS Code Remote 連接 WSL2這是我認(rèn)為 WSL2 方案里體驗(yàn)最好的部分。在 Windows 上裝好 VS Code然后裝一個(gè)叫 WSL 的官方擴(kuò)展。裝完后按 F1輸入WSL: Connect to WSLVS Code 就會(huì)在 WSL2 里啟動(dòng)一個(gè)服務(wù)端界面還是 Windows 的但終端、文件系統(tǒng)、Python 解釋器全部是 WSL2 里的。這意味著你可以在 Windows 的 VS Code 里寫代碼代碼實(shí)際存在 Linux 文件系統(tǒng)里運(yùn)行時(shí)用的是 Linux 的 Python 和 CUDA。調(diào)試、斷點(diǎn)、變量查看全部正常。而且因?yàn)槲募?Linux 側(cè)IO 性能比放在/mnt/c/下好很多。注意項(xiàng)目文件一定要放在 WSL2 的 Linux 文件系統(tǒng)里比如~/projects/不要放在/mnt/c/Users/xxx/下??缥募到y(tǒng)訪問的 IO 性能差距在大量小文件讀寫時(shí)非常明顯訓(xùn)練時(shí)加載數(shù)據(jù)集能差出好幾倍。4.2 數(shù)據(jù)集與模型文件的存放策略WSL2 的磁盤空間默認(rèn)是動(dòng)態(tài)擴(kuò)展的但上限受 Windows 磁盤剩余空間限制。數(shù)據(jù)集大的話建議單獨(dú)掛載一塊 Windows 磁盤到 WSL2 里或者用wsl --mount掛載物理磁盤。我自己的做法是代碼和虛擬環(huán)境放在 WSL2 默認(rèn)的 ext4 文件系統(tǒng)里數(shù)據(jù)集放在 Windows 的 D 盤通過/mnt/d/datasets/訪問。雖然跨文件系統(tǒng)有性能損耗但數(shù)據(jù)集通常是大文件順序讀取損耗可以接受而且方便在 Windows 側(cè)用工具管理和備份。如果數(shù)據(jù)集特別大且讀取頻繁可以考慮在 WSL2 里單獨(dú)掛一塊虛擬磁盤VHD格式化成 ext4性能接近原生。4.3 終端與 Shell 的個(gè)性化配置WSL2 默認(rèn)的終端是 Windows Terminal體驗(yàn)已經(jīng)不錯(cuò)。我一般會(huì)做幾件事裝 zsh 和 oh-my-zsh配置一些常用別名裝 tmux 做會(huì)話管理。常用別名示例alias gsgit status alias llls -alF alias nvnvidia-smi alias actsource ~/venvs/torch/bin/activatetmux 在跑長(zhǎng)時(shí)間訓(xùn)練時(shí)特別有用SSH 斷開或者終端關(guān)閉后訓(xùn)練進(jìn)程不會(huì)中斷。配合nohup或者直接tmux new -s train開一個(gè)會(huì)話訓(xùn)練跑起來后 detach隨時(shí)可以 reattach 查看進(jìn)度。4.4 性能調(diào)優(yōu)的幾個(gè)關(guān)鍵點(diǎn)WSL2 默認(rèn)會(huì)占用較多內(nèi)存可以在 Windows 用戶目錄下創(chuàng)建.wslconfig文件限制資源[wsl2] memory32GB processors16 swap8GB這個(gè)配置根據(jù)你機(jī)器的實(shí)際內(nèi)存調(diào)整一般給 WSL2 分配總內(nèi)存的一半到三分之二比較合適。內(nèi)存給太少訓(xùn)練時(shí)容易 OOM給太多 Windows 側(cè)會(huì)卡。GPU 方面WSL2 的 CUDA 性能損耗在 5% 到 10% 左右主要來自虛擬化層的通信開銷。對(duì)于大多數(shù)訓(xùn)練任務(wù)來說可以接受。如果追求極致性能可以考慮用--gpu-support相關(guān)的優(yōu)化參數(shù)但實(shí)際提升有限。磁盤 IO 是 WSL2 相對(duì)薄弱的環(huán)節(jié)尤其是跨文件系統(tǒng)訪問。如果訓(xùn)練時(shí)數(shù)據(jù)加載是瓶頸可以考慮把數(shù)據(jù)集預(yù)處理成單個(gè)大文件比如 LMDB 或 HDF5 格式減少小文件隨機(jī)讀取。5. 常見問題與排查實(shí)錄5.1 GPU 相關(guān)問題的排查思路問題一nvidia-smi在 WSL2 里提示找不到命令這通常是因?yàn)?CUDA Toolkit 沒裝或者 PATH 沒配好。先確認(rèn) Windows 側(cè)nvidia-smi能跑然后在 WSL2 里檢查/usr/local/cuda-12.1/bin是否在 PATH 里。如果 CUDA 裝了但命令找不到多半是.bashrc沒 source 或者路徑寫錯(cuò)了。問題二PyTorch 顯示 CUDA available 為 False按這個(gè)順序排查第一nvidia-smi在 WSL2 里能不能跑第二PyTorch 版本是不是 CPU 版第三CUDA Toolkit 版本和 PyTorch 編譯版本是否匹配第四Windows 驅(qū)動(dòng)版本是否太舊。我遇到過最常見的原因是裝成了 CPU 版 PyTorch用pip list一看版本號(hào)沒有cu后綴就知道了。問題三訓(xùn)練時(shí)報(bào) CUDA out of memoryWSL2 里 GPU 顯存是直接透?jìng)鞯暮?Windows 側(cè)共享。如果 Windows 側(cè)有程序占著顯存比如瀏覽器硬件加速、游戲WSL2 里能用的顯存就會(huì)減少。訓(xùn)練前關(guān)掉不必要的 GPU 占用程序。另外.wslconfig里可以設(shè)置gpuMemoryLimit但一般不需要。5.2 網(wǎng)絡(luò)與下載速度問題WSL2 的網(wǎng)絡(luò)是 NAT 模式默認(rèn)走 Windows 主機(jī)的網(wǎng)絡(luò)。pip 和 apt 下載慢的話換國(guó)內(nèi)源是最直接的方案。pip 換源pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simpleapt 換源前面提過編輯 sources.list 替換域名即可。如果遇到 WSL2 里 DNS 解析異??梢詸z查/etc/resolv.conf有時(shí)候需要手動(dòng)指定 DNS 服務(wù)器。不過較新版本的 WSL2 已經(jīng)自動(dòng)處理了這個(gè)問題一般不用管。5.3 文件系統(tǒng)與權(quán)限問題WSL2 里訪問 Windows 文件時(shí)權(quán)限顯示為 777這是正常的因?yàn)?NTFS 和 ext4 的權(quán)限模型不同。如果某些程序?qū)?quán)限敏感可以把文件復(fù)制到 Linux 文件系統(tǒng)里再操作。另一個(gè)常見問題是 Git 在跨文件系統(tǒng)時(shí)的換行符處理。建議在 WSL2 里配置git config --global core.autocrlf input這樣提交時(shí)統(tǒng)一轉(zhuǎn)成 LF避免 Windows 和 Linux 協(xié)作時(shí)的換行符混亂。5.4 常見問題速查表現(xiàn)象可能原因解決方法nvidia-smi 找不到CUDA Toolkit 未裝或 PATH 未配裝 CUDA Toolkit檢查 .bashrcCUDA available FalsePyTorch 是 CPU 版重裝 GPU 版 PyTorch訓(xùn)練 OOMWindows 側(cè)占用顯存關(guān)閉占用 GPU 的程序pip 下載慢默認(rèn)源在國(guó)外換清華或阿里源文件讀寫慢跨文件系統(tǒng)訪問項(xiàng)目文件放 Linux 側(cè)WSL2 啟動(dòng)失敗虛擬化未啟用或內(nèi)核舊檢查 BIOS運(yùn)行 wsl --update內(nèi)存占用過高默認(rèn)無限制配置 .wslconfig 限制6. 我踩過的幾個(gè)坑和最終建議6.1 驅(qū)動(dòng)和 Toolkit 的版本陷阱我最早犯的錯(cuò)是在 WSL2 里裝 NVIDIA 驅(qū)動(dòng)結(jié)果和 Windows 驅(qū)動(dòng)沖突GPU 完全用不了。后來才明白 WSL2 的 GPU 直通是 Windows 驅(qū)動(dòng)負(fù)責(zé)硬件層Linux 側(cè)只需要 CUDA Toolkit 提供編譯和運(yùn)行時(shí)庫。這個(gè)分工一定要搞清楚。另一個(gè)坑是 CUDA 版本和 PyTorch 版本不匹配。有次我裝了 CUDA 12.4但 PyTorch 當(dāng)時(shí)只支持到 12.1結(jié)果torch.cuda.is_available()一直是 False。后來降級(jí) CUDA 到 12.1 就正常了。所以版本匹配這件事寧可花十分鐘查清楚也不要憑感覺裝。6.2 磁盤空間和性能的平衡WSL2 的虛擬磁盤文件ext4.vhdx會(huì)隨著使用不斷增長(zhǎng)但不會(huì)自動(dòng)收縮。刪了大文件后vhdx 文件在 Windows 側(cè)看還是那么大。可以用wsl --manage 發(fā)行版 --set-sparse true開啟稀疏模式或者手動(dòng)用 diskpart 壓縮。不過壓縮有風(fēng)險(xiǎn)操作前備份重要數(shù)據(jù)。性能方面我的經(jīng)驗(yàn)是代碼和虛擬環(huán)境放 Linux 側(cè)數(shù)據(jù)集放 Windows 側(cè)用/mnt/訪問模型 checkpoint 存 Linux 側(cè)。這樣兼顧了 IO 性能和磁盤空間管理。6.3 日常使用的幾個(gè)小技巧第一用 Windows Terminal 的標(biāo)簽頁功能一個(gè)標(biāo)簽跑訓(xùn)練一個(gè)標(biāo)簽寫代碼一個(gè)標(biāo)簽看日志切換很方便。第二VS Code 的 Remote WSL 模式下Python 解釋器要選 WSL2 里的 venv 路徑不要選 Windows 的 Python。第三訓(xùn)練腳本用tmux或者nohup跑避免終端關(guān)閉導(dǎo)致訓(xùn)練中斷。第四定期用wsl --shutdown完全關(guān)閉 WSL2 再重啟可以釋放一些緩存和僵尸進(jìn)程尤其是長(zhǎng)時(shí)間運(yùn)行后。第五如果要用 DockerWSL2 里裝 Docker Engine 比用 Docker Desktop 更輕量性能也更好。裝完后配置 GPU 支持容器里也能直接用 CUDA。這套環(huán)境我從去年用到現(xiàn)在跑了十幾個(gè)訓(xùn)練項(xiàng)目穩(wěn)定性很好。唯一需要注意的是 Windows 更新后偶爾會(huì)重置 WSL2 的網(wǎng)絡(luò)配置遇到網(wǎng)絡(luò)問題時(shí)先wsl --shutdown重啟一下大部分情況都能解決。