
做 3D Gaussian Splatting 训练或者想在 Windows 11 上本地跑通相关渲染管线的朋友大概率都会撞见一个叫 simple-knn 的小家伙。它算不得明星项目但却是整个 CUDA 加速链路里绕不过去的一环。很多人在这一步卡住报错千奇百怪其实问题大多不在 simple-knn 本身而在于 Windows 11 下的编译链没有理顺。这篇文章就是把我在这台 Windows 11 工作站上从源码编译 simple-knn 的过程、踩过的坑、以及最后的排查方法完整记录下来。无论你是要在 3DGS 项目里顺手编它还是单纯需要把 simple-knn 作为独立扩展编译进 Python 环境这篇指南都能直接用。先说结论编译 simple-knn 的难度不在 simple-knn 本身而在 Windows 上 CUDA 扩展编译环境的搭建。它本质上是一个 C/CUDA 写成的 PyTorch C 扩展源码里有.cu文件需要 nvcc 和 MSVC 编译器协同工作。只要工具链版本对齐整个编译过程其实一分钟左右就能跑完。下面我会从项目定位、环境准备、源码结构、编译实操到报错排查按我实际操作顺序一步步讲清楚。1. simple-knn 是什么为什么偏要走源码编译1.1 先搞清楚它在项目里的角色simple-knn 从名字就能看出来是一个简化版的 K 近邻搜索实现核心逻辑用 CUDA 编写。它专门服务于 3D Gaussian Splatting 这类需要在大规模点云、高斯集合上频繁做邻域查询的场景。训练 3DGS 的时候每次迭代都要为每个高斯点找最近的若干邻居这个操作直接决定密度控制、位置更新这些环节的效率。simple-knn 就是干这个的。它和另一个常被一起提到的 rasterization 扩展diff-gaussian-rasterization一样都是典型的 CUDA extension。这类扩展不能像普通纯 Python 库那样在 PyPI 上发布跨平台可用的预编译 wheel因为 CUDA 代码必须针对本机的 CUDA Toolkit、GPU 架构和 MSVC 编译器现场编译。Windows 11 用户拿到源码后自己完成源码编译是绕不开的一步。1.2 源码编译和 pip 直接装的差异很多人第一反应是图省事直接pip install simple-knn。我的实际经验是别在这上面浪费时间。这个包几乎不会作为独立 wheel 出现在常用 PyPI 源里它更像是 3DGS 项目的内置模块与主项目一起分发。就算你翻到某个编译好的 wheel版本和本机 CUDA/PyTorch 大概率也对不上装完导入阶段照样报错。源码编译的优势在于可以精确匹配你本机的 CUDA Toolkit 和 PyTorch 版本还能针对自己的显卡架构做调整。缺点就是要求工具链齐全出错了得自己排。考虑到 simple-knn 编译产物只是一个很小的.pyd文件这个成本非常可控。我自己第一次成功编译后后续换机器重装基本三五分钟就能搞定。2. 环境准备与工具链选型Windows 11 版2.1 Visual Studio用 2022 版本最省心在 Windows 11 上编译 CUDA 扩展MSVC 编译器是刚需。因为 nvcc 编译完.cu文件后需要调用 cl.exe 来完成 C 部分和最终链接。这里有个关键点你装的 Visual Studio 版本必须被当前 CUDA Toolkit 支持。我用的是 VS 202217.x对应的 MSVC v143 工具集配合 CUDA 12.x是目前最省心的组合。安装 VS 时不要图精简至少勾选使用 C 的桌面开发工作负载它会把 MSVC 编译器、Windows SDK、CMake 相关组件一并装好。很多人编译失败是因为只装了 VS Code或者装了 VS 但没选 C 组件导致系统里根本没有 cl.exe。你在开始菜单里能搜到x64 Native Tools Command Prompt for VS 2022这个快捷方式存在基本就说明环境到位了。2.2 CUDA Toolkit 版本要和 PyTorch 对齐这是整个编译过程里最容易翻车的点。simple-knn 通过 PyTorch 的 C 扩展机制构建它会引用 PyTorch 自带的 CUDA 头文件和库同时也要用系统的 CUDA Toolkit 做 nvcc 编译。这两边的版本必须兼容。举个例子如果你的 PyTorch 是 cu121 版本装的是 CUDA 11.8那大概率会出现头文件版本不一致、甚至 nvcc 编译选项无法解析的问题。我的建议很简单先查 PyTorch 的 CUDA 版本再装对应的 CUDA Toolkit。比如 PyTorch 2.3.0cu121 对应 CUDA 12.1那系统里就装 CUDA 12.1 或 12.4向下兼容通常没问题。如果你用的是最新 PyTorchCUDA 12.4/12.6 通常也能配合好我在 26H2 的 Windows 11 上就用 CUDA 12.4 验证过。2.3 Python 虚拟环境强烈建议单独建源码编译这事最怕 Python 环境混乱。系统 Python 里装了一堆包不同项目依赖互相影响编译时就会遇到明明装了 PyTorch 却提示找不到这种玄学问题。所以我的建议是给这个项目单独建一个虚拟环境然后用虚拟环境里的 Python 去执行编译。我在 Windows 11 上习惯用 Anaconda 或 miniconda因为 conda 创建环境后切换非常方便conda activate knn_env一条命令就完事。如果你不想用 conda也可以直接用python -m venv knn_env。重点是记住编译时用的python命令必须指向你最终要导入 simple_knn 的那个解释器。用错了环境编出来的.pyd文件放到另一个环境里根本加载不了。2.4 一个关于系统版本的小经验我测试的第一台机器是 Windows 11 企业版 LTSC 2024后来又在一台 26H2 的机器上跑过同样的流程。结论是系统版本对这种源码编译几乎没有影响关键是工具链版本。LTSC 版本预装运行库少一些如果遇到缺失 dll 的报错装一下VC 运行库合集就能解决但这和 simple-knn 本身的编译无关。3. 源码获取与关键文件解析3.1 源码从哪里拿simple-knn 通常不单飞。在 3D Gaussian Splatting 项目里它被放在submodules/simple-knn目录下是作为子模块引入的。所以最标准的获取方式是在克隆主项目时带上--recursive参数这样 submodule 会一并拉下来。下载源码后先别急着跑编译把目录结构过一遍。simple-knn 的核心文件很少通常包括setup.py、simple_knn.cu、simple_knn.h以及一个__init__.py。它没有一堆复杂的依赖全部核心逻辑都集中在那一个.cu文件里。由于这些文件是 CUDA 源文件普通编辑器打开会看到一堆以__global__、__device__开头的函数这就是 KNN 计算的核心。3.2 setup.py 到底在干什么理解 setup.py 的内容能帮你定位大多数编译问题。这个脚本通常长这样from setuptools import setup from torch.utils.cpp_extension import BuildExtension, CUDAExtension setup( namesimple_knn, ext_modules[ CUDAExtension( namesimple_knn, sources[simple_knn.cu], extra_compile_args{cxx: [-stdc14], nvcc: [-O3]} ) ], cmdclass{build_ext: BuildExtension} )关键点有两处。第一CUDAExtension是 PyTorch 提供的类它会自动把 PyTorch 的 include 路径和 CUDA 的 include 路径拼进编译命令。第二.cu文件会被 nvcc 编译C 部分由 MSVC 编译最终一起链接成simple_knn.pyd。如果你改了显卡架构可以在extra_compile_args里给 nvcc 加-gencode参数但更省事的做法是通过环境变量控制。3.3 为什么 nvcc 和 cl.exe 必须同时在场这个问题是 Windows 编译独有的。在 Linux 上gcc 一家独大nvcc 直接调用 gcc 就能完成全部工作。但在 Windows 上nvcc 负责设备端代码GPU 部分而主机端代码CPU 部分和最终链接必须由 MSVC 的 cl.exe 和 link.exe 来完成。所以你的命令行环境里必须同时能访问到这两个编译器。很多人直接在普通 PowerShell 里执行python setup.py build_ext --inplace然后收到cl.exe is not recognized就是缺了这一步。解决方式要么打开x64 Native Tools Command Prompt for VS 2022要么在 PowerShell 里手动初始化 VS 环境。我后面会给出具体做法。4. 编译实操全过程4.1 第一步把编译环境初始化干净我推荐直接使用 VS 自带的开发终端而不是普通 PowerShell。操作方法不复杂在开始菜单搜x64 Native Tools Command Prompt for VS 2022并打开它已经自动加载了 cl.exe 的环境变量。在这个窗口里再切换到你的项目虚拟环境conda activate knn_env这里有个细节conda 的虚拟环境可能自带一个cl.exe比如安装了某些 MSVC 分发包时导致 VS 的 cl.exe 被挡在外面。遇到这种问题时可以在命令行里执行where cl.exe看看第一个命中路径是谁。如果确实是 conda 目录里的把 VS 的 VC Tools 路径手动加到你当前 PATH 的最前面或者干脆用vcvars64.bat重新初始化。4.2 第二步设置 CUDA 架构参数这一步不是必需的但我强烈建议做。simple-knn 编译默认会生成一个通用架构兼容性广但性能一般。设置TORCH_CUDA_ARCH_LIST环境变量可以精确指定目标显卡架构编译出来的扩展在你这块卡上效率更高。$env:TORCH_CUDA_ARCH_LIST 8.6不同显卡对应的值我不展开只给几个参考RTX 3060 及大部分 Ampere 架构是8.6RTX 4080 是8.9RTX 4090 也是8.9。如果你不知道自己显卡的 compute capability查一下显卡型号的参数表即可或者用小一点的通用值7.5它是兼容范围最广的保守选项。这台机器上我用的是8.6编译速度快运行时也没有性能损失。4.3 第三步执行编译命令切到 simple-knn 源码目录执行编译cd submodules\simple-knn python setup.py build_ext --inplace这个过程会有大量输出。前半段是检查工具链、解析 CUDA 路径中间是 nvcc 编译.cu文件最后是 MSVC 链接生成.pyd。如果一切顺利一分钟内命令行就会回到提示符目录下出现一个类似simple_knn.cp312-win_amd64.pyd的文件这就是编译产物。如果你不想在源码目录里留一堆中间文件也可以直接用 pip 安装pip install submodules/simple-knnpip 会调用 setup.py 构建 wheel然后安装到当前 Python 环境的 site-packages 里。两种方式我都试过都可以。区别只是前者编译产物留在源码目录方便调试后者更干净。4.4 第四步验证编译结果编译完别急着跑大项目先用一行代码确认扩展能被正常导入import simple_knn print(simple_knn.__file__)如果没有任何报错说明编译成功。如果这里报错比如DLL load failed或者ModuleNotFoundError多半是环境不对或者.pyd依赖的 DLL 找不到。此时可以先检查一下 PyTorch 能不能导入import torch print(torch.__version__, torch.version.cuda)PyTorch 本身能正常导入是 simple_knn 导入成功的必要前提。因为.pyd文件在加载时会链接到 Python 环境里的torch_python.dll和 CUDA 相关 DLL这些缺一不可。5. 常见问题与排查技巧实录5.1 实际遇到的报错和解决办法我把编译和导入阶段常见的报错整理成一张速查表都是我实测或帮别人排查处理过的情况报错内容原因解决办法cl.exe is not recognized当前终端没有加载 MSVC 环境改用 x64 Native Tools Command Prompt for VS 2022或手动执行vcvars64.batC1083: Cannot open include file: cuda_runtime.hCUDA_PATH 环境变量未设置或路径不对确认 CUDA 安装位置重装或手动设置CUDA_PATH及 PATHLNK1104: cannot open file cudart.lib链接器找不到 CUDA 库检查CUDA_PATH\lib\x64是否在库搜索路径里重开终端error: identifier nullptr is undefinedC 标准版本太低在 setup.py 的extra_compile_args里加[-stdc14]nvcc fatal: unsupported gpu architecture指定了不支持的架构号用TORCH_CUDA_ARCH_LIST设置为显卡真实的 compute capabilityImportError: DLL load failed.pyd依赖的 PyTorch/CUDA DLL 不兼容清空 build 目录重新编译确保 PyTorch 和 CUDA Toolkit 版本严格匹配No module named torch编译用的 Python 环境不对激活包含 PyTorch 的虚拟环境后再执行编译5.2 一个通用排查思路很多报错看起来千奇百怪但排查思路是一致的。先确认三件事当前终端是不是 VS 开发环境、当前 Python 是不是目标虚拟环境、CUDA_PATH 是不是指向 nvcc 实际所在目录。这三件事确认完八成的问题都消失了。另外编译过程中经常遇到明明改了环境变量却还是报同样的错。这种情况先别急着重装关掉当前终端重新开一个。Windows 的环境变量改动不会自动刷新到已打开的进程里很多玄学问题其实就是变量没有刷新。我踩过几次坑之后形成固定习惯改完环境变量一律新开窗口再编译。5.3 清空重编最暴力也最有效的手段如果改了代码或换了工具链版本编译后导入还是报错别犹豫把中间文件清空重编。在 simple-knn 目录下删除build目录和根目录下散落的.pyd、.lib、.obj文件再重新打包。python setup.py clean --all然后重新走一遍python setup.py build_ext --inplace。别觉得这很原始Windows 上的 CUDA 扩展编译经常因为缓存了旧产物导致各种奇怪问题清一次能省你两小时的排查时间。6. 一些延伸建议和技术总结6.1 从 simple-knn 延伸到整个 CUDA 扩展编译simple-knn 编译这条路走通之后你会发现整个 3DGS 项目里的其他 CUDA 扩展比如 diff-gaussian-rasterization编译流程几乎是同一个模板。区别只在于源码文件更多编译时间更长但那套工具链检查、虚拟环境准备、架构参数设置的方法可以完全复用。所以在配置环境时我建议一步到位把 VS 2022、CUDA Toolkit、PyTorch 都装成兼容的最新版本。这样编译 simple-knn 通过后编译其他扩展也会很顺利。如果你还没开始装环境别用老旧的 CUDA 11.x直接上 CUDA 12.x 是当前最稳妥的选择。6.2 几个容易被忽略的小细节先说路径。Windows 上源码目录如果有中文名或者空格可能出现一些莫名其妙的编译问题。项目路径里尽量只使用英文和数字不要带中文字符也不要放在 Program Files 这类带空格且带权限限制的目录里。再说防火墙和杀毒软件。有些安全软件会拦截.pyd文件的生成或加载导致编译成功但导入失败。如果你遇到DLL load failed并且怎么排查都没问题可以看看杀毒软件有没有隔离记录。最后是磁盘空间。CUDA Toolkit 的安装会占好几个 GB编译过程临时文件也不小。确保系统盘有至少 20GB 的空余空间否则半途报磁盘不足就尴尬了。6.3 后续还能怎么扩展simple-knn 编译成功只是开始。你可以把它接进自己的点云处理流程也可以在它基础上改造成更符合需求的 KNN 搜索逻辑。它的源码结构非常精简特别适合用来学习如何写一个 PyTorch CUDA 扩展。想深入的话把 setup.py 和.cu文件逐行读一遍收获比网上看一堆教程都大。我个人在实际操作中的体会是源码编译这类事情八成的时间花在环境准备上真正编译和解决问题只占两成。工具链版本配对了后面就是顺水推舟。如果你在 Windows 11 上编译 simple-knn 时遇到我上面没覆盖的报错建议把第一个报错信息不是最后那个贴到搜索引擎里看 nvcc 或 cl.exe 的具体输出比盯着编译失败这几个字瞎猜要高效得多。