
1. 为什么要在 Windows 上折腾内核级 Linux 开发环境如果你是一个长期在 Windows 上做 AI 开发的从业者大概率经历过这样的场景本地跑一个 PyTorch 训练脚本Windows 原生 Python 环境各种 DLL 冲突、CUDA 版本对不上、某些 Linux 专属的编译工具链根本装不了最后不得不开一台云服务器或者装双系统。双系统切换麻烦云服务器按小时计费又心疼尤其是做模型调试和数据处理这种需要反复试错的活儿本地环境的响应速度直接决定了你的迭代效率。WSL2 就是在这个夹缝里长出来的一个方案。它不是虚拟机也不是简单的兼容层而是微软在 Windows 内核里内置了一个轻量级的 Linux 内核通过 Hyper-V 的虚拟化能力跑一个真正的 Linux 发行版。你可以在 Windows 里直接敲bash跑apt install用nvidia-smi看显卡甚至跑 Docker 容器。最关键的是从 WSL2 开始微软加入了 GPU 直通能力也就是 Windows 主机上的 NVIDIA 显卡可以直接被 WSL2 里的 Linux 环境调用CUDA 计算不再被挡在门外。这套方案适合谁第一类是做深度学习训练和推理的开发者需要在本地快速验证模型、调试数据管道第二类是做数据科学和科学计算的从业者依赖 Linux 下的编译工具和 Python 生态第三类是想学 Linux 但不想折腾双系统的新手WSL2 提供了一个几乎零成本的入门环境。这篇文章我会从零开始把 WSL2 的安装、GPU 直通配置、CUDA 环境搭建、常见坑点全部拆开讲清楚每一步都告诉你为什么这么做以及我实际踩过的坑。2. WSL2 的安装与内核级 Linux 环境初始化2.1 确认硬件与系统前提条件在动手之前先确认你的机器满足几个硬性条件。CPU 需要支持虚拟化技术Intel 的 VT-x 或者 AMD 的 AMD-V这个在 BIOS 里通常是默认开启的但有些品牌机出厂会关掉。你可以在任务管理器里看“性能”标签页CPU 那一栏右下角会显示“虚拟化已启用”或“已禁用”。如果显示禁用重启进 BIOS 找到 Virtualization Technology 选项打开。系统版本方面WSL2 要求 Windows 10 版本 1903 及以上或者 Windows 11 任意版本。我建议直接上 Windows 11因为 WSL2 在 Win11 上的 GPU 直通支持更完整而且 Windows Terminal 的体验好很多。另外如果你用的是 NVIDIA 显卡驱动版本需要满足最低要求这个后面会细说。还有一个容易被忽略的点Windows 功能里的“虚拟机平台”和“适用于 Linux 的 Windows 子系统”这两个可选组件必须开启。很多人只开了后者结果 WSL2 启动时报错就是因为虚拟机平台没开。2.2 安装 WSL2 的两种路径与选择逻辑安装 WSL2 有两条路。第一条是命令行一键安装在管理员权限的 PowerShell 里执行wsl --install这条命令会自动开启所需组件、下载最新内核、安装默认的 Ubuntu 发行版然后提示你重启。重启后设置用户名和密码就能用了。这是最省事的方式适合全新环境。第二条路是手动分步安装适合已经装过 WSL1 或者想自定义发行版的情况。步骤是先dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart开启子系统功能再dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart开启虚拟机平台重启后下载 WSL2 内核更新包安装最后wsl --set-default-version 2把默认版本设为 2。我为什么推荐第一条路因为手动安装容易漏掉内核更新包这一步导致wsl --set-version 2报错“请运行 wsl --update”。一键安装虽然简单但它默认装的是 Ubuntu如果你想要别的发行版可以用wsl --install -d Debian或者wsl --list --online看有哪些可选。2.3 首次启动后的基础配置装完之后第一次进 Ubuntu系统会让你创建用户名和密码。这个用户名和 Windows 用户名是独立的密码在输入时不会显示正常现象。进去之后第一件事是更新软件源sudo apt update sudo apt upgrade -y然后装一些基础工具比如build-essential、git、curl、wget。这些在后面编译 Python 包和拉取代码时都会用到。另外建议把默认的 shell 换成 zsh 或者至少装个oh-my-zsh因为 WSL2 里的 bash 补全和提示不如 zsh 顺手尤其是做 AI 开发经常要在多个 conda 环境之间切换zsh 的插件能省不少事。还有一个关键配置WSL2 的内存和 CPU 分配。默认情况下 WSL2 会占用主机一半的内存如果你主机是 32GWSL2 最多能用 16G。但有时候跑大模型训练需要更多内存可以在 Windows 用户目录下创建一个.wslconfig文件写入[wsl2] memory24GB processors8 swap8GB这个文件放在C:\Users\你的用户名\下改完执行wsl --shutdown再重启生效。注意 memory 不要设得太大给 Windows 主机留至少 8G否则主机本身会卡。3. GPU 直通的核心原理与驱动配置3.1 WSL2 GPU 直通到底是怎么实现的很多人以为 WSL2 里能用 GPU 是因为微软做了某种“模拟”其实不是。WSL2 的 GPU 直通走的是 GPU 半虚拟化技术微软在 Windows 主机上安装的显卡驱动里内置了一个特殊的 WDDM 驱动模型它会把 GPU 的计算能力通过/dev/dxg这个设备节点暴露给 WSL2 的 Linux 内核。Linux 侧再通过一个叫dxgkrnl的内核模块和用户态的libdxcore库把 CUDA 调用翻译成主机能理解的指令。换句话说WSL2 里的 CUDA 并不是在 Linux 内核里直接驱动显卡而是通过一个“翻译层”把计算任务转发给 Windows 主机的驱动。这个设计的好处是你不需要在 WSL2 里单独装显卡驱动只需要在 Windows 主机上装好驱动就行。坏处是某些底层特性可能不如原生 Linux 完整比如某些需要直接访问 GPU 硬件的调试工具可能跑不了。理解这个原理很重要因为它决定了你装驱动的顺序先在 Windows 装驱动再在 WSL2 里装 CUDA Toolkit顺序反了会各种报错。3.2 Windows 主机驱动的正确安装方式在 Windows 上装 NVIDIA 驱动最稳妥的方式是去 NVIDIA 官网下载对应型号的驱动而不是用 Windows Update 自动推送的版本。自动推送的版本往往偏旧而且可能不带 WSL2 所需的组件。下载时选择“GeForce”或“Quadro”对应你的显卡系列操作系统选 Windows 11下载类型选“Game Ready 驱动”或“Studio 驱动”都行Studio 驱动更稳定适合开发场景。安装时有一个关键选项在自定义安装里确保“NVIDIA 图形驱动程序”和“NVIDIA CUDA 驱动”都勾选。有些人为了省空间只装图形驱动结果 WSL2 里nvidia-smi找不到设备。装完之后在 Windows 的 PowerShell 里执行nvidia-smi能看到显卡信息就说明主机驱动没问题。这里有个坑如果你之前装过旧版驱动最好先用 DDU 工具彻底卸载再装新版否则残留的驱动文件可能导致 WSL2 里的 CUDA 版本和主机驱动不匹配。我遇到过主机驱动是 535 版本WSL2 里装了 CUDA 12.2结果torch.cuda.is_available()返回 False折腾了半天才发现是驱动残留导致的。3.3 WSL2 内 CUDA Toolkit 的安装与版本匹配Windows 主机驱动装好后进 WSL2 的 Ubuntu先验证 GPU 是否可见nvidia-smi如果这条命令能输出显卡型号、驱动版本、CUDA 版本说明 GPU 直通已经通了。注意这里的 CUDA 版本是主机驱动支持的最高版本不是你实际安装的版本。接下来装 CUDA Toolkit。很多人直接apt install nvidia-cuda-toolkit这是 Ubuntu 仓库里的版本往往偏旧而且不带 cuDNN。正确做法是去 NVIDIA 官网的 CUDA Toolkit 下载页选择 Linux - x86_64 - WSL-Ubuntu - 你的 Ubuntu 版本然后按照给出的命令安装。以 CUDA 12.3 为例wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600 wget https://developer.download.nvidia.com/compute/cuda/12.3.0/local_installers/cuda-repo-wsl-ubuntu-12-3-local_12.3.0-1_amd64.deb sudo dpkg -i cuda-repo-wsl-ubuntu-12-3-local_12.3.0-1_amd64.deb sudo cp /var/cuda-repo-wsl-ubuntu-12-3-local/cuda-*-keyring.gpg /usr/share/keyrings/ sudo apt-get update sudo apt-get -y install cuda-toolkit-12-3装完后把 CUDA 路径加到.bashrc或.zshrcexport PATH/usr/local/cuda-12.3/bin:$PATH export LD_LIBRARY_PATH/usr/local/cuda-12.3/lib64:$LD_LIBRARY_PATH然后source ~/.bashrc生效。验证nvcc --version能看到版本号。版本匹配是这里最大的坑。主机驱动版本决定了 WSL2 能支持的最高 CUDA 版本比如驱动 535 支持到 CUDA 12.2你硬装 CUDA 12.3 的 Toolkit编译时可能不报错但运行 PyTorch 时会提示“CUDA driver version is insufficient”。所以装之前先nvidia-smi看右上角的 CUDA Version那个数字就是上限。4. Python 与深度学习框架的环境搭建4.1 Miniconda 的安装与虚拟环境管理AI 开发离不开 Python 环境管理我强烈建议用 Miniconda 而不是系统自带的 Python。WSL2 的 Ubuntu 自带 Python 3.10 或 3.11但系统级的 pip 安装容易污染全局环境而且不同项目对 PyTorch、TensorFlow 的版本要求不一样用 conda 隔离最省心。下载安装wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh安装时一路回车最后问是否conda init选 yes。重开终端后conda --version能输出版本号。然后创建环境conda create -n ai python3.10 conda activate ai为什么选 Python 3.10因为截至我写这篇文章时PyTorch 2.x 和 TensorFlow 2.15 对 3.10 的支持最稳定3.11 有些包还没跟上3.12 更不用说。做 AI 开发不要追最新 Python 版本稳定压倒一切。4.2 PyTorch 的 GPU 版本安装与验证在 conda 环境里装 PyTorch不要用pip install torch那样装的是 CPU 版本。正确做法是去 PyTorch 官网的安装页面选择对应的 CUDA 版本复制命令。比如 CUDA 12.1pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121装完后验证import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0))如果is_available()返回 True说明 GPU 直通和 PyTorch 都配好了。如果返回 False先检查nvidia-smi是否正常再检查 PyTorch 版本和 CUDA 版本是否匹配。常见问题是装了 cu121 的 PyTorch 但主机驱动只支持到 CUDA 12.0这时候要么升级主机驱动要么重装低版本 PyTorch。还有一个坑WSL2 里torch.cuda.is_available()第一次调用可能比较慢因为要初始化 dxgkrnl 通道等几秒正常。如果一直 False试试export CUDA_VISIBLE_DEVICES0显式指定设备。4.3 TensorFlow 与其他框架的兼容性处理TensorFlow 在 WSL2 上的 GPU 支持稍微麻烦一点。从 TF 2.10 开始官方不再提供 Windows 原生 GPU 支持但 WSL2 是支持的。安装方式和 Linux 一样pip install tensorflow[and-cuda]装完后验证import tensorflow as tf print(tf.config.list_physical_devices(GPU))如果输出空列表检查 cuDNN 是否安装。TF 需要 cuDNN 8.x而 PyTorch 对 cuDNN 的依赖相对宽松。你可以在 NVIDIA 官网下载 cuDNN 的 tar 包解压后把文件复制到 CUDA 目录tar -xvf cudnn-linux-x86_64-8.x.x.x_cudaX.X-archive.tar.xz sudo cp cudnn-*-archive/include/cudnn*.h /usr/local/cuda/include sudo cp -P cudnn-*-archive/lib/libcudnn* /usr/local/cuda/lib64 sudo chmod ar /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn*这里注意 cuDNN 版本要和 CUDA 版本对应比如 CUDA 12.x 配 cuDNN 8.9 以上。版本不对会报libcudnn.so.8: cannot open shared object file。5. 文件系统性能与开发工作流优化5.1 跨文件系统访问的性能陷阱WSL2 有一个非常关键的架构特点它的 Linux 文件系统是一个 ext4 格式的虚拟磁盘存放在 Windows 的%LOCALAPPDATA%\Packages\...\LocalState\ext4.vhdx里。而 Windows 的文件系统是 NTFS。当你从 WSL2 里访问 Windows 文件比如/mnt/c/Users/...或者从 Windows 访问 WSL2 文件\\wsl$\Ubuntu\home\...都要经过一层 9P 协议的文件共享层性能损耗非常大。我实测过在/mnt/c/下跑pip install或者解压数据集速度比在 WSL2 原生文件系统里慢 5 到 10 倍。所以做 AI 开发项目代码和数据集一定要放在 WSL2 的原生目录下比如~/projects和~/datasets。Windows 那边只用来放一些不常访问的备份文件。如果你习惯用 Windows 的 IDE 比如 VS Code 编辑代码不用担心VS Code 有 Remote-WSL 插件可以直接连到 WSL2 里编辑原生文件体验和本地一样。PyCharm 也有 WSL 支持在设置里把解释器指向 WSL2 的 conda 环境就行。5.2 数据盘挂载与磁盘空间管理WSL2 的虚拟磁盘默认是动态扩展的你往里写多少数据vhdx 文件就涨多大但删数据后 vhdx 不会自动缩小。时间长了可能占掉几十 G 空间。压缩方法是wsl --shutdown diskpart select vdisk fileC:\Users\你的用户名\AppData\Local\Packages\...\LocalState\ext4.vhdx attach vdisk readonly compact vdisk detach vdisk exit这个操作我建议每个月做一次尤其是经常删数据集的人。另外如果你有额外的 SSD 或者机械盘可以把数据集放在 Windows 的某个盘里然后在 WSL2 里挂载。但前面说了跨文件系统性能差所以更好的做法是把整个 WSL2 的虚拟磁盘迁移到那块盘上。迁移命令是wsl --export导出再wsl --import导入到新位置。这样既扩大了空间又保持了原生文件系统性能。5.3 端口转发与远程访问配置WSL2 的网络是 NAT 模式它有自己的虚拟网卡和 IPWindows 主机访问 WSL2 的服务需要端口转发。比如你在 WSL2 里跑 Jupyter Notebook默认监听localhost:8888Windows 浏览器直接访问localhost:8888是通的因为 WSL2 做了 localhost 转发。但如果你想让局域网里其他机器访问就需要在 Windows 上做端口转发netsh interface portproxy add v4tov4 listenport8888 listenaddress0.0.0.0 connectport8888 connectaddress$(wsl hostname -I)这条命令把 Windows 的 8888 端口转发到 WSL2 的 8888。注意 WSL2 的 IP 每次重启会变所以这个命令要写进脚本每次开机跑。或者更简单的方式是用wsl --hostname固定主机名然后在 Windows 的 hosts 文件里加一条解析。做 AI 开发经常需要起 TensorBoard、Streamlit、FastAPI 这些服务端口转发配好了你可以在主机浏览器里直接调试不用在 WSL2 里折腾命令行浏览器。6. 常见故障的排查链路与修复方案6.1 nvidia-smi 报错“No devices were found”这是 WSL2 GPU 直通最常遇到的问题。排查顺序是这样的第一步在 Windows PowerShell 里跑nvidia-smi如果主机都找不到显卡那是主机驱动问题重装驱动。第二步如果主机正常但 WSL2 里报错检查 Windows 功能里的“虚拟机平台”是否开启没开的话 GPU 直通不工作。第三步检查 WSL2 内核版本uname -r应该显示 5.10 以上低版本内核不支持 dxgkrnl。第四步如果以上都正常试试wsl --update更新内核然后wsl --shutdown重启。我遇到过一次特殊情况主机驱动是 525 版本WSL2 里nvidia-smi报错升级到 535 后解决。后来查资料发现 525 版本对 WSL2 的 GPU 直通支持有 bug所以驱动版本不要太旧建议至少 530 以上。6.2 PyTorch 报“CUDA out of memory”但显存明明够这个问题的根源往往不是显存不够而是 WSL2 的内存分配限制。WSL2 默认最多用主机一半内存如果你的模型需要大量 pinned memory 或者数据加载器开了很多 worker可能触发内存瓶颈报错却显示 CUDA OOM。解决办法是在.wslconfig里加大 memory 和 swap然后重启 WSL2。另一个可能是 PyTorch 的缓存分配器碎片化。可以在代码开头加torch.cuda.empty_cache()或者设置PYTORCH_CUDA_ALLOC_CONFmax_split_size_mb:128来优化分配策略。6.3 训练过程中 WSL2 突然卡死或重启WSL2 在高负载下偶尔会卡死尤其是 GPU 和 CPU 同时满载时。这通常是因为 WSL2 的虚拟化层资源调度跟不上。缓解办法有几个一是限制 DataLoader 的num_workers不要设成 CPU 核心数设成一半左右二是在.wslconfig里给 WSL2 分配固定的 CPU 核心不要让它和 Windows 主机抢三是关闭 Windows 的“内存压缩”功能这个功能在 WSL2 高负载时会拖后腿。还有一个隐藏坑Windows 的快速启动功能会导致 WSL2 的虚拟磁盘状态异常。建议在控制面板的电源选项里关闭“启用快速启动”虽然开机慢几秒但 WSL2 稳定性会好很多。6.4 pip 安装包时编译报错缺少头文件在 WSL2 里 pip 安装某些包比如apex、deepspeed时需要编译 CUDA 扩展报错fatal error: cuda_runtime.h: No such file or directory。这是因为 CUDA 的头文件路径没加到编译器的搜索路径里。解决办法是确保CUDA_HOME环境变量指向/usr/local/cuda并且PATH和LD_LIBRARY_PATH都配好了。如果还不行装一个cuda-toolkit的完整包不要只装 runtime。另外编译时用的 gcc 版本也要注意。Ubuntu 22.04 默认 gcc 11某些老版本 CUDA 只支持到 gcc 10这时候要么降级 gcc要么加-allow-unsupported-compiler参数。我一般建议直接升级 CUDA 到 12.x对 gcc 11 支持很好。7. 我在这套环境上跑通的实际工作流7.1 从数据预处理到模型训练的完整链路我目前的日常流程是这样的数据集放在~/datasets用 pandas 或 polars 做预处理中间结果存成 parquet 格式。训练脚本放在~/projects用 conda 环境隔离依赖。启动训练时用nohup或者tmux挂后台因为 WSL2 的终端关掉后进程会断。tmux 是必须装的sudo apt install tmux然后tmux new -s train开一个会话在里面跑训练关终端也不影响。监控方面nvidia-smi -l 1可以每秒刷新显存和利用率或者用watch -n 1 nvidia-smi。TensorBoard 在 WSL2 里跑Windows 浏览器访问localhost:6006实时看 loss 曲线。这套流程跑下来从数据到模型验证全部在本地完成不需要连服务器。7.2 与 Windows 工具链的协作方式虽然开发在 WSL2 里但有些工具还是 Windows 上的好用。比如看图片用 Windows 照片查看器处理 Excel 用 Office这些都不需要进 WSL2。文件互传用\\wsl$\Ubuntu\home\用户名这个路径在 Windows 资源管理器里直接访问。但记住只传小文件大文件走 WSL2 原生目录。VS Code 的 Remote-WSL 是我最推荐的组合。在 WSL2 里code .直接打开当前目录VS Code 会自动装 WSL 服务端然后你就能在 Windows 的界面里编辑 Linux 文件终端也是 WSL2 的。调试 Python 时断点、变量查看都正常体验和本地开发没区别。7.3 这套方案的边界与不适合的场景WSL2 不是万能的。如果你的模型需要多卡 NVLink 通信WSL2 不支持因为 GPU 直通只暴露单卡的 PCIe 通道。如果你需要 RDMA 或者 InfiniBandWSL2 也没有。另外某些需要直接操作 GPU 硬件的性能分析工具比如 Nsight Systems 的某些底层功能在 WSL2 里可能受限。还有一个现实问题WSL2 的 GPU 性能相比原生 Linux 有大约 5% 到 10% 的损耗这是虚拟化层的开销。对于调试和中小规模训练完全够用但如果是大规模分布式训练还是建议上原生 Linux 服务器。我的定位很明确WSL2 是本地开发调试环境不是生产训练环境。用它来快速验证想法、调试代码、跑小规模实验效率比连远程服务器高得多。这套环境我用了大半年从最初的驱动装不上到后来跑通 PyTorch、TensorFlow、JAX 三个框架中间踩的坑基本都在这篇文章里了。如果你按这个流程走大部分问题都能避开。剩下的就是动手装装完跑个nvidia-smi和torch.cuda.is_available()看到 True 的那一刻后面的事就顺了。