Windows下编译DeepSpeed全流程:环境配置到GPU训练实战

Windows下编译DeepSpeed全流程:环境配置到GPU训练实战 说实话在Windows上编译DeepSpeed这件事我最早是拒绝的。一个项目文档里从第一天就写明“DeepSpeed officially supports Linux”的库强行塞到Windows上跑光是想想就知道编译链有多难受。但后来实在绕不过去——手头的工作站装的是Windows系统要微调大模型又不想为了跑个实验专门去装双系统或者再买一台Linux机器。于是在某天下午我对着VS的编译日志硬啃了几小时终于把DeepSpeed在Windows上编译通过并且让GPU实打实地跑起来了。这篇文章就是想把这条完整路线记录下来。不是什么“官方推荐”做法而是我自己反复踩坑验证过的可行方案。内容覆盖Windows下从零准备PyTorch GPU环境到编译DeepSpeed算子再到用GPU实际跑通一个训练例子的全过程。适合那些跟我一样必须在Windows上做深度学习训练、大模型微调又不想被Linux劝退的人。1. 为什么在Windows上编译DeepSpeed这么麻烦1.1 DeepSpeed对Windows的“官方冷漠”DeepSpeed是微软开源的深度学习优化库主打大模型训练时的显存优化和加速。ZeRO系列、offload到CPU/NVMe、FusedAdam这类能力在做大模型微调时基本是刚需。但讽刺的是微软自家的这个库对自家Windows系统从来不上心官方文档和CI测试基本只覆盖Linux。问题出在DeepSpeed的核心结构上。它不是一个纯Python库而是大量使用C和CUDA算子编译时依赖GCC或者Clang工具链还依赖很多Linux生态的库比如libaio异步I/O库。到了Windows上这些依赖全都不成立。MSVC编译器不是不能用但很多DeepSpeed的C代码从没在MSVC上测过一编译就爆错。我最初直接跑pip install deepspeed装是装上了但一跑就报错说找不到cpu_adam之类的一堆算子实现。后来才明白Windows下pip安装的DeepSpeed默认跳过了所有算子编译装出来的只是一个“空壳”真正干活时根本用不了。1.2 一条切实可行的路线经过多次尝试我最后确定了一条可行路径在Windows上用MSVC编译DeepSpeed源码并且按需开启必要的算子编译。核心思路有几个关键点不要试图全量编译。DeepSpeed的算子很多但在Windows上跑真正常用的也就那么几个CPUAdamCPU端优化器算子、FusedAdam融合Adam、以及ZeRO所需的通信原语。只开需要的编译模块省略掉libaio这类Windows上根本不存在的依赖。使用源码安装而不是pip直接装。从GitHub拉下源码设置好编译开关用python setup.py build_ext手动编译算子这样才能确保需要的东西真正被编出来。配合正确的PyTorch GPU版。DeepSpeed依赖PyTorch的C扩展机制如果PyTorch本身没装对后续编译必然连环踩坑。这条路走通之后我没再遇到什么解决不了的大问题。编译一次以后直接复用对Windows用户来说算是能接受的方案了。2. 环境准备先把地基打牢2.1 工具链清单一览编译DeepSpeed之前得先把整个工具链对齐。我在实际准备环境中发现大多数人编译失败不是因为DeepSpeed本身难搞而是前置环境版本不匹配。我把核心依赖列成了一个清单组件推荐版本说明WindowsWindows 10/11 64位无特殊要求Python3.10或3.11不要用3.12部分算子适配不完善CUDA Toolkit12.1或11.8选PyTorch官方已验证的版本cuDNN与CUDA版本匹配训练性能必需VS Build ToolsVisual Studio 2022勾选“使用C的桌面开发”Git任意较新版本拉取DeepSpeed源码PyTorch2.6.0GPU版/CUDA 12.1使用--index-url指定CUDA版本来源这里单独说一句Python版本的问题。我之前试着用Python 3.12装DeepSpeed结果碰到一堆算子编译时error: no matching constructor for initialization之类的报错查了半天是编译器对C标准支持和Python 3.12扩展API不兼容导致的。换回3.10之后一次通过。所以稳妥起见3.10是最省心的选择。2.2 安装CUDA与VS Build Tools的关键细节CUDA Toolkit的安装看着简单其实埋了不少雷。装完之后很多人直接跑nvcc -V发现找不到命令原因就是环境变量没生效。安装包默认会把CUDA装到C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1但bin目录并没有自动加入Path。装完之后一定要手动检查一下C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.1\bin手动把这条路径加进系统环境变量的Path中。注意是加bin这一层不是加CUDA根目录。我见过有人直接把根目录加进去最后nvcc还是识别不了白白浪费半天排查时间。VS Build Tools的安装是另一个重点。打开Visual Studio Installer勾选“使用C的桌面开发”工作负载里面会包含MSVC编译器、Windows SDK和CMake工具。这一步如果漏了后面编译DeepSpeed时会直接报Microsoft Visual C 14.0 or greater is required根本走不下去。另外我在实操中还发现一个技巧编译时最好用“x64 Native Tools Command Prompt for VS 2022”这个终端而不是普通的cmd或PowerShell。这个终端会自动配置好MSVC编译器路径和Windows SDK环境变量省掉很多手工设置环境的功夫。2.3 创建一个干净的conda环境环境这块我强烈建议用conda或者venv隔离不要直接装在系统Python里。我在一个满是旧依赖的系统Python上编译DeepSpeed时被各种版本的numpy、setuptools冲突折腾得够呛。创建环境的命令很简单conda create -n deepspeed python3.10 -y conda activate deepspeed如果网络速度不理想建议先给conda配置清华源conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --set show_channel_urls yes激活环境之后再继续后续操作。这里有个很常见的坑如果忘了conda activate deepspeed后面所有pip包都装进了系统环境实际运行Python时却用的是conda环境最终必然出现ModuleNotFoundError: No module named torch。3. 安装PyTorch GPU版3.1 区分CPU版和GPU版在Windows上装PyTorch最大的坑是默认版本问题。如果直接跑pip install torch大概率会从PyPI拉到一个不带CUDA的CPU版本。CPU版本虽然能跑但torch.cuda.is_available()永远返回FalseDeepSpeed编译时也找不到CUDA工具链整个方案直接废掉。GPU版的PyTorch必须从PyTorch官方索引安装。核心命令是这个pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121这里的cu121代表CUDA 12.1。我用的PyTorch版本是2.6.0对应CUDA 12.1的wheel包和DeepSpeed配合很稳定。3.2 国内网络环境下的安装策略如果你在内网或者网络不稳定官方源可能拉不动大文件。我曾见过有人配了清华源然后发现pip install torch装的还是CPU版——这是因为通用镜像源只提供CPU版wheel包GPU版必须走PyTorch官方源。折中做法是先用浏览器或者下载工具从https://download.pytorch.org/whl/cu121/torch-2.6.0cu121-cp310-cp310-win_amd64.whl拉到本地再通过本地文件安装pip install C:\downloads\torch-2.6.0cu121-cp310-cp310-win_amd64.whl pip install C:\downloads\torchvision-0.21.0cu121-cp310-cp310-win_amd64.whl pip install torchaudio2.6.0 --index-url https://download.pytorch.org/whl/cu121本地wheel安装的好处是稳定、可断点续传、还能确保版本完全匹配。我实际下载的时候发现这些wheel文件动辄2GB多用下载工具比pip直连稳定得多。3.3 验证PyTorch确实吃到了GPU装完之后别急着往后走先跑一段验证代码python -c import torch; print(torch.__version__); print(torch.cuda.is_available()); print(torch.version.cuda)正常输出应该类似2.6.0cu121 True 12.1如果torch.cuda.is_available()返回False那就别继续往下走了先把GPU环境修好。最常见的两个原因一是驱动太旧不支持CUDA 12.1二是torch还是CPU版。这时需要确认pip show torch看版本号里有没有cu121字样。没有的话卸载掉重装GPU版pip uninstall torch torchvision torchaudio -y然后再按之前的命令装GPU版。4. 编译DeepSpeed核心战场4.1 先把源代码和依赖拉齐环境准备好后进入最关键的编译环节。首先从GitHub拉取DeepSpeed源码git clone https://github.com/microsoft/DeepSpeed.git cd DeepSpeed然后确保Python依赖安装完整一般用pip install -r requirements/requirements.txt就能搞定。我在Windows上执行时发现这个文件里的依赖版本偏低但不影响使用。真正重要的是下面两个编译包pip install ninja pip install setuptools64.0Ninja是并行构建工具能大幅缩短编译时间setuptools新版支持PEP 660对源码安装有很多细节优化。4.2 设置编译开关和环境变量这是最核心的一步。DeepSpeed编译受环境变量控制在Windows上必须手动指定。我在cmd里执行的是set DS_BUILD_OPS1 set DS_BUILD_AIO0 set DS_BUILD_UTILS1 set DS_BUILD_FUSED_ADAM1 set DS_BUILD_CPU_ADAM1 set DS_BUILD_ONEADAM1几个变量的含义我解释一下DS_BUILD_OPS1总开关让DeepSpeed真正编译C算子。不设这个的话装完就是个空壳。DS_BUILD_AIO0禁用libaio异步I/O模块这个模块在Windows上根本没有对应库不关掉编译必挂。DS_BUILD_UTILS1编译工具类算子很多功能依赖这层。DS_BUILD_FUSED_ADAM1和DS_BUILD_CPU_ADAM1显式开启融合优化器算子。这是大模型训练时真正省显存、提速度的关键部件。如果你是在PowerShell里操作语法略有不同$env:DS_BUILD_OPS1 $env:DS_BUILD_AIO0 $env:DS_BUILD_UTILS1 $env:DS_BUILD_FUSED_ADAM1 $env:DS_BUILD_CPU_ADAM1 $env:DS_BUILD_ONEADAM14.3 正式编译与安装环境变量设置好之后在“x64 Native Tools Command Prompt for VS 2022”里执行python setup.py build_ext --inplace注意这里用build_ext --inplace而不是直接pip install -e .。前者的好处是会先编译算子并且在当前目录生成编译产物方便第一时间发现哪个算子编译失败。我第一次执行时就卡在fused_adam算子上报了一堆MSVC语法错误。排查之后发现是缺少Windows头文件支持后来通过更新到最新源码分支解决。build_ext成功之后再正式安装pip install -e .-e表示可编辑安装源码改动后不用重新安装就能生效调试时特别方便。编译过程会花掉一段时间具体取决于CPU核数和内存。我机器的配置是16核编译耗时大约10分钟。编译期间要看到大量ninja: build completed这类信息才算正常。4.4 编译完成后的验证编译完成后用ds_report验证一下DeepSpeed的算子是否真正可用ds_report正常情况下应该在输出里看到cpu_adam、fused_adam等算子的状态显示为[OKAY]。如果显示[WARNING]或[FAILED]说明对应算子编译有问题需要回头检查。另外直接跑一段Python验证也能看出问题python -c import deepspeed; print(deepspeed.__version__) python -c from deepspeed.ops.adam import DeepSpeedCPUAdam; print(CPUAdam OK)如果第二行没有报错说明CPUAdam算子编译成功整个DeepSpeed的编译链路基本就通了。5. 实测跑通一个GPU训练例子5.1 准备测试脚本编译通过只是第一关真正让DeepSpeed和PyTorch在GPU上协同工作还需要实测。我准备了一个最小化的ZeRO-2训练脚本来验证整个链路是否真的可用。import torch import deepspeed from torch import nn class TinyModel(nn.Module): def __init__(self, dim512): super().__init__() self.net nn.Sequential( nn.Linear(dim, dim * 2), nn.ReLU(), nn.Linear(dim * 2, dim) ) def forward(self, x): return self.net(x) ds_config { train_batch_size: 16, gradient_accumulation_steps: 1, optimizer: { type: Adam, params: {lr: 1e-4} }, zero_optimization: { stage: 2 }, fp16: { enabled: True } } model TinyModel().cuda() model_engine, optimizer, _, _ deepspeed.initialize( modelmodel, model_parametersmodel.parameters(), configds_config ) inputs torch.randn(8, 512).cuda() labels torch.randn(8, 512).cuda() for step in range(100): outputs model_engine(inputs) loss nn.MSELoss()(outputs, labels) model_engine.backward(loss) model_engine.step() if step % 20 0: print(fstep {step} loss {loss.item():.4f})这里有几个细节说明一下model_engine deepspeed.initialize(...)返回的对象封装了原生PyTorch模型完全替代了原来的model。前向、反向、更新全都走model_engine的接口。ZeRO-2会把优化器状态和梯度分片到多卡但单卡上开启stage 2也能正常跑可以用来验证通信原语是否可用。开启fp16要求模型支持自动混合精度测试模型默认支持直接跑没问题。5.2 观察显存与速度跑这个脚本的时候我习惯在另一个终端开着nvidia-smi -l 1监控显存和GPU利用率。我实测时显存大约占用了2.3GB左右对于一个512维小模型来说很正常。关键是这个过程能证明两点第一DeepSpeed的初始化没有报错说明算子和通信库真的编译成功了第二GPU利用率能看到明显的周期性波动说明训练在真正调用CUDA核心。如果你跑起来之后完全看不到显存占用变化多半是fp16没生效或者模型压根没在GPU上。这时检查一下torch.cuda.is_available()再确认模型在model_engine.backward之前的输入都在cuda()上。5.3 踩过的性能坑测试过程中最容易让人误解的一个现象是第一次前向时耗时特别长甚至比CPU还慢。这是正常的因为DeepSpeed在第一次前向时会做大量的初始化工作比如分配GPU内存、建立通信组、预热融合算子。多跑几个step之后速度会趋于稳定。还有一个坑是train_batch_size必须能被gradient_accumulation_steps × 实际batch size整除。我一开始配了train_batch_size16但每个step实际喂了inputs的batch size是8导致DeepSpeed在内部计算梯度累积步数时报错。后来把train_batch_size改成8或者让inputs的batch size翻倍才正常。6. 常见问题速查表整个过程中我整理了最有代表性的几类报错和排查思路在这里一并列出方便你快速对照报错/现象根本原因处理方式ModuleNotFoundError: No module named torchPython环境没激活或torch装到了其他环境conda activate deepspeed后重装torcherror: could not find a version that satisfies the requirement torch从PyPI默认源拉包找不到合适版本使用--index-url https://download.pytorch.org/whl/cu121torch.cuda.is_available()为Falsetorch是CPU版或NVIDIA驱动过旧卸载后重装GPU版更新驱动Microsoft Visual C 14.0 or greater is required缺少VS C Build Tools安装VS 2022 Build Tools并勾选“使用C的桌面开发”nvcc: No such file or directoryCUDA环境变量未配置将CUDAPATH\bin加入系统Path编译时DS_BUILD_AIO相关报错Windows无libaio支持设置DS_BUILD_AIO0ds_report显示cpu_adam不可用编译时算子没编成功检查编译日志确认MSVC工具链环境重跑build_extfailed to initialize nvml: GPU access blocked by the operating system使用了WSL但GPU透传未配置或驱动不支持检查Windows侧驱动确保WSL版本和NVIDIA驱动匹配attn_implementationtorch is not supported某些模型推理框架和torch版本不兼容升级或降级torch按框架文档设置正确的attention实现这里重点提醒一下WSL的情况。如果你是在Windows Subsystem for Linux里编译DeepSpeed遇到NVML初始化失败的概率比原生Windows高得多因为WSL2的GPU透传依赖Windows宿主机驱动版本和WSL的协同支持。我最后选择直接在原生Windows上编译省掉了很多麻烦。7. 最后的几点实操建议编译DeepSpeed这件事说难也难说简单也简单关键是把工具链版本对齐。我在这个项目里最大的体会是网上关于Windows编译DeepSpeed的教程少且零散很多人试了几天就放弃了。但只要你忍下性子把CUDA、VS、PyTorch和DeepSpeed的版本关系理清楚整个过程其实是可以复现的。还有一个建议如果你只是短期做实验不想维护本地编译环境也可以考虑租一台Linux GPU服务器跑任务Windows本地只做代码编辑和调试。但如果你跟我一样必须长期在Windows环境下做训练和微调那花一个下午把DeepSpeed编译通是非常值得的投资。之后每次创建新环境只需要复用这套流程就能快速装好。最后分享一个小技巧你把编译好的DeepSpeed相关wheel包留存一份下次换机器或者重装系统时直接pip install本地wheel可以跳过漫长编译。我第二次配置时整个环境搭建从原来的四小时压缩到了二十分钟以内效率提升非常明显。