ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

WSL2搭建AI开发环境:Windows下CUDA与PyTorch实战指南

WSL2搭建AI开发环境:Windows下CUDA与PyTorch实战指南

在Windows上搞AI开发,过去是一件很拧巴的事。Windows能跑PyTorch,能跑CUDA,社区教程也不少,可一旦涉及到Linux only的库、Docker容器、训练加速组件,或者你想保证本地环境和生产服务器一致,原生Windows环境就会变成一场事故现场。早年间我试过双系统,也试过在VMware里折腾GPU穿透,结果都不算理想——一个要频繁重启切换,另一个性能和稳定性都不太行。直到WSL2逐渐成熟,才真正解决了“Windows机器上跑Linux AI环境”这个问题。

今天我从WSL2的内核级Linux特性讲起,说清楚它和传统虚拟机在GPU使用上的本质区别,然后带你从零搭一套可用的AI开发环境:从BIOS虚拟化检查、WSL2安装与D盘搬迁,到CUDA工具链、Miniconda、PyTorch的安装验证,最后跑一个真实的小模型推理,并整理几个我实际踩过、大家在社区里问得最多的雷。无论你是第一次接触WSL2,还是已经在Windows上被AI环境折磨过一阵子,这篇应该能给你一些可以直接落地的操作。

1. 为什么是 WSL2:从“伪 Linux”到内核级 Linux 的质变

1.1 Windows 上做 AI 的痛点,绕不开

我早期在Windows下做Python数据分析和模型调试,跑个sklearn还好,一旦涉及需要编译C++扩展的包,例如tokenizers、llvmlite,Windows下经常要装一堆Visual C++ Build Tools,还偶尔编译失败。更难受的是,很多AI基础设施根本没有Windows版本,或者只在Linux上提供完整支持。比如NCCL,多卡通信库在Windows上是缺失的;Docker Desktop的容器核心本质上也要靠Linux VM来跑;再比如vLLM这类推理框架,官方只支持Linux。生产环境的训练服务器清一色Linux,本地开发环境却是Windows,环境一致性很难保证。

有人会说,那就装双系统嘛,训练的时候启动Linux。但日常调代码、看数据、开会做文档都在Windows里,反复重启切换真的很劝退。传统虚拟机VMware/VirtualBox呢?把PCIe网卡映射还算常见,GPU穿透却是另一个难度等级,不仅要额外配置显卡,而且性能损耗不小。这些痛点叠加起来,WSL2就成了一条大家绕不开的路。

1.2 WSL1 与 WSL2 的差距不在版本号,在系统调用

WSL1其实不是虚拟机,它是一个系统调用翻译层,把Linux程序发起的系统调用翻译成Windows NT内核的调用。听着很妙,实际坑很多:Docker跑不了,FUSE不支持,inotify行为怪异,一些依赖内核特性的应用直接崩。所以WSL1被社区调侃是“伪Linux”。

WSL2则完全不同——它运行在轻量级Hyper-V虚拟机上,加载的是微软使用开源代码维护的真正的Linux内核(microsoft-standard-WSL2),系统调用原生执行,兼容性上基本可以当成一台真实的Ubuntu服务器。我自己从WSL1切到WSL2后,最大的感受是:能把生产环境那套Docker Compose原样搬到本地跑,不再担心“环境不一致,在我这是好的”这种话。

维度WSL1WSL2传统VM
Linux内核无,系统调用翻译有,微软维护的开源内核有,完整内核
启动速度秒级秒级(轻量VM)分钟级
系统调用兼容性不完整原生兼容原生兼容
Docker支持不支持完整支持完整支持
GPU加速无支持CUDA等需额外直通配置,复杂度高
跨OS文件IO较快/mnt/c路径偏慢慢
内存占用低受.wslconfig管控通常较大

1.3 别把“GPU 直通”想歪了,WSL2 的机制是 GPU-PV

标题里写了“GPU直通”,但我要先说清楚:WSL2里的GPU加速,并不是传统虚拟机里那种PCIe直通,也就是把物理显卡整个交给虚拟机独占的VFIO方案。微软和NVIDIA合作实现的,是GPU-PV(para-virtualization),思路很简单:Windows侧拥有物理GPU和WDDM驱动,WSL2的Linux内核里有一个虚拟GPU驱动(dxgkrnl),Linux用户态程序(CUDA库)把计算请求通过这个虚拟总线送到Windows物理驱动上执行。

这个设计带来的实际好处是Windows和WSL2能同时用GPU。我可以Windows里开着浏览器看视频,WSL2里同时跑一个小训练,互相不干扰。而传统直通模式下,虚拟机独占显卡,Windows宿主机就没法用它了。

代价也很明显:WSL2里不需要也不应该安装Linux版NVIDIA驱动,只需要安装CUDA Toolkit。很多人在WSL2里下载并运行了NVIDIA官方Linux驱动的.run包,结果内核模块加载失败,直接导致WSL2启动不了,这是新手最容易踩的坑,后面会单独讲。

2. 开工之前先检查三件事:虚拟化、系统版本和显卡驱动

2.1 虚拟化没开启,后面一切都是白搭

社区里有一条很有代表性的报错:运行wsl --install -d ubuntu-24.04时报错“WSL2 无法启动,因为此计算机上未启用虚拟化”。我见过不少朋友卡在这里,他们的电脑其实性能很强,就是BIOS里虚拟化没开。

检查方法很简单:打开任务管理器,切到“性能”,再点“CPU”,看右下角“虚拟化”是否显示“已启用”。如果显示“已禁用”,重启进BIOS/UEFI,找到Intel VT-x/VT-d(AMD平台是SVM Mode)并开启。主板品牌不同,菜单位置也略有差异,搜索一下自己主板型号就行。

除了BIOS,Windows层面还需要两个可选功能:适用于Linux的Windows子系统和虚拟机平台。在管理员PowerShell里运行下面两条命令,然后重启:

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

新版Windows 11直接用wsl --install会自动启用这些功能,一般不用手动管。但如果你有安全软件或旧版Hyper-V配置残留,同样会踩到虚拟化未启用的报错,下面第6部分会展开讲。

2.2 Windows 版本与 WSL 内核的匹配

WSL2对Windows版本有要求。Windows 10 2004以上基本都支持,但建议至少是21H2,越新越好;Windows 11则没有问题。如果遇到提示“WSL2 尚未准备就绪”之类的话,多半是WSL2的内核更新包没有安装或太旧。在管理员PowerShell里跑一下:

wsl --update wsl --set-default-version 2

如果wsl --update因为网络问题失败,也可以到微软官方下载中心拿到WSL2内核更新包的离线MSI安装文件,装完再wsl --set-default-version 2。这里要多说一句:WSL2的整体组件和单独发行版镜像是分开的,wsl --install会同时处理两者,但旧版Windows或者手动安装时容易漏掉内核更新包,于是就会出现各种奇怪报错。所以遇到WSL启动异常,先跑一遍wsl --update通常是最快的诊断手段。

2.3 显卡驱动:一个 Windows 驱动通吃两边

WSL2里要使用NVIDIA GPU,Windows侧需要安装NVIDIA驱动,并且版本要够新。从实践上说,直接去NVIDIA官网下载最新的Game Ready或Studio驱动安装就好。注意不需要在WSL2 Linux内部安装驱动,Windows驱动会被虚拟化协议共享给WSL2使用。

验证驱动是否正常,可以先在Windows PowerShell里运行nvidia-smi,能看到显卡信息就说明驱动OK。这一步非常基础,但很多教程跳过了,导致后面在WSL2里排查半天,最后发现是Windows驱动太旧。如果你用AMD显卡或者Intel核显,WSL2也支持DirectML加速,可以跑ONNX Runtime这类推理框架,但本文以NVIDIA+CUDA为主线,因为目前AI大模型生态里CUDA是绝对主流。

3. 安装与搬迁:把 WSL2 装好并放到 D 盘上

3.1 用 wsl --install 装发行版

在管理员PowerShell里执行:

wsl --install -d Ubuntu-24.04

这个命令会下载并安装Ubuntu 24.04 LTS。如果不指定发行版,默认是当前推荐的Ubuntu版本。装完后会要求设置一个Unix用户名和密码,记住:这个密码以后用sudo时会频繁使用。如果执行后提示虚拟化未开,回到上一章检查BIOS;如果卡在下载阶段,参考3.3节。

也可以先执行wsl --list --online看看有哪些发行版可选,比如Ubuntu、Debian、Kali Linux、openSUSE等。AI开发我默认推荐Ubuntu LTS版本,理由很简单:社区资料最多,CUDA、conda、PyTorch的兼容性验证都是围绕Ubuntu做的。

3.2 迁移到 D 盘:export/import 是最可靠的路

WSL2默认会把发行版VHD文件放在C盘用户目录下,跑的模型、数据集稍微大一点,C盘就爆了。我比较推荐export/import这条路线,因为可控性强,还能顺便备份:

wsl --shutdown wsl --export Ubuntu-24.04 D:\wsl-backup\ubuntu-24.04.tar wsl --unregister Ubuntu-24.04 wsl --import Ubuntu-24.04 D:\wsl\ubuntu-24.04 D:\wsl-backup\ubuntu-24.04.tar

--unregister会注销并删除C盘上的发行版,相当于格式化整个环境;--import后面第二个路径是新的VHD存放目录,第三个是tar包路径。导入完成后,WSL会默认以root用户登录,需要手动改回之前的用户名。有个特实用的表:

问题解决方法
import后默认用户是root进入WSL后执行 `echo -e "[user]\ndefault=你的用户名"
tar包太大,导出慢导出前先sudo apt clean并清理conda缓存,体积能小不少

导出和导入确实会花一些时间,尤其tar包几十上百GB的时候。有朋友问能不能直接拷贝VHD文件,理论上可以,但前提是发行版处于shutdown状态,而且直接拷贝不如export/import干净,建议还是按标准流程走。

3.3 下载慢和卡死的处理

wsl --install本质是从微软官方服务器拉取发行版和应用包,国内网络环境下卡在“正在下载”很常见。我的处理思路是绕开在线安装,手动下载离线包:

  • WSL2内核更新包:微软官网有wsl_update_x64.msi离线安装文件,下到本地直接装。
  • 发行版离线安装:微软为每个发行版提供了Appx离线包,下载后用Add-AppxPackage命令安装,或者找网络通畅的时间点安装。

进入WSL2之后,apt更新慢的问题更好解决。修改/etc/apt/sources.list,或者用Ubuntu新版本支持的deb822格式,把源换成可用的国内镜像源。这个操作属于常规运维技巧,按通用教程操作即可,不展开。

3.4 基础配置:换源、启用 systemd、装必要工具

装完WSL2之后,我一般立刻做三件事。

  1. 更新系统:sudo apt update && sudo apt upgrade -y
  2. 启用systemd。新版WSL2支持systemd,编辑sudo nano /etc/wsl.conf,加入:
[boot] systemd=true

然后wsl --shutdown再启动。启用systemd后,Docker、SSH、定时任务这些服务才能用标准方式管理,对后面的AI开发很关键。

  1. 安装基础工具:sudo apt install -y build-essential git curl wget unzip vim。AI编译依赖很多,build-essential一般必须装。

注意修改完wsl.conf必须wsl --shutdown,不是单纯退出终端的那种“关闭”。这是新手经常弄错的地方,配置文件改了不生效,以为是bug,其实是WSL还没有完全停止。

4. 装 CUDA 工具链和 PyTorch:WSL2 变成一台小型训练机

4.1 先理解 WSL2 的 CUDA 架构

在WSL2里跑AI,需要分清两套东西:Windows侧的NVIDIA驱动负责物理GPU计算请求的最终执行;WSL2 Linux侧的CUDA Toolkit提供nvcc编译器、CUDA运行时库、开发头文件等。PyTorch的CUDA版本运行时其实已经内置了一部分驱动API,但如果你要用nvcc编译自定义CUDA算子,就必须安装完整的Toolkit。

在WSL2里执行nvidia-smi时,输出的Driver Version显示的是Windows驱动的版本,CUDA Version是当前驱动最高支持的CUDA版本。也就是说,WSL2内的CUDA能力上限实际上由Windows驱动版本决定,而不是由Linux侧的Toolkit决定。

这一节说清楚,大家就不会再纠结“为什么我在WSL2里装Linux驱动报错”了——因为压根不需要装。微软和NVIDIA的WSL2方案里,驱动的所有权在Windows侧。

4.2 安装 CUDA Toolkit

NVIDIA对WSL2提供了专用的wsl-ubuntu软件源,安装命令如下:

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 cuda-toolkit-12-4

注意安装的是cuda-toolkit-12-4而不是cuda,后者会尝试安装CUDA驱动包,在WSL2里是多余且容易出问题的。具体包名版本以NVIDIA官网WSL-Ubuntu repo页为准,通常是大版本对应一个包,比如cuda-toolkit-12-4、cuda-toolkit-12-6。

装完验证:

nvcc --version

能输出版本信息即可。如果你只跑PyTorch、不直接写CUDA算子,其实不装完整Toolkit也能跑,因为PyTorch的pip包会带CUDA运行时。但我建议还是装,因为很多第三方库在编译扩展时会去找nvcc,没有它编译报错。

4.3 用 Miniconda 管好 Python 环境

AI开发最忌讳把系统Python搞乱。我强烈建议装Miniconda,理由很直白:项目之间的依赖隔离、包升级不互相影响、创建环境秒级完成。

wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh

安装过程中一路yes,结束后重开终端,创建项目环境:

conda create -n ai python=3.10 -y conda activate ai

国内用户如果觉得conda下载慢,可以配置国内镜像源,这也是常规操作。现在也有更快的uv可以做Python环境管理,但Miniconda在AI生态里的通用性依然最好,新手照着社区教程走不容易卡壳。

4.4 安装 PyTorch 并验证 GPU 可用

以CUDA 12.1版本对应的PyTorch为例:

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

如果你安装了其他CUDA版本,就去PyTorch官网选对应的命令。装完后第一条GPU验证命令:

python -c "import torch; print(torch.cuda.is_available(), torch.cuda.get_device_name(0))"

正常情况下输出True NVIDIA GeForce RTX 4090之类的信息。看到True,说明WSL2到GPU的链路已经通了,你可以开始跑模型了。如果输出False,不要慌,大部分情况是PyTorch的CUDA版本和Windows侧驱动不匹配,先升级Windows驱动,再换用新版本的PyTorch CUDA轮子。少数情况是根本没启用GPU加速,回到nvidia-smi检查。

5. 跑一个真实模型:nvidia-smi、推理验证与资源限制

5.1 nvidia-smi 输出信息怎么读

进入WSL2后运行nvidia-smi,能看到类似下面的输出:

+-----------------------------------------------------------------------------+ | NVIDIA-SMI 545.84 Driver Version: 545.84 CUDA Version: 12.3 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | RTX 4090 On | 00000000:00:0B.0 On | N/A | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | +-------------------------------+----------------------+----------------------+

几个关键点:Driver Version是Windows侧驱动的版本号,不是Linux驱动;CUDA Version是驱动支持的CUDA最高版本,不代表WSL2里已装的Toolkit;Memory-Usage显示的是物理GPU的总显存占用,Windows侧和WSL2侧所有进程共享这部分显存。

如果你发现自己什么训练都没跑,显存却被占了一部分,很可能Windows里某个程序正在用GPU,比如浏览器硬件加速、视频渲染工具或游戏。这在AI开发时需要注意,显存不够时先关掉Windows侧的大户。

5.2 用 Transformers 跑一次真实推理

CUDA通了之后,我建议直接跑一个真实模型,验证链路完全OK。安装:

pip install transformers

然后运行一段小脚本,用一个小型生成式模型做文本续写:

from transformers import AutoModelForCausalLM, AutoTokenizer model_name = "gpt2" tok = AutoTokenizer.from_pretrained(model_name) model = AutoModelForCausalLM.from_pretrained(model_name).to("cuda") inputs = tok("WSL2 runs a real Linux kernel,", return_tensors="pt").to("cuda") out = model.generate(**inputs, max_new_tokens=20) print(tok.batch_decode(out)[0])

第一次跑会下载模型参数,一般需要几百MB到几GB,耗时取决于网络。如果遇到下载慢的问题,HuggingFace也提供了镜像端点,可以配置HF_ENDPOINT环境变量指过去,后面下载模型就快很多。跑起来以后,另开一个终端执行watch -n 1 nvidia-smi,能看到模型推理进程挂在GPU上,显存占用和利用率都在跳动,这时候你心里大概就踏实了:WSL2里的AI开发环境已经可以正常干活。

5.3 给 WSL2 分配合理的 CPU 和内存

WSL2默认会吃掉大量物理内存,一般是宿主机内存的50%以上,甚至更高,Windows会很卡。我习惯在Windows用户目录下建一个.wslconfig文件来控制资源配额:

[wsl2] memory=16GB processors=8 swap=4GB localhostForwarding=true

改完同样需要wsl --shutdown再启动。注意memory别设成超过物理内存的70%,否则Windows桌面和浏览器会先挂。如果机器是32GB内存,给WSL2分16GB比较合理;如果只有16GB内存,我建议分8GB,留一些给Windows本身。

显存方面没有类似的配置项,因为显存是物理共享的,WSL2不能独占。跑大规模训练时,显存不够就只能换更小的batch size、用混合精度训练,或者做模型并行/CPU offload,这些在WSL2里和裸机Linux上没有区别。

5.4 和开发工具的衔接

环境跑通以后,我一般用VS Code连进WSL2开发。VS Code装一个WSL扩展,然后code .就能直接在WSL2环境里编辑、调试、跑终端。PyCharm也支持WSL解释器,可以在设置里选择WSL里的conda环境。这些工具本质上都是通过WSL的转发机制连进去的,无需在WSL2里额外装SSH服务。

有一点要提醒:WSL2里跑项目,工作区尽量放在Linux文件系统内部,比如~/projects,不要放在/mnt/c或/mnt/d。跨OS文件IO走的是9P协议,性能比本地文件系统差不少,尤其是大量小文件读写,能慢一个数量级。我一开始图省事把项目放D盘,后来发现预训练数据读取、模型权重保存都明显慢,迁到Linux侧之后立刻好了。

6. 高频踩坑清单:五个值得提前避开的雷

6.1 WSL2 无法启动,报虚拟化未启用

2.1节说过基础检查,这里再总结完整排查链路。先看任务管理器“虚拟化”是否已启用,没有就去BIOS开VT-x/SVM;再看Windows功能里是否勾选了“虚拟机平台”,没有就启用;最后看Windows版本是不是太老,老版本跑一遍wsl --update。我遇到过最隐蔽的情况是杀毒软件或第三方安全软件抢占Hyper-V平台,导致WSL2起不来,这种时候需要暂时禁用相关模块,或者查看系统事件日志里Hyper-V服务是否报错。

6.2 wsl --install 卡在下载

前面提过离线安装法,这里补充一个容易弄错的地方:如果你用的是Win10老版本,wsl --install可能连WSL内核包都不会自动更新,所以直接卡在下载或报“已安装所有组件”但启动失败。先跑wsl --update,不行就手动下载MSI离线包。至于发行版镜像,离线Appx安装同样可行,总比一直卡死强。

6.3 PyTorch 报 CUDA 初始化失败

典型报错有RuntimeError: CUDA error: no kernel image is available for execution on the device和failed to initialize CUDA。遇到这种先分三步走:

  1. Windows PowerShell里跑nvidia-smi,确认Windows驱动正常且版本够新。
  2. WSL2里跑同样的命令,确认能在WSL2里看到GPU。
  3. 看PyTorch的CUDA版本。no kernel image通常是PyTorch的CUDA版本过老,不包含你显卡架构对应代码,例如GPU太新而PyTorch还是cu111,解决方法是装对应高版本CUDA的PyTorch轮子,比如cu121或更高,同时Windows驱动保持最新。

还有一个小坑:不要在WSL2里运行NVIDIA Linux驱动安装包。这也是社群高频错误。一旦运行了,内核模块加载可能失败,甚至WSL2直接黑屏或者无法启动,最后只能靠wsl --unregister重装环境。记住原则:WSL2里只装CUDA Toolkit,不装驱动。

6.4 /mnt/c 路径下 IO 很慢

性能问题不是报错,但会消耗大量时间。在WSL2里读写Windows挂载盘非常慢,如果你把数据集放在D盘然后代码里直接路径引用,训练时每个epoch都要读很久。我的习惯是把数据集和代码统一放在~/data、~/code这类Linux路径下,Windows侧文件通过复制或软链导入。文件传输只需一次,之后每次训练都用本机文件系统,性能提升非常明显。

6.5 环境里的默认用户变成 root

wsl --import之后默认登录root,sudo权限当然无所谓,但root身份用久了会有权限混乱、包被装乱的风险。改回非root用户的方案在3.2节表格里写过:编辑/etc/wsl.conf加上[user] default=你的用户名,然后wsl --shutdown再启动。还有更直接的办法:Windows下用发行版自带的exe命令设置默认用户,比如ubuntu2404.exe config --default-user xxx,这个我推荐给记不住wsl.conf路径的朋友。

最后说个我的个人习惯:WSL2环境我一般不装图形界面,所有操作都在终端和VS Code里完成,因为AI开发本来就不需要桌面。如果你需要可视化调试,再单独在Windows侧开工具就行,WSL2专注于计算。另外,每过一两个月我会做一次wsl --export备份,D盘空间够就放着,空间紧张就删掉,但养成这个习惯后,我重装环境的成本几乎为零。踩过这么多坑之后,说实话WSL2不算完美,但在Windows桌面上获得接近Linux服务器的开发体验,它确实是目前最靠谱的一条路。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进