csrc/ 负责 hoshicore._custom_op._C 的原生实现与本地构建。
设计边界:
- 只覆盖 custom-op 原生层
- Python 公共入口保持为
hoshicore._custom_op - 运行时按
compiled -> numpyfallback - 构建统一走
CMake + Ninja
csrc/
build_ops.py
CMakePresets.json
CMakeLists.txt
module.cpp
common/
ops/
fgp/
max/
median/
noise/
sigma_clip/
cuda/
职责:
module.cpppybind11 模块入口,注册_C内的算子ops/<name>/单个算子的 C++/CUDA 实现与绑定build_ops.py统一本地构建入口CMakeLists.txt/CMakePresets.jsoncustom-op 的 CMake/Ninja 构建骨架
不要求必须使用 conda。只要当前解释器环境里具备以下组件即可:
- Python 3.10+
pybind11- Python development headers
cmakeninja- 可用的 C/C++ 编译器
如果当前环境缺少 CMake/Ninja,可额外安装:
pip install -r csrc/requirements.txt这个文件只补 native 构建工具,不重复根目录 requirements.txt 里的项目依赖;
编译器和 OpenMP runtime 仍然是系统工具链要求。
已激活目标环境时,直接运行:
python csrc/build_ops.pybuild_ops.py 会把当前 sys.executable 传给 CMake 的 Python3_EXECUTABLE。
需要显式指定解释器时,直接用解释器路径调用脚本即可。
默认构建:
python csrc/build_ops.py显式系统 GCC:
python csrc/build_ops.py --cc /usr/bin/gcc --cxx /usr/bin/g++CUDA 构建:
python csrc/build_ops.py --cuda --cc /usr/bin/gcc --cxx /usr/bin/g++显式解释器:
/path/to/python csrc/build_ops.py --cc /usr/bin/gcc --cxx /usr/bin/g++只看配置:
python csrc/build_ops.py --dry-run--preset指定 CMake preset;日常路径通常不需要手动传--cc / --cxx显式指定编译器--cuda打开 CUDA 构建,自动根据平台选择对应 CUDA preset--compiler gcc|clang|msvc|auto选择编译器家族--no-openmp关闭 OpenMP--march-native启用本机 CPU 指令集优化;只建议本机 benchmark 使用--lto启用 LTO--omp-simd为支持的 kernel 启用显式 OpenMP SIMD pragma--clean清理旧产物后全量重编--verbose-build打印完整 backend 输出
- 扩展模块输出到
hoshicore/_custom_op/_C*.so|.pyd cmake中间产物默认在csrc/build/<preset>/- CUDA custom-op 当前为 fused
camera_model_remap
最终发布为 PyInstaller single-folder 模式。CUDA runtime 静态链接到 _C;
OpenMP 在 Linux/Windows 为动态链接(PyInstaller 自动收集),macOS 为静态链接。
| 依赖 | 链接方式 | 说明 |
|---|---|---|
| OpenMP (Linux + GCC) | 动态(libgomp.so) |
系统自带,PyInstaller 自动收集到产物目录 |
| OpenMP (Windows + MSVC) | 动态(vcomp140.dll) |
VC++ Redistributable 组件,PyInstaller 自动收集 |
| OpenMP (macOS) | 静态(Homebrew libomp.a) |
需先 brew install libomp,编译时自动检测并静态链接 |
| CUDA runtime | 静态(cudart_static) |
消除 libcudart.so / cudart64_*.dll 依赖 |
# Linux — 确认 cudart 已静态链接,libgomp 为动态(PyInstaller 会收集)
ldd hoshicore/_custom_op/_C*.so | grep -E "cudart|gomp"
# 预期:只看到 libgomp.so,不应出现 libcudart.so
# Windows (Developer Command Prompt)
dumpbin /dependents hoshicore/_custom_op/_C*.pyd
# 预期:出现 VCOMP140.DLL(正常),不应出现 cudart64_*.dllOpenMP 动态库由 PyInstaller 自动收集。spec file 确保 _C 模块被包含即可:
# PyInstaller spec — hiddenimports 确保 _C 被打包
hiddenimports=['hoshicore._custom_op._C']若后续使用了 cuBLAS/cuFFT 等额外 CUDA 库且无法静态链接,再按需添加到
binaries=[] 中。
构建 CUDA 算子需要安装 CUDA Toolkit,版本选择支持本机 GPU 的即可。 最终发布建议 12.8+,可覆盖所有架构的 NVIDIA GPU。
构建路径:
- Linux:
python csrc/build_ops.py --cuda - Windows: 使用
windows-msvc-cudapreset
Preset 参考:
| Preset | 平台 |
|---|---|
linux-gcc-cuda |
Linux |
windows-msvc-cuda |
Windows |
| 方向 | 状态 |
|---|---|
| AMD (ROCm/HIP) | 待评估 |
| macOS (Metal/MPS) | 待设计 |
| Vulkan (compute shader) | 待评估 |
所有 GPU 后端保持 CPU fallback 语义不变。
普通用户只需安装 NVIDIA 驱动(>= 570.65,对应发布构建的 CUDA 12.8),不需要 CUDA Toolkit。 驱动版本要求与 GPU 型号无关,只要驱动足够新即可;驱动过旧或无 NVIDIA GPU 时自动回退 CPU。
最小流程:
- 在
csrc/ops/<name>/新增.h/.cpp - 在
CMakeLists.txt新增 static library target 并链接到_C - 在
module.cpp中注册bind_*_ops(m) - 在
hoshicore/_custom_op/ops/增加 Python 包装与 numpy fallback - 在
hoshicore/_custom_op/backend_registry.py注册BackendCandidate - 在
hoshicore/_custom_op/api.py+__init__.py导出 - 补 focused tests(
tests/test_custom_ops.py) - 补 microbenchmark(
bench/cpu/kernels.py)
BackendCandidate 用于运行时判断当前包是否实际包含 native kernel。若 CMake /
打包未包含某个 kernel,Python wrapper 必须回到 numpy/CPU fallback;缺失 native
backend 只能影响性能,不能影响 public API 可用性。
CUDA 算子沿用同样流程,但额外需要:
- 在
CMakeLists.txt的HNW_ENABLE_CUDA分支里接入.cu/binding 源文件 - 保持 CPU fallback 语义不变
.cpp绑定文件需#include "common/compat.h"(MSVCssize_t兼容)- 在
BackendCandidate中标注对应 backend(如cuda_host_io)和 build flag(如cuda)
- 构建架构与 preset 设计详见 CMAKE_MIGRATION.md