Windows 上搭建 WSL2 深度学习环境:CUDA 与 PyTorch 完整指南
发布时间:2026/10/9 3:45:33 锦皓数字建站

1. 为什么要在 Windows 上折腾 WSL2 而不是装双系统很多人第一次接触深度学习开发时都会面临一个经典的选择题到底是在 Windows 上直接跑还是装个 Ubuntu 双系统或者干脆买台 Linux 主机。我前后试过这三种方案最后长期稳定用的是 WSL2。原因不复杂但值得掰开说清楚。Windows 原生跑 PyTorch 并不是不行conda 装一装、CUDA 装一装也能跑起来。但问题在于生态。大量开源项目、论文复现代码、数据处理脚本默认假设你在 Linux 环境下工作。路径分隔符、文件权限、shell 脚本、apt依赖、fork行为这些在 Windows 上要么不支持要么行为不一致。你会在各种莫名其妙的地方卡住比如某个库的编译脚本用了 bash 语法或者某个数据加载器依赖num_workers的多进程 fork 机制Windows 上直接报错。双系统的问题则是切换成本太高。你正在 Windows 上查资料、写文档突然要跑个训练得重启切到 Ubuntu来回折腾一次五分钟起步思路全断了。而且双系统下两个环境的文件互访很麻烦NTFS 分区在 Linux 下挂载虽然能读写但权限和性能都有坑。WSL2 恰好卡在一个甜点位置。它是一个真正的 Linux 内核跑在轻量级虚拟机里通过微软自己的内核补丁实现了和 Windows 的深度集成。你在 Windows 里开个终端就能进 Linux文件系统互通剪贴板互通甚至可以直接在 Windows 里用 VS Code 连进 WSL2 写代码。更关键的是从 WSL2 开始微软支持了 GPU 直通GPU Paravirtualization也就是说你那张 NVIDIA 显卡可以同时被 Windows 和 WSL2 使用CUDA 程序在 WSL2 里能直接调用到物理 GPU。注意GPU 直通依赖 WSL2 内核版本和 Windows 版本Windows 10 需要 21H2 及以上Windows 11 原生支持。老版本 Windows 10 可能需要在 Windows 功能里手动开启虚拟机平台和适用于 Linux 的 Windows 子系统两个组件。我现在的日常是Windows 侧负责浏览器、文档、通讯工具WSL2 侧负责所有代码、训练、调试。两边通过/mnt/c/和\\wsl$互相访问文件VS Code 装个 Remote-WSL 插件就能无缝开发。这套组合用了两年多跑过 BERT 微调、Stable Diffusion 推理、LLaMA 量化稳定性没问题。2. 装 WSL2 之前必须搞清楚的几个概念在动手之前有几个概念如果不搞清楚后面踩坑会踩得很惨。我见过太多人上来就wsl --install然后发现装到了 C 盘、GPU 调不到、磁盘爆了再回头收拾烂摊子。2.1 WSL1 和 WSL2 的本质区别WSL1 是微软早期做的一个系统调用翻译层它把 Linux 的系统调用实时翻译成 Windows 的对应调用。好处是文件系统性能好、启动快坏处是很多系统调用没法完美翻译比如inotify、epoll的部分行为、fork的语义导致 Docker、某些数据库、部分 Python 库跑不起来。WSL2 换了个思路直接跑一个真正的 Linux 内核放在一个轻量级虚拟机里。系统调用不再翻译而是原生执行。代价是跨文件系统访问变慢因为要走 9P 协议但 Linux 内部的文件操作反而更快。对于深度学习场景WSL2 是唯一选择因为 CUDA 只支持 WSL2。2.2 发行版选择Ubuntu 22.04 还是别的WSL2 支持很多发行版Ubuntu、Debian、Fedora、openSUSE 都有。我推荐 Ubuntu 22.04 LTS理由有三一是 NVIDIA 官方对 Ubuntu 的支持最完善CUDA 文档默认就是 Ubuntu二是绝大多数深度学习框架的预编译包都是针对 Ubuntu 的三是社区资料最多遇到问题好搜。Ubuntu 24.04 也可以但有些老项目的依赖还没跟上比如某些版本的 PyTorch 对 glibc 版本有要求。22.04 是目前最稳的选择。2.3 存储位置千万别默认装 C 盘这是我最想强调的一点。WSL2 的虚拟磁盘默认放在C:\Users\你的用户名\AppData\Local\Packages\下面是一个ext4.vhdx文件。这个文件会随着你装东西不断膨胀而且 WSL2 的虚拟磁盘有个特性删了文件它不会自动缩小。你装个 CUDA 就 5 个 G装个 PyTorch 再加几个 G数据集动辄几十上百 GC 盘很快就红了。正确做法是在安装发行版之前就把默认安装位置改到别的盘。有两种方式一是通过wsl --export和wsl --import迁移二是直接修改注册表或用一个.wslconfig配置。我习惯的做法是先装好然后立刻导出再导入到 D 盘。# 查看已安装的发行版 wsl --list --verbose # 关闭 WSL wsl --shutdown # 导出到 D 盘 wsl --export Ubuntu-22.04 D:\wsl\ubuntu22.04.tar # 注销原来的 wsl --unregister Ubuntu-22.04 # 导入到 D 盘指定目录 wsl --import Ubuntu-22.04 D:\wsl\Ubuntu-22.04 D:\wsl\ubuntu22.04.tar --version 2导入之后默认用户会变成 root需要改回普通用户。编辑/etc/wsl.conf[user] default你的用户名然后在 Windows 侧wsl --shutdown重启一次就生效了。2.4 内存和 CPU 分配WSL2 默认会占用宿主机最多 50% 的内存Windows 11 上是 50%老版本是 80%。如果你机器内存不大跑大模型训练时可能 Windows 侧会卡。可以在用户目录下建一个.wslconfig文件来限制[wsl2] memory32GB processors8 swap8GB localhostForwardingtrue这个文件放在C:\Users\你的用户名\.wslconfig。改完wsl --shutdown重启生效。我一般给 WSL2 分配物理内存的 60% 到 70%留一部分给 Windows 本身。3. GPU 直通WSL2 里调 CUDA 的完整链路这是整个部署里最核心也最容易出问题的部分。很多人以为在 WSL2 里装个 CUDA Toolkit 就完事了其实不是。WSL2 的 GPU 直通有一套独立的驱动模型搞错了就是torch.cuda.is_available()返回 False。3.1 WSL2 GPU 直通的原理传统 Linux 上NVIDIA 驱动分内核态nvidia.ko和用户态libcuda.so两部分。内核态驱动直接和 GPU 硬件通信用户态库提供 CUDA API。WSL2 的情况特殊GPU 硬件是被 Windows 的驱动占用的WSL2 里的 Linux 内核没法直接访问。微软和 NVIDIA 的方案是在 Windows 侧装一个特殊的 WSL 驱动nvidia-smi在 Windows 里能看到这个驱动通过 GPU-PVGPU Paravirtualization把 GPU 能力暴露给 WSL2 虚拟机。WSL2 里只需要装用户态的 CUDA 库不需要装内核态驱动。这就意味着一个关键结论WSL2 里不要装 NVIDIA 的 Linux 显卡驱动。你只需要在 Windows 侧装好驱动然后在 WSL2 里装 CUDA Toolkit 就行。如果你在 WSL2 里手贱装了nvidia-driver-xxx大概率会把环境搞坏。3.2 Windows 侧驱动准备第一步确认你的 Windows 装了支持 WSL 的 NVIDIA 驱动。去 NVIDIA 官网下载最新的 Game Ready 或 Studio 驱动都行版本建议 470 以上。装完之后在 Windows 的 PowerShell 里跑nvidia-smi能看到显卡信息和驱动版本就对了。注意这里的 CUDA Version 显示的是驱动支持的最高 CUDA 版本不是已安装的版本。3.3 WSL2 里验证 GPU 可见性进 WSL2先跑一个命令nvidia-smi如果这个命令能输出和 Windows 侧类似的信息说明 GPU 直通已经通了。如果报command not found说明 WSL2 里没装nvidia-utils但更可能的是 Windows 驱动版本太老或者 WSL 内核太旧。如果nvidia-smi报错说找不到设备先检查 Windows 侧驱动再wsl --update更新 WSL 内核。3.4 CUDA Toolkit 的安装选择WSL2 里装 CUDA Toolkit我推荐用 NVIDIA 官方 apt 源不要用 Ubuntu 自带的nvidia-cuda-toolkit包那个版本太老。# 下载并安装 keyring 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-get update # 安装 CUDA Toolkit这里以 12.1 为例 sudo apt-get install -y cuda-toolkit-12-1注意 URL 里的wsl-ubuntu这是 NVIDIA 专门为 WSL 准备的源和普通 Ubuntu 的源不一样。用错了源可能装出来的版本不兼容。装完之后配置环境变量编辑~/.bashrcexport PATH/usr/local/cuda-12.1/bin:$PATH export LD_LIBRARY_PATH/usr/local/cuda-12.1/lib64:$LD_LIBRARY_PATHsource ~/.bashrc之后跑nvcc --version验证。3.5 CUDA 版本和 PyTorch 的匹配这是新手最容易翻车的地方。PyTorch 的每个版本都是针对特定 CUDA 版本编译的你装的 CUDA Toolkit 版本和 PyTorch 期望的不一致就会出现各种诡异问题。我整理了一个对应关系表方便对照PyTorch 版本推荐 CUDA安装命令后缀2.0.x11.7 / 11.8cu117 / cu1182.1.x11.8 / 12.1cu118 / cu1212.2.x11.8 / 12.1cu118 / cu1212.3.x11.8 / 12.1cu118 / cu1212.4.x12.1 / 12.4cu121 / cu124实际安装时你不需要在系统里装完整的 CUDA ToolkitPyTorch 的 pip 包自带 CUDA runtime。但如果你想编译自定义算子、跑nvcc那就需要装 Toolkit。我的建议是系统里装一个和 PyTorch 匹配的 Toolkit 版本这样最省心。提示nvidia-smi显示的 CUDA Version 是驱动支持的上限不是你装的版本。nvcc --version显示的才是你实际装的 Toolkit 版本。这两个可以不一样但 Toolkit 版本不能超过驱动支持的上限。4. Python 环境conda 还是 venv以及那个经典的 conda 报错环境管理这块我踩过的坑比 GPU 那块还多。尤其是那个conda : 无法将conda项识别的报错几乎每个人都遇到过。4.1 为什么选 Miniconda 而不是 AnacondaAnaconda 预装了几百个包几个 G 的空间大部分你用不上。Miniconda 只带 conda 和 Python干净。深度学习场景下conda 的优势在于它能管理非 Python 的依赖比如 CUDA 库、MKL 数学库这些用 pip 装起来很麻烦。wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh装的时候注意两点一是安装路径建议放在用户目录下比如~/miniconda3二是最后问你是否conda init选 yes。4.2 conda 命令找不到的根因那个conda : 无法将conda项识别的报错根本原因是 shell 没有加载 conda 的初始化脚本。conda 安装时会往~/.bashrc里写一段初始化代码但如果你用的是 zsh或者.bashrc没被 source就会找不到。排查步骤确认~/miniconda3/bin/conda这个文件存在检查~/.bashrc里有没有 conda 的 init 块如果没有手动跑~/miniconda3/bin/conda init bashsource ~/.bashrc或者重开终端如果用的是 zsh把bash换成zsh。如果用的是 fishconda 的支持要单独配置。还有一种情况是你在 Windows 的 PowerShell 里跑 conda 命令。WSL2 里的 conda 和 Windows 的 conda 是两套东西别搞混了。在 WSL2 终端里操作别在 PowerShell 里操作。4.3 创建专用的 PyTorch 环境不要用 base 环境跑项目这是铁律。base 环境搞坏了修复很麻烦。conda create -n pytorch python3.10 -y conda activate pytorchPython 版本选 3.10 或 3.113.12 有些库还没跟上。然后装 PyTorch# CUDA 12.1 版本 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121注意--index-url参数这是 PyTorch 官方的 CUDA 专用源。不加这个参数pip 会从 PyPI 装 CPU 版本。4.4 验证 GPU 是否真的可用装完之后跑一段验证代码import torch print(PyTorch version:, torch.__version__) print(CUDA available:, torch.cuda.is_available()) print(CUDA version:, torch.version.cuda) print(Device count:, torch.cuda.device_count()) print(Device name:, torch.cuda.get_device_name(0)) # 实际跑一个张量运算 x torch.randn(1000, 1000).cuda() y torch.randn(1000, 1000).cuda() z x y print(Matrix multiply on GPU done:, z.shape)如果torch.cuda.is_available()返回 False按这个顺序排查nvidia-smi在 WSL2 里能不能跑通PyTorch 版本和 CUDA 版本是否匹配是不是装了 CPU 版本的 PyTorch看torch.version.cuda是不是 None环境变量LD_LIBRARY_PATH有没有包含 CUDA 的 lib64我遇到过一次折腾半天发现是 pip 装成了 CPU 版因为--index-url拼错了。这种低级错误反而最难发现。5. 那些没人告诉你但一定会遇到的坑前面讲的是标准流程但实际操作中总有一些文档里不写、搜也搜不到的问题。这部分我把我踩过的坑整理出来希望能帮你省点时间。5.1 磁盘空间只增不减WSL2 的 ext4.vhdx 文件有个特性你删了文件它不会自动把空间还给 Windows。跑了几次训练删了数据集C 盘还是满的。解决办法是手动压缩虚拟磁盘。先wsl --shutdown然后用 diskpart# 以管理员身份打开 PowerShell wsl --shutdown diskpart # 在 diskpart 里执行 select vdisk fileD:\wsl\Ubuntu-22.04\ext4.vhdx attach vdisk readonly compact vdisk detach vdisk exit这个过程可能比较慢取决于磁盘大小。压缩完能回收不少空间。5.2 跨文件系统访问的性能陷阱WSL2 访问 Windows 文件/mnt/c/走的是 9P 协议性能很差。如果你把数据集放在 Windows 盘然后在 WSL2 里读IO 会成为瓶颈。我实测过同样的数据集放在 WSL2 内部文件系统比放在/mnt/d/快 5 到 10 倍。所以原则是代码和数据都放在 WSL2 内部Windows 侧只放一些需要共享的文档。如果数据集太大WSL2 磁盘放不下那宁可扩 WSL2 磁盘也别放/mnt/。5.3 内存泄漏和 OOMWSL2 有个已知问题Linux 侧释放的内存不一定马上还给 Windows。跑大模型训练时可能 Linux 里free显示内存充足但 Windows 侧已经快爆了。.wslconfig里可以设置autoMemoryReclaim需要较新的 WSL 版本[wsl2] autoMemoryReclaimgradual这个选项会让 WSL2 定期把空闲内存还给 Windows。如果版本不支持那就只能定期wsl --shutdown重启。5.4 多卡和显存分配WSL2 的 GPU 直通目前对多卡支持有限。如果你机器上有多张 NVIDIA 显卡WSL2 里可能只能看到一张或者看到多张但没法做 P2P 通信。做多卡训练的话WSL2 不是好选择还是得上原生 Linux。单卡场景下显存分配和原生 Linux 没区别。torch.cuda.set_per_process_memory_fraction这些 API 都能正常用。5.5 网络和端口转发WSL2 的网络是 NAT 模式WSL2 里的服务默认 Windows 侧能通过localhost访问因为微软做了端口转发。但如果你在 WSL2 里跑 Jupyter想从局域网其他机器访问就需要额外配置。# 在 WSL2 里启动 Jupyter监听所有网卡 jupyter notebook --ip0.0.0.0 --port8888然后在 Windows 侧用netsh做端口转发或者直接用 WSL2 的 IPip addr能看到。不过 WSL2 的 IP 每次重启会变做固定转发比较麻烦。我的做法是本地开发就用localhost需要远程访问就 SSH 隧道。6. 从零到跑通第一个训练完整实操清单前面讲了原理和坑这部分给一个可以直接抄的完整流程。假设你是一台全新的 Windows 11 机器有一张 NVIDIA 显卡。6.1 系统准备先确认 Windows 版本和虚拟化开启# 查看 Windows 版本 winver # 确认虚拟化已开启任务管理器 - 性能 - CPU - 虚拟化已启用如果虚拟化没开进 BIOS 开启 Intel VT-x 或 AMD-V。6.2 安装 WSL2 和 Ubuntu# 一条命令装好 WSL2 和默认 Ubuntu wsl --install # 重启电脑后Ubuntu 会自动启动设置用户名和密码装完之后立刻迁移到 D 盘参考 2.3 节。然后更新系统sudo apt update sudo apt upgrade -y sudo apt install -y build-essential git wget curl vim6.3 装 NVIDIA 驱动和 CUDAWindows 侧装最新 NVIDIA 驱动。WSL2 侧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配置环境变量然后nvidia-smi和nvcc --version都验证一遍。6.4 装 Miniconda 和 PyTorchwget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh source ~/.bashrc conda create -n pytorch python3.10 -y conda activate pytorch pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu1216.5 跑通验证脚本import torch import time assert torch.cuda.is_available(), CUDA 不可用检查驱动和 PyTorch 版本 device torch.device(cuda) x torch.randn(4096, 4096, devicedevice) y torch.randn(4096, 4096, devicedevice) # 预热 for _ in range(3): z x y torch.cuda.synchronize() # 计时 start time.time() for _ in range(10): z x y torch.cuda.synchronize() elapsed time.time() - start print(f10 次 4096x4096 矩阵乘法耗时: {elapsed:.3f}s) print(f平均每次: {elapsed/10*1000:.1f}ms) print(f显存占用: {torch.cuda.memory_allocated()/1024**3:.2f} GB)这个脚本能跑通说明整个链路没问题。矩阵乘法的耗时可以和你显卡的理论算力对比一下看看有没有明显异常。6.6 VS Code 远程开发配置在 Windows 的 VS Code 里装 Remote - WSL 插件然后CtrlShiftP选 WSL: Connect to WSL。连上之后VS Code 的服务端会跑在 WSL2 里终端、调试、Python 解释器全部走 WSL2 环境。Python 解释器选~/miniconda3/envs/pytorch/bin/python。这样你在 VS Code 里写代码实际执行在 WSL2 的 conda 环境里GPU 也能正常调用。7. 性能实测WSL2 和原生 Linux 到底差多少很多人关心 WSL2 的性能损耗。我用自己的机器做了一组对比测试配置是 i7-12700K 32GB DDR4 RTX 3080 10GB。测试项WSL2原生 Ubuntu差异4096 矩阵乘法10次1.82s1.79s1.7%ResNet50 单张推理8.3ms8.1ms2.5%BERT-base 微调1 epoch142s138s2.9%磁盘顺序读1GB1.2GB/s2.8GB/s-57%磁盘随机读4K45K IOPS180K IOPS-75%结论很清晰GPU 计算性能几乎无损磁盘 IO 有明显差距。所以如果你的瓶颈在 GPUWSL2 完全够用如果瓶颈在数据加载那要么优化数据管道用num_workers多进程预取要么考虑原生 Linux。我实际跑 LLaMA-7B 的 LoRA 微调WSL2 和原生 Linux 的每步耗时差距在 3% 以内。对于个人开发和小规模训练这个损耗完全可以接受。8. 一些零散但有用的经验最后分享几个零散的点都是实际用下来觉得有价值的。关于nvidia-smi在 WSL2 里刷新慢的问题这是正常的因为要走虚拟化层。想看实时显存占用可以在 Windows 侧用任务管理器或者装个 GPU-Z。关于 CUDA 版本迁移如果你要从 CUDA 11.8 升到 12.1最干净的做法是删掉 conda 环境重建而不是在现有环境里升级。CUDA 相关的库版本依赖很复杂升级容易搞出玄学问题。关于torch.cuda.OutOfMemoryErrorWSL2 下的显存管理和原生 Linux 基本一致但有个细节WSL2 里nvidia-smi显示的显存占用可能和torch.cuda.memory_allocated()对不上因为前者包含 CUDA context 的开销。排查 OOM 时以 PyTorch 的统计为准。关于备份WSL2 的整个环境就是一个 vhdx 文件定期wsl --export备份一下换机器或者环境搞坏了直接导入恢复比重新配一遍快得多。我现在保持每月导出一次的习惯文件放移动硬盘。关于 Windows 和 WSL2 的文件互访从 WSL2 访问 Windows 用/mnt/c/从 Windows 访问 WSL2 用\\wsl$\Ubuntu-22.04\。后者在文件资源管理器地址栏直接输入就能进很方便。这套环境我从 2022 年用到现在跑过各种模型稳定性没问题。唯一一次翻车是 Windows 自动更新把 WSL 内核搞挂了wsl --update一下就好了。整体来说WSL2 做 AI 开发环境对于个人开发者和小团队是目前 Windows 平台上最省心的方案。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。