Windows 编译 3DGS CUDA 扩展全流程指南 1. 为什么 Windows 上编译 diff-gaussian-rasterization 这么折腾1.1 这个库到底是干什么的diff-gaussian-rasterization 是 3D Gaussian Splatting3DGS里最核心的可微光栅化模块。3DGS 用一堆带透明度的高斯椭球来表达场景训练过程中需要把几十万到几百万个高斯投影到 2D 图像上做渲染同时还得把梯度反向传播回去。这部分计算量巨大纯 Python 或者用 PyTorch 原生的张量算子来写效率低得没法看所以原作者用原生 CUDA 内核写了前向和反向传播再通过 PyTorch 的 C Extension 机制编译成自定义算子。问题就出在这个编译上。这个模块并不提供预编译好的 wheel 包所有跑 3DGS 训练的人包括用 gsplat、Gaussian-Splatting 官方仓库、或者各种二创项目都得在自己的机器上从源码把 CUDA 内核编译一遍。Linux 上这事儿相对顺滑Windows 上各种环境变量、编译器版本、CUDA 版本之间的暗坑就全冒出来了。1.2 难编译的根源在于三件套版本匹配Windows 下编译这个库实质上要同时满足三件事C 编译器MSVC、CUDA Toolkit提供 nvcc 编译器、PyTorch 自带的 CUDA 运行库。这三者的版本关系很微妙谁不配合都会让编译炸掉。我这次的组合是 PyTorch 2.7.1cu126、CUDA Toolkit 13.1、RTX 显卡我手头是 RTX 4080 Super另外一个测试机器是 RTX 5090 D。表面上看 nvcc 版本比 PyTorch 自带的 CUDA 12.6 高一截很多人一听就觉得版本对不上肯定编译不了。实际上编译工具链和运行库是两套东西只要 nvcc 能生成目标 GPU 架构对应的 cubin 文件运行时会去找 PyTorch 里 bundle 的 CUDA 12.6 动态库这中间当然有大坑但并不是完全不能跑。后面我会详细拆解到底哪里会出问题、怎么绕过去。1.3 谁需要看这篇记录如果你正在做 3D 重建、神经渲染、SLAM 相关的研究或工程跑任何基于 3DGS 的代码库时卡在这一步那这篇记录就是给你写的。内容包括工具链怎么装、环境变量怎么配、编译命令怎么写、报错怎么排查、编译完怎么验证。我尽量把每一步背后的原因也讲清楚避免你改了这里那里又跟着炸。注意如果你用的是 Colab 或者只跑预训练模型、不碰训练流程那基本用不到这个模块的源码编译。只有需要自己训练 3DGS 或者修改光栅化代码的人才必须走完这套流程。2. 编译前的环境准备与工具链搭配2.1 需要的软件清单先列一下我这台 Windows 11 机器上最终确认可用的完整环境你可以对照着准备组件版本说明操作系统Windows 11 26H2其实 Win10 也适用但部分新版驱动对 Win11 支持更积极Python3.10 ~ 3.12PyTorch 2.7 支持 3.9-3.13但 3.10/3.11 最稳PyTorch2.7.1cu126必须通过官网命令安装 GPU 版CUDA Toolkit13.1提供 nvcc装的时候只勾编译器组件即可Visual Studio202217.x必须装C 桌面开发工作负载显卡驱动最新 Game Ready / Studio 驱动确保支持你显卡的 CUDA 算力两个机器分别是 RTX 4080 Super计算能力 8.9和 RTX 5090 D计算能力 12.0都编译成功了。4080 那台过程更顺5090 D 那台多花了点时间处理架构参数这个后面单独讲。2.2 Visual Studio 2022 的安装细节很多人在这步栽跟头因为默认安装 VS 时根本不会带 C 编译工具链。记住安装 VS 2022 时工作负载一定要勾选使用 C 的桌面开发。这会把 MSVC 编译器cl.exe、Windows SDK、CMake 等工具都装上。装完之后有一个很容易被忽略的点cl.exe 所在路径。在默认安装下它的路径大概是C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.4x.x\bin\Hostx64\x64\cl.exe这个目录下的 cl.exe 才是 64 位编译器。千万别用 x86 那个目录里的 cl.exe否则编译 CUDA 扩展时会报一堆不兼容错误。另外我建议你在安装 VS 时把适用于 Windows 的 C CMake 工具这个可选组件也勾上后面排查 ninja 相关问题会少很多麻烦。还有个经验Windows 更新偶尔会破坏 MSVC 的环境变量设置如果你之前能用、突然某天编译报 cl.exe 找不到先去检查 VS 是否完整再检查环境变量。我遇到过两次最后都是 VS 的修复功能解决的。2.3 CUDA Toolkit 13.1 和 PyTorch cu126 的搭配逻辑这里需要把概念理清楚。PyTorch 的 cu126 指它内部链接了 CUDA 12.6 的运行时库cudart、cublas 这些编译扩展时 nvcc 用的是系统安装的 CUDA Toolkit。也就是说运行时版本取决于 PyTorch编译期版本取决于 nvcc。理论上 nvcc 版本比运行库高一般不会出大问题因为 CUDA 在 11 之后做了比较好的向后兼容老运行库能跑新编译器产出的 cubin前提是目标架构在新 CUDA 里仍然支持。但如果你反过来用 12.6 的 nvcc 配合要求 13.x 的库就容易崩。实际操作中有一个很明显的矛盾点如果显卡是 RTX 50 系列Blackwell 架构sm_120CUDA 12.6 的 nvcc 并不原生支持 sm_120你编译时会遇到Unsupported gpu architecture的报错。这时候要么升级 CUDA Toolkit 到 12.8 以上官方支持 Blackwell 的版本要么就是像我这样直接用 13.1。PyTorch 的运行时虽然是 12.6但 nvcc 13.1 编出来的 cubin 只要架构匹配运行时的兼容性是可以接受的。这套组合我在 RTX 5090 D 上实测通过训练 3DGS 时没有出现驱动崩溃或 CUDA 错误。注意如果你用的是 RTX 40 系列及更早显卡强烈建议直接装和 PyTorch 同版本的 CUDA Toolkit比如 cu126 就装 12.6这样兼容性风险最小。13.1 更多是为了 Blackwell 显卡的不得已选择或者是还想干其他 CUDA 开发活儿的场景。3. 完整编译流程实操3.1 环境变量配置编译 diff-gaussian-rasterization 之前必须让整个命令行环境知道三件事CUDA 装在哪、编译器是谁、要生成什么架构的代码。先说 CUDA_HOME。安装完 CUDA Toolkit 后通常环境变量会自动带上 CUDA_PATH但很多编译脚本只认 CUDA_HOME所以需要手动补setx CUDA_HOME C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.1 setx CUDA_PATH C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.1设置完之后一定要把 nvcc 的路径加进 PATHsetx PATH %PATH%;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.1\bin然后重新开一个 PowerShell 窗口注意是重新开不是直接在当前窗口继续用setx 设置的变量在新窗口才生效验证nvcc --version这时候你应该能看到 nvcc 的版本信息。如果提示找不到命令说明 PATH 没生效或者安装路径不对。记得 nvcc 不是所有 CUDA 安装方式都会出现的如果当时只装了 NVIDIA App 或驱动那没有 nvcc 也正常必须装完整的 CUDA Toolkit。3.2 下载项目并准备依赖diff-gaussian-rasterization 不是单独存在的它通常是你下载的某个 3DGS 项目里的一个子模块。以最经典的官方仓库为例git clone https://github.com/graphdeco-inria/gaussian-splatting --recursive--recursive参数很关键它会连带拉取submodules/diff-gaussian-rasterization这个子模块。如果忘了加submodules目录下会是空的后面编译会直接报找不到源码。克隆完成之后先建一个干净的 Python 虚拟环境。我用的是 condaconda create -n gaussian python3.11 conda activate gaussian然后装 PyTorch。这里千万别用 pip 默认源里的 CPU 版本 PyTorch必须用官方 CUDA 版本的安装命令pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126装完后验证一下 PyTorch 是否真的能看到 CUDApython -c import torch; print(torch.__version__, torch.cuda.is_available())如果输出2.7.1cu126 True说明环境正常。如果显示 True 但版本号不带 cu126说明装成了 CPU 版得重新装。3.3 安装第三方依赖diff-gaussian-rasterization 本身只有 CUDA 代码和很小的 Python 封装但编译期依赖一个名为plyfile的库用于点云 PLY 文件读写3DGS 的数据加载依赖它。这一步不做编译时会报ModuleNotFoundError: No module named plyfile。安装方法pip install plyfile tqdmtqdm 是官方训练代码里显示进度条用的一起装上省心。如果你的具体项目里还用到 opencv、numpy、shapely 这些就按对应仓库的 requirements 装。另外建议把ninja也装上这是加速编译的关键工具pip install ninjaninja 比 MSVC 原生的 nmake 快不少diff-gaussian-rasterization 的 setup.py 会自动检测 ninja 是否存在并优先使用。我在两个平台上做过对比用 ninja 编译大概能省三分之一的时间。3.4 核心编译命令与架构参数设置终于到编译这一步。进入子模块目录然后安装cd submodules/diff-gaussian-rasterization pip install .如果到这里一切顺利你会看到 nvcc 开始编译一堆 .cu 文件屏幕刷出大量日志。整个编译过程在普通配置的机器上大约需要 15 到 40 分钟取决于 CPU 核数和磁盘速度。但如果你直接这么跑大概率会遇到架构不匹配的报错。这里的参数调整对 RTX 显卡尤其重要。diff-gaussian-rasterization 的 setup.py 通过torch.cuda.get_device_capability()来识别 GPU 计算能力理论上能自动适配。问题在于当 PyTorch 运行库CUDA 12.6不认识新显卡架构时它返回的能力值可能是空或者错误值导致 nvcc 收到一个不存在的架构参数而崩溃。解决办法是手动指定目标架构。查一下你的 RTX 显卡对应的计算能力显卡系列计算能力TORCH_CUDA_ARCH_LIST 值RTX 40 系列8.98.9RTX 50 系列12.012.0RTX 30 系列8.68.6在编译前设置环境变量$env:TORCH_CUDA_ARCH_LIST8.9如果是 RTX 5090 D 那种 Blackwell 架构$env:TORCH_CUDA_ARCH_LIST12.0然后重新执行pip install .。这个环境变量只需要在编译时设置不影响后续运行。编译成功的明显标志是最后出现类似Successfully built diff_gaussian_rasterization的字样并且没有红色错误日志。如果看到error C1083、fatal error、Unsupported gpu architecture那编译失败直接跳到第 4 节排查。3.5 编译完成后的验证编译成功后先别急着跑训练脚本。我习惯先用一个最小测试验证算子是否真的能调用 CUDApython -c import diff_gaussian_rasterization; print(import ok)如果这条命令报错最常见的原因有两个。一是 DLL 加载失败PyTorch 加载扩展时会去找 CUDA 运行库如果系统里同时装了多个版本的 CUDA可能加载到不匹配的版本。二是编译时环境变量没配好导致生成的文件不完整。更严格的验证方式是调用官方测试脚本里render函数跑一次前向和反向import torch from diff_gaussian_rasterization import GaussianRasterizationSettings, GaussianRasterizer # 构造一个最小输入 means3D torch.randn(100, 3, devicecuda, dtypetorch.float32) # ... 按官方调用方式填充参数这个测试能为后续训练提前踩出运行时问题。实测经验是只要 import 成功且能跑一次前向后面训练基本不会在算子层面出幺蛾子。4. 高频报错与排查实录4.1 nvcc 找不到或环境变量失效症状执行pip install .时日志里出现nvcc: File not found或CUDA_HOME environment variable is not set。原因setup.py 在编译时需要找到 nvcc它依赖环境变量 CUDA_HOME 或 CUDA_PATH。很多人装了 CUDA Toolkit但环境变量没设置或者设置了之后没有重新打开终端。解决按 3.1 节重新设置环境变量setx 之后务必开新终端。另外检查一下C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\目录下到底有几个版本文件夹。如果同时有 v12.6 和 v13.1注意 CUDA_HOME 到底指向了哪个最好只保留一份或者把 CUDA_HOME 指准确。还有一个诡异的坑某些 GPU 驱动更新会覆盖 CUDA 相关环境变量。我遇到过装好驱动后 nvcc 直接失效的情况重设环境变量解决。4.2 Unsupported gpu architecture 报错症状nvcc 报nvcc fatal : Unsupported gpu architecture compute_89或compute_120。这个报错要分两种场景。一是显卡较新RTX 50 系列CUDA 12.6 的 nvcc 不认识 sm_120二是 setup.py 自动检测架构失败PyTorch 返回了 PyTorch 自身支持列表里的某个值但 nvcc 不支持。解决思路很简单设置 TORCH_CUDA_ARCH_LIST 覆盖自动检测。4090 和 4080 Super 都用 8.95090 D 用 12.0。设置后重新编译这个报错就消失了。关键时刻的踩坑经验如果你同时设置 TORCH_CUDA_ARCH_LIST 为多个值比如8.9;12.0编译时间会翻倍。只在同一台机器上跑的话老老实实只填你当前显卡对应的值即可。4.3 cl.exe 无法识别或 fatal error C1083症状编译早期出现cl.exe不是有效命令或者fatal error C1083: Cannot open include file: cuda_runtime.h。cl.exe找不到说明 MSVC 的编译环境没初始化。最省事的办法是打开x64 Native Tools Command Prompt for VS 2022在这个终端里手动激活 conda 环境然后再执行编译。这个终端会自动设置好 MSVC 的所有环境变量。你可以在开始菜单搜x64 Native找到后右键以管理员身份运行然后conda activate gaussian cd submodules/diff-gaussian-rasterization pip install .cuda_runtime.h找不到则是 nvcc 找不到 CUDA include 目录检查 CUDA_HOME 是否设置正确。注意标准路径里 include 目录是$(CUDA_HOME)\include如果 CUDA_HOME 多写了一层也会报这个错。4.4 ninja 编译中断且残留缓存症状编译到一半报错中断修复后重新执行编译但日志显示某些 .obj 文件仍然报同样的错甚至出现ninja: error: rebuilding ...死循环。原因ninja 会生成.ninja_deps和 build 目录里面记录了编译状态。如果源码没变它认为不需要重新编译直接沿用之前的失败结果。解决在 diff-gaussian-rasterization 目录下把build文件夹整个删除再重新编译rm -rf build pip install .这个操作我至少做过十几次属于治标又治本的土办法。相比之下pip install . --force-reinstall不一定能解决缓存污染问题删 build 才是可靠的。4.5 运行时 DLL 加载失败症状编译成功但import diff_gaussian_rasterization报OSError: [WinError 126] 找不到指定的模块或DLL load failed。这个是最隐蔽的坑之一。diff_gaussian_rasterization 编译出的 pyd 文件会依赖 PyTorch 的 DLL如果 PyTorch 运行时加载不到对应版本的 CUDA 动态库就会报这个错。排查步骤先用python -c import torch; print(torch.version.cuda)确认 PyTorch 的 CUDA 版本然后用where cudart64_*.dll看看系统里有哪些 CUDA 运行库。如果你之前装过旧版 CUDA系统的 PATH 里残留了旧版本的 cudart而新编译的 pyd 依赖新版本符号就可能导致加载失败。解决保证系统 PATH 里 CUDA bin 目录只有一个版本或者干脆在 Python 代码开头手动插入正确 CUDA 路径import os os.add_dll_directory(rC:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.1\bin)这个os.add_dll_directory方法从 Python 3.8 开始才可用如果你的环境是 Python 3.7 及以下得用别的方式但建议直接用 3.10 以上的环境没必要在旧 Python 上折腾。4.6 常用排查速查表报错关键词根因首选解决方案nvcc not found环境变量未设置设 CUDA_HOME 并重开终端Unsupported gpu architecture架构列表空或版本过老设置 TORCH_CUDA_ARCH_LIST 为显卡对应算力cl.exe 找不到MSVC 环境未初始化用 x64 Native Tools 终端编译CUDA_HOME not setsetup.py 找不到 nvcc设置 CUDA_HOME 指向 Toolkit 根目录C1083 include 错误include 路径缺失检查 CUDA_HOME 是否多了一层WinError 126DLL 加载失败清理 PATH 中的多版本 CUDA 或 add_dll_directoryninja 卡死缓存污染删 build 目录重编5. 编译完成后的性能验证与使用建议5.1 先跑通官方 demo 再改代码编译成功只是第一步我强烈建议先用官方的训练脚本完整跑一个很小的场景确认整个管线没问题再去做任何自定义修改。用经典仓库里的train.py跑几十个迭代观察 loss 是否下降、渲染出的图像是否正常这比任何单元测试都靠谱。我第一次编译成功后在 RTX 4080 Super 上跑官方自行车场景速度大概 120 FPS 的渲染帧率训练迭代一步耗时远低于纯 PyTorch 实现。RTX 5090 D 上更夸张同样场景直接到了 200 FPS 级别。这说明 CUDA 算子确实吃到了新架构的性能红利。5.2 组合多个 3DGS 项目时的注意事项diff-gaussian-rasterization 并不是唯一一个需要编译的模块。很多后续工作比如 2DGS、Deformable-GS、StreetGaussians都有类似的子模块。它们的编译套路大同小异但有几个共性坑一是每个项目都会自带一份 diff-gaussian-rasterization 的拷贝版本可能有细微差异编译时尽量用项目自带的版本不要混用。二是一些项目要求特定版本的 PyTorch如果你的 PyTorch 版本过低或过高编译时可能报某个 API 不存在。三是记住不同项目最好用独立的 conda 环境避免依赖污染。我遇到过最隐晦的问题A 项目编译好的 diff_gaussian_rasterization在 B 项目里 import 时突然报属性缺失最后发现是两个项目要求的模块版本不同编译出来的 pyd 也不同名但同路径覆盖了彼此。所以 conda 环境隔离真的是基本功。5.3 关于这套环境组合的个人体会编译 diff-gaussian-rasterization 这件事技术上不难难的是面对一大堆报错时不慌。我前后在 Windows 上编译过十几次把几个关键经验放在最后第一环境变量一定用 setx 设置而不要在 PowerShell 里临时$env:设置后就不管了因为你不知道 setup.py 会不会在子进程里重新读取。临时变量很容易在某个环节丢失setx 一劳永逸。第二GPU 驱动、CUDA Toolkit、PyTorch 三者尽量保持驱动 Toolkit 运行时的关系。这句话是我踩了无数坑之后的总结。驱动版本过低会导致新 CUDA 编译器生成的部分指令执行错误。第三如果实在编译不过去不要死磕。先确认自己的 CUDA Toolkit 是不是残废安装只装了驱动没装组件然后再检查 VS 是否完整。90% 的 Windows 编译失败都出在这两个地方而不是 diff-gaussian-rasterization 本身。第四我后来发现把整个编译过程放在 SSD 上会显著比 HDD 稳定。nvcc 编译时会生成大量临时文件磁盘 IO 瓶颈会导致一些莫名其妙的超时或文件锁错误。如果你笔记本是 HDD建议把项目代码挪到 SSD 分区再编译。Windows 下编译 CUDA 扩展这件事本质上是把一个 Linux 生态的工具链强行搬到 Windows 上。diff-gaussian-rasterization 只是其中比较典型的一个。只要理解了编译器归编译器、运行时归运行时这个核心逻辑版本组合的问题就能自己想明白。希望这份记录能帮你少走弯路一次编译通过。