Building pytorch3d 0.7.9 from Source on Windows 11在 Windows 11 上从源码编译 pytorch3d 0.7.9 完全指南适用环境Windows 11 CUDA Toolkit 13.x PyTorch 2.7.x Python 3.12难度⭐⭐⭐⭐需要手动 patch 源码编译时间约 20–40 分钟https://github.com/facebookresearch/pytorch3d目录环境说明前置准备克隆源码踩坑全记录与解决方案坑1Pulsar 链接失败 LNK2001坑2CUB_HOME 未设置坑3ext.cpp 仍然 #include pulsar 头文件坑4/* */ 注释块在 MSVC 下失效坑5pulsar/global.h 常量未定义坑6USE_NINJA0 对 pytorch3d 无效一键 patch 脚本合并版最终编译命令安装与验证原理总结1. 环境说明项目版本OSWindows 11 Professional Workstation Build 29531GPUNVIDIA GeForce RTX 3090 24GBGPU Driver595.02CUDA Toolkit13.1nvcc V13.1.80PyTorch2.7.1cu126以 CUDA 12.6 编译Python3.12.11venv 虚拟环境Visual Studio2022 Professional v17.12.17pytorch3d0.7.9⚠️注意版本不匹配CUDA Toolkit 13.1 vs PyTorch cu12612.6。这个不匹配是贯穿整个编译过程的背景问题我们通过之前已经打过的cpp_extension.pypatch 来绕过版本检查参见 diff-gaussian-rasterization 编译教程。2. 前置准备确保以下条件已满足# 激活虚拟环境 H:\PythonProjects3\Win_ComfyUI\.venv\Scripts\Activate.ps1 # 确认 Python 版本 python --version # Python 3.12.11 # 确认 PyTorch 已安装 python -c import torch; print(torch.__version__, torch.cuda.is_available()) # 2.7.1cu126 True # 确认 nvcc 可用需在 VS2022 Developer PowerShell 环境下 nvcc --version # nvcc release 13.1 # 安装编译依赖 pip install build wheel setuptools fvcore iopathVS2022 工具链环境变量初始化每次新开终端都需要# 导入 VS2022 编译环境 Import-Module D:\Program Files\Microsoft Visual Studio\2022\Professional\Common7\Tools\Microsoft.VisualStudio.DevShell.dll Enter-VsDevShell -VsInstallPath D:\Program Files\Microsoft Visual Studio\2022\Professional -SkipAutomaticLocation -DevCmdArguments -archx643. 克隆源码https://github.com/facebookresearch/pytorch3dcd H:\PythonProjects3\Win_ComfyUI git clone https://github.com/facebookresearch/pytorch3d.git cd pytorch3d # 确认版本 git log --oneline -5pytorch3d 没有专门的 Windows release wheel官方对 Windows 的支持非常有限必须从源码编译。https://pypi.org/project/pytorch3d/#fileshttps://www.piwheels.org/project/pytorch3d/4. 踩坑全记录与解决方案坑1Pulsar 链接失败 LNK2001错误现象LINK : error LNK2001: unresolved external symbol ...pulsar... pytorch3d/_C.cp312-win_amd64.pyd : fatal error LNK1120: 7 unresolved externals根本原因Pulsar 是 pytorch3d 内置的球形渲染器pytorch3d/csrc/pulsar/其模板函数在 CUDA 13.x Windows 下的符号导出方式与链接器期望不一致。这是上游已知问题官方对 Windows 的 Pulsar 支持本就残缺不全。解决方案直接删除 pulsar 源码目录Remove-Item -Path pytorch3d\csrc\pulsar -Recurse -Force删除目录后pytorch3d.renderer.points.pulsarPython 模块纯 Python 包装层仍然保留只是底层 C 渲染器不可用。对于 ComfyUI-3D-Pack 的使用场景不影响。坑2CUB_HOME 未设置错误现象UserWarning: The environment variable CUB_HOME was not found. NVIDIA CUB is required for compilation...根本原因pytorch3d 的setup.py要求显式设置CUB_HOME环境变量指向 CUB 头文件目录。CUBCUDA Unbound是 CUDA 的模板库从 CUDA 11 起已内置于 Toolkit但 pytorch3d 不会自动探测仍然要求手动指定。定位 CUB 实际路径# CUDA 13.x 将 CUB 移入了 cccl 子目录传统路径 include\cub 不存在 Get-ChildItem C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.1 -Recurse -Filter cub.cuh -ErrorAction SilentlyContinue | Select-Object FullName # 输出 # C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.1\include\cccl\cub\cub.cuh解决方案$env:CUB_HOME C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.1\include\cccl\cub Test-Path $env:CUB_HOME # 必须输出 True⚠️CUDA 版本差异CUDA 12.x 及以下CUB 通常在include\cub\CUDA 13.xCUB 被纳入 CCCLCUDA C Core Libraries路径变为include\cccl\cub\如果你不确定用Get-ChildItem ... -Filter cub.cuh -Recurse搜索确认。坑3ext.cpp 仍然#includepulsar 头文件错误现象H:\...\pytorch3d\csrc\ext.cpp(10): fatal error C1083: ./pulsar/global.h: No such file or directory根本原因删除csrc/pulsar目录后pytorch3d/csrc/ext.cpp里仍然有硬编码的 pulsar#include和注册代码// 第 9–13 行 // clang-format off #include ./pulsar/global.h // Include before torch/extension.h. // clang-format on #include ./pulsar/pytorch/renderer.h #include ./pulsar/pytorch/tensor_util.h以及第 100–176 行的PulsarRenderer类注册块。环境变量BUILD_PULSAR0对这些硬编码的#include完全无效——该变量只影响setup.py是否将 pulsar 的.cu文件加入编译列表不会修改ext.cpp的内容。解决方案用 patch 脚本修改ext.cpp见第5节完整脚本坑4/* */注释块在 MSVC 下失效错误现象第一版 patch 之后ext.cpp(147): error C2059: syntax error: , ext.cpp(155): error C2653: pulsar: is not a class or namespace name根本原因第一版 patch 用/* ... */块注释包裹了 pulsar 注册代码/* PULSAR DISABLED py::class_ pulsar::pytorch::Renderer, ... */ // END PULSAR DISABLED直觉上这应该有效但 MSVC 的预处理器在处理/* */注释时有一个已知行为在某些模板展开和宏处理场景下注释内的代码仍然会被语法解析器扫描导致pulsar::命名空间引用报错。正确方案使用#if 0 ... #endif#if 0 // PULSAR DISABLED py::class_ pulsar::pytorch::Renderer, ... #endif // END PULSAR DISABLED#if 0是 C/C 预处理器指令预处理阶段就将整个块完全跳过编译器根本看不到里面的代码。这是禁用大段代码的标准做法比/* */更可靠。坑5pulsar/global.h 常量未定义错误现象patch#if 0之后ext.cpp(193): error C2065: EPS: undeclared identifier ext.cpp(179): error C2065: MAX_FLOAT: undeclared identifier ext.cpp(180): error C2065: MAX_INT: undeclared identifier根本原因ext.cpp最后几行使用了EPS、MAX_FLOAT、MAX_INT、MAX_UINT、MAX_USHORT这些常量m.attr(EPS) py::float_(EPS); m.attr(MAX_FLOAT) py::float_(MAX_FLOAT); // ...这些常量原本定义在./pulsar/global.h里我们已经把这个 include 注释掉了所以常量全部丢失。解决方案在ext.cpp开头手动补充这些常量定义#include limits #ifndef MAX_FLOAT #define MAX_FLOAT std::numeric_limitsfloat::max() #endif #ifndef MAX_INT #define MAX_INT std::numeric_limitsint::max() #endif #ifndef MAX_UINT #define MAX_UINT std::numeric_limitsunsigned int::max() #endif #ifndef MAX_USHORT #define MAX_USHORT std::numeric_limitsunsigned short::max() #endif #ifndef EPS #define EPS 1e-6f #endif坑6USE_NINJA0 对 pytorch3d 无效现象设置了$env:USE_NINJA0但编译仍然调用 ninjasetup.py也一样。根本原因PyTorch 2.7 的cpp_extension.py在 Windows 上对 CUDA 扩展强制使用 ninja相关函数是win_wrap_ninja_compile第 907 行该函数完全没有检查USE_NINJA变量def win_wrap_ninja_compile(sources, ...): # 直接调用 _write_ninja_file_and_compile_objects # 没有任何 USE_NINJA 判断结论这个问题其实不需要解决。ninja 本身工作正常之前编译失败的原因是代码层面的错误pulsar 相关问题修好代码后 ninja 正常完成编译。5. 一键 patch 脚本合并版将以下内容保存为patch_final.py放在pytorch3d目录下# patch_final.py # 适用于 pytorch3d 0.7.9在 Windows CUDA 13.x 下禁用 Pulsar 并补充常量定义 content open(pytorch3d/csrc/ext.cpp, r, encodingutf-8).read() # ── Step 1: 注释掉 pulsar 的 3 行 #include ────────────────────────────────── content content.replace( // clang-format off\n #include ./pulsar/global.h // Include before torch/extension.h.\n // clang-format on\n #include ./pulsar/pytorch/renderer.h\n #include ./pulsar/pytorch/tensor_util.h, // clang-format off\n // #include ./pulsar/global.h // DISABLED: pulsar removed for Windows build\n // clang-format on\n // #include ./pulsar/pytorch/renderer.h\n // #include ./pulsar/pytorch/tensor_util.h ) # ── Step 2: 补充 pulsar/global.h 里的常量定义 ───────────────────────────────── insert_after // #include ./pulsar/pytorch/tensor_util.h defines // ── Pulsar constants (originally from pulsar/global.h) ───────────────────── // These were defined in pulsar/global.h which weve disabled above. // Manually redefined here to keep the rest of ext.cpp compiling. #include limits #ifndef MAX_FLOAT #define MAX_FLOAT std::numeric_limitsfloat::max() #endif #ifndef MAX_INT #define MAX_INT std::numeric_limitsint::max() #endif #ifndef MAX_UINT #define MAX_UINT std::numeric_limitsunsigned int::max() #endif #ifndef MAX_USHORT #define MAX_USHORT std::numeric_limitsunsigned short::max() #endif #ifndef EPS #define EPS 1e-6f #endif // ──────────────────────────────────────────────────────────────────────────── content content.replace(insert_after, insert_after defines) # ── Step 3: 用 #if 0 / #endif 禁用 pulsar 注册块 ───────────────────────────── # 注意不能用 /* */ 块注释MSVC 会在注释块内继续解析 pulsar:: 命名空间引用。 # #if 0 是预处理器指令整个块在预处理阶段就被跳过编译器完全看不到。 old_block ( // Pulsar.\n // Pulsar not enabled on AMD.\n #ifdef PULSAR_LOGGING_ENABLED\n c10::ShowLogInfoToStderr();\n #endif\n py::class_\n pulsar::pytorch::Renderer,\n std::shared_ptrpulsar::pytorch::Renderer(m, PulsarRenderer) ) new_block ( #if 0 // PULSAR DISABLED ── pulsar removed, Windows CUDA 13.x incompatible\n py::class_\n pulsar::pytorch::Renderer,\n std::shared_ptrpulsar::pytorch::Renderer(m, PulsarRenderer) ) content content.replace(old_block, new_block) old_end pulsar::pytorch::sphere_ids_from_result_info_nograd); new_end pulsar::pytorch::sphere_ids_from_result_info_nograd);\n #endif // END PULSAR DISABLED content content.replace(old_end, new_end) # ── Step 4: 注释掉 PULSAR_MAX_GRAD_SPHERES依赖 pulsar 类型──────────────── content content.replace( m.attr(PULSAR_MAX_GRAD_SPHERES) py::int_(MAX_GRAD_SPHERES);, // m.attr(PULSAR_MAX_GRAD_SPHERES) py::int_(MAX_GRAD_SPHERES); // DISABLED ) open(pytorch3d/csrc/ext.cpp, w, encodingutf-8).write(content) print(✅ patch_final.py applied successfully)运行方式cd H:\PythonProjects3\Win_ComfyUI\pytorch3d python patch_final.py # 输出✅ patch_final.py applied successfully验证 patch 结果# 确认所有 pulsar 引用都在注释或 #if 0 块内 Select-String -Path pytorch3d\csrc\ext.cpp -Pattern ^[^/].*pulsar | Where-Object { $_ -notmatch #if 0|#endif } # 应该无输出即没有活跃的 pulsar 代码6. 最终编译命令按顺序执行以下步骤# ── 0. 进入源码目录 ─────────────────────────────────────────────────────────── cd H:\PythonProjects3\Win_ComfyUI\pytorch3d # ── 1. 删除 pulsar C 源码目录 ─────────────────────────────────────────────── Remove-Item -Path pytorch3d\csrc\pulsar -Recurse -Force -ErrorAction SilentlyContinue # ── 2. 设置环境变量 ─────────────────────────────────────────────────────────── # CUB 路径CUDA 13.x 专用路径旧版本在 include\cub $env:CUB_HOME C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.1\include\cccl\cub # MSVC 编译工具链 $env:DISTUTILS_USE_SDK 1 $env:MSSdk 1 # CUDA 编译选项 $env:FORCE_CUDA 1 $env:BUILD_PULSAR 0 # 只编译 RTX 3090 对应的 Ampere 架构sm_86加速编译 $env:TORCH_CUDA_ARCH_LIST 8.6 # ── 3. 应用源码 patch ───────────────────────────────────────────────────────── python patch_final.py # ── 4. 清理旧的构建产物 ─────────────────────────────────────────────────────── Remove-Item -Path build, dist, *.egg-info -Recurse -Force -ErrorAction SilentlyContinue # ── 5. 编译约 20–40 分钟───────────────────────────────────────────────── python setup.py bdist_wheel 21 | Tee-Object -FilePath H:\PythonProjects3\Win_ComfyUI\pytorch3d_build.log为什么用setup.py而不是python -m build两者都可以。使用setup.py bdist_wheel的好处是输出更直接Tee-Object能同时显示并保存完整日志方便排查问题。7. 安装与验证编译成功后在dist/目录下会生成 wheel 文件# 安装 pip install dist\pytorch3d-0.7.9-cp312-cp312-win_amd64.whl # 验证必须在 pytorch3d 源码目录外执行否则 import 会读本地源码而非安装包 cd H:\PythonProjects3\Win_ComfyUI python -c import pytorch3d; print(✅ pytorch3d 安装成功, pytorch3d.__version__) # 输出✅ pytorch3d 安装成功 0.7.98. 原理总结为什么 Windows 编译 pytorch3d 这么麻烦问题根因解决思路Pulsar LNK2001Windows CUDA 13.x 的 C 模板符号导出机制与 Linux 不同直接移除 PulsarCUB_HOME 找不到CUDA 13.x 把 CUB 移入 cccl 子目录pytorch3d 不自动探测手动设置新路径ext.cpp 找不到 pulsar 头文件BUILD_PULSAR0 只控制编译列表不修改源码直接 patch 源码/* */注释无效MSVC 传统预处理器对注释块内仍做部分解析改用#if 0 / #endif常量未定义EPS/MAX_* 常量定义在被禁用的 pulsar/global.h 中在 ext.cpp 开头手动补充定义CUDA 13.1 PyTorch cu126 版本不匹配本次编译中 CUDA Toolkit13.1与 PyTorch 内置 CUDA12.6存在版本不匹配。这通过之前对cpp_extension.py的 patch 绕过了版本检查。编译出的扩展在运行时使用 PyTorch 的 CUDA Runtime12.6不直接依赖系统 CUDA 13.1 Runtime因此实际运行没有问题。TORCH_CUDA_ARCH_LIST 的意义$env:TORCH_CUDA_ARCH_LIST 8.6RTX 3090 是 Ampere 架构compute capability 8.6。不设置此变量时pytorch3d 会为所有可见 GPU 的所有架构编译大幅增加编译时间。明确指定8.6可以将编译时间从 60 分钟压缩到 20–40 分钟。本文记录于 2026年3月基于 ComfyUI-3D-Pack 插件依赖手动编译的实际踩坑经历。