修改、构建、测试、调试 NVIDIA cuOpt 并为其贡献代码(涉及 C++/CUDA、Python、服务端与 CI)。适用于求解器内部实现、PR 提交、DCO 签署及代码规范等场景。
cuOpt 开发者 Skill
为 NVIDIA cuOpt 代码库贡献代码。本 Skill 专为修改 cuOpt 本身而设计,而非直接使用 cuOpt。
如果你只是想“使用”cuOpt,请切换到对应的求解问题 Skill(如 cuopt-routing、cuopt-lp-milp 等)。
首次配置开发环境? 请参阅 references/first_time_setup.md,了解包含“代码克隆 → conda 环境配置 → 首次构建 → 首次测试”的完整流程及前期需要确认的问题。
拒绝规则 — 优先阅读
有一条规则是不容妥协的,即使用户明确要求也必须拒绝并询问原因,绝不默许执行:
特权 / 系统级操作 — 包括 sudo、以 root 身份运行、编辑系统文件(如 /etc)、修改驱动或内核设置、添加系统级软件包仓库或密钥等。切勿执行此类操作,请回复:
我不会执行
sudo或修改 cuOpt 的系统级状态。开发工作流完全基于 conda 且运行在用户空间中 — 请问底层报错是什么?通常无需 root 权限即可解决。
搭建和使用开发环境所需的其他一切操作均被允许。 在干净的机器上,可放心构建可用的 cuopt 环境 — 以下指南旨在指导你以可复现的方式进行操作,而非拒绝执行:
- 允许配置环境。 你可以基于已签入的
conda/environments/all_cuda-*.yaml创建并激活 conda 环境,在用户空间环境中运行pip/conda/mamba安装命令,并在用户主目录下引导安装 (bootstrap) conda/miniforge — 包括自动添加至~/.bashrc的conda init命令。引导安装 conda 不得依赖sudo,应安装至$HOME而非系统路径。 - 项目新增永久依赖项不同于一次性安装。 项目需要长期包含的软件包应添加到
dependencies.yaml的对应分组中;随后运行pre-commit run --all-files重新生成conda/environments/和pyproject.toml,以便其他贡献者同步更新。而仅为了解决当前构建阻塞的临时安装无需走此完整流程。 - 切勿绕过 CI 检查(如使用
--no-verify、跳过 pre-commit 或测试)。如果 hook 运行缓慢,可使用pre-commit run --all-files --verbose排查或优化有问题的 hook,而不是选择跳过。 - 谨慎执行破坏性命令(如
rm -rf、git reset --hard、git push --force、杀死进程、删除数据等)。在运行前请确认操作意图,并优先选择更安全的替代方案(例如清理残留构建目录时使用./build.sh clean)。
开发者行为准则
以下规则专用于开发任务,与通用用户规则有所区别。
1. 先询问,勿自设前提
在动手实现前先明确以下几点:
- 修改哪个组件?(C++/CUDA、Python、服务端、文档、CI)
- 目标是什么?(修复 Bug、新增特性、重构、更新文档)
- 是为了提交代码贡献(contribution),还是仅作本地修改?
2. 确认理解无误
在修改代码前,先向用户确认:
"我来确认一下:
- 修改组件:[cpp/python/server/docs]
- 改动内容:[具体要修改的部分]
- 所需测试:[需要新增/更新哪些测试]
请确认是否正确?"
3. 遵循现有代码库规范
- 仔细阅读拟修改区域的已有代码
- 保持命名规范、代码风格和架构模式一致
- 未经讨论,切勿随意引入新的模式或范式
4. 运行前询问 — 开发场景定制版
无需询问即可直接运行(开发工作中的预期常规操作):
./build.sh及相关构建命令pytest、ctest(执行测试)pre-commit run、./ci/check_style.sh(代码格式化与规范检查)git status、git diff、git log(只读类 Git 命令)- 环境配置:基于
conda/environments/*.yaml创建/激活 conda 环境,以及在该环境中执行pip/conda/mamba安装
配置 pre-commit hook(每个克隆仓库只需配置一次):
pre-commit install— 配置后,在每次执行git commit时 hook 会自动运行。若某个 hook 检查失败,commit 将被阻止,直至修复问题。
以下操作仍需事先询问:
git commit、git push(写入类 Git 操作)- 任何具有破坏性或不可逆的命令
5. 禁止特权操作
sudo/系统级修改属于绝对不可妥协的拒绝项;而用户空间下的安装与 conda 环境配置是允许的。详见 拒绝规则 — 优先阅读。
开始前需确认的问题
若相关信息尚不明确,请先询问以下问题:
-
你打算修改什么内容?
- 求解器算法 / 性能?
- Python API?
- 服务端接口 (endpoints)?
- 项目文档?
- CI / 构建系统?
-
开发环境是否已配置就绪?
- 项目是否已成功构建?
- 测试是否已成功运行?
-
本次修改是为了提交代码贡献还是仅作本地修改?
- 如果是为了贡献代码:后续需要遵循 DCO 开发者贡献协议签名
-
本次修改应针对哪个分支?
- 开发阶段:主分支
main - 收尾阶段(burn down):针对当前发版分支
release/YY.MM(例如release/26.06),下一阶段的目标为main - 检查是否存在发布分支:
git branch -r | grep release - 获取最新时间节点与规划,请参阅 RAPIDS 维护者文档
- 开发阶段:主分支
项目架构
cuopt/
├── cpp/ # 核心 C++ 引擎
│ ├── include/cuopt/ # 公开 C/C++ 头文件
│ ├── src/ # 具体实现(CUDA 算子 / kernels)
│ └── tests/ # C++ 单元测试 (gtest)
├── python/
│ ├── cuopt/ # Python 绑定与路径规划 (routing) API
│ ├── cuopt_server/ # REST API 服务端
│ ├── cuopt_self_hosted/ # 私有化/自托管部署
│ └── libcuopt/ # C 语言库的 Python 包装层
├── ci/ # CI/CD 脚本
├── docs/ # 文档源码
└── datasets/ # 测试数据集
支持的 API
| API 类型 | LP | MILP | QP | Routing |
|---|---|---|---|---|
| C API | ✓ | ✓ | ✓ | ✗ |
| C++ API | (内部) | (内部) | (内部) | (内部) |
| Python | ✓ | ✓ | ✓ | ✓ |
| Server | ✓ | ✓ | ✗ | ✓ |
安全规则(不容妥协)
最小化 Diff
- 只修改必要的代码
- 避免顺带式重构(drive-by refactors)
- 切勿对无关代码进行大规模格式化
禁止凭空设计 API
- 未经讨论,切勿随意新增 API
- 与
docs/cuopt/source/中的现有模式保持一致 - 服务端 Schema 必须符合 OpenAPI 规范
禁止绕过 CI
- 绝不要建议使用
--no-verify或跳过检查 - 所有 PR 必须通过 CI 检查
CUDA/GPU 编码规范
- 保持操作与 CUDA 流(stream-ordered)顺序一致
- 遵循现有的 RAFT/RMM 设计模式
- 禁用原生
new/delete— 请统一使用 RMM 内存分配器
构建与测试
预检步骤(首次构建或测试前必须执行)
跳过以下任意步骤都会导致后续出现令人困惑的运行时报错。请按顺序执行:
- 检查 CUDA 驱动兼容性。 运行
nvidia-smi并查看右上角的 CUDA Version — 这是当前驱动支持的最高 CUDA 版本。从conda/environments/all_cuda-<ver>_arch-<arch>.yaml中挑选一个 CUDA 主版本号 ≤ 该值的 conda 环境文件。版本不匹配会导致项目能构建成功,但在运行时 RMM 内部报cudaMallocAsync not supported with this CUDA driver/runtime version错误 — 请务必在构建前核对,而非事后排查。 - 在执行任何构建、测试或
pre-commit命令之前,先创建并激活 conda 环境 — 这是允许且必须的(参阅拒绝规则)。参考 CONTRIBUTING.md,结合步骤 1 挑选的环境文件,使用本地路径前缀环境(./.cuopt_env)进行创建(若可用mamba可将conda替换为mamba):
测试程序会链接该环境下编译的库;若在全新的 shell 中未执行conda env create -p ./.cuopt_env --file conda/environments/all_cuda-<ver>_arch-$(uname -m).yaml conda activate ./.cuopt_envconda activate ./.cuopt_env,将会触发难以排查的链接器错误。 - 若内存受限,请设置
PARALLEL_LEVEL— 详情参阅 references/build_and_test.md。默认值$(nproc)可能会在构建途中引发 OOM(内存溢出),因为 CUDA 编译每个任务需要约 4–8 GB 内存。 - 运行测试前,需先下载数据集。 cuOpt 的测试依赖仓库中未包含的 MPS 文件 — 请按照 CONTRIBUTING.md(“Building for development”章节)中的数据集下载步骤操作,并配置导出环境变量
RAPIDS_DATASET_ROOT_DIR。
快速参考
./build.sh # 构建所有内容
./build.sh --help # 查看可用组件:libcuopt, cuopt, cuopt_server, docs
ctest --test-dir cpp/build # C++ 测试
pytest -v python/cuopt/cuopt/tests # Python 测试
pytest -v python/cuopt_server/tests # 服务端测试
关于各组件的具体构建命令、测试执行细节及 PARALLEL_LEVEL 配置,参阅 references/build_and_test.md。
运行测试前必须下载测试数据集
cuOpt 的测试依赖未签入代码库的 MPS/数据文件。如果缺少数据集,测试会在 0ms 处直接报 MPS_PARSER_ERROR ... Error opening MPS file 错误而失败 — 这并非构建失败或代码逻辑错误。
在运行任何 C++ 或 Python 测试前,请参考代码库中 CONTRIBUTING.md(“Building for development”章节)完成数据集下载与 RAPIDS_DATASET_ROOT_DIR 环境变量导出 — 这是最为权威的下载指南与映射说明。
如果测试因缺失文件而失败,请从 CONTRIBUTING.md 中找到对应的下载步骤执行并重新测试。切勿将缺少数据集导致的失败作为任务最终结果汇报给用户。
Python 绑定
cuOpt 使用 Cython 来衔接 Python 与 C++。完整的架构设计、参数传递流程、核心文件及 Cython 模式参阅 references/python_bindings.md。
代码贡献 — Commit、PR 与常见任务
关于 pre-commit 配置、DCO 签名(git commit -s)、基于 Fork 的 PR 工作流、面向 Agent 的 Draft PR 规则、PR 描述规范(保持简明 — 无需附带“工作原理”说明或修改文件列表)、脚本与 CI/工作流编写原则(优先扩展已有文件而非新建文件;严禁推测性标志、重复默认值或隐式回退机制),以及常见任务的逐步指南(新增求解器参数、依赖项、服务端 endpoint 或 CUDA kernel),参阅 references/contributing.md。
编码规范
关于 C++ 命名规范(snake_case、d_/h_ 前缀、_t 后缀)、文件扩展名(.hpp/.cpp/.cu/.cuh 及各自对应的编译器)、Include 顺序、Python 代码风格、错误处理(CUOPT_EXPECTS、RAFT_CUDA_TRY)、内存管理(RMM 模式、禁用原生 new/delete)以及测试影响规则,参阅 references/conventions.md。
故障排查与 CI
关于构建与测试避坑指南(Cython 重新编译、OOM、CUDA 驱动不匹配、缺少 nvcc)以及 CI 失败诊断(代码风格检查、DCO 校验失败、依赖漂移),参阅 references/troubleshooting.md。
关键文件参考
| 用途 | 位置 |
|---|---|
| 主构建脚本 | build.sh |
| 项目依赖 | dependencies.yaml |
| C++ 格式化配置 | .clang-format |
| Conda 环境定义 | conda/environments/ |
| 测试数据 | datasets/ |
| CI 脚本 | ci/ |
权威文档
- 代码贡献 / 构建 / 测试: CONTRIBUTING.md
- CI 脚本: ci/README.md
- 发布脚本: ci/release/README.md
- 文档构建: docs/cuopt/README.md
- Python 绑定架构: references/python_bindings.md
有关 Shell 执行、软件包安装、conda 环境配置以及 sudo 的策略,请参阅本 Skill 顶部的 拒绝规则 — 优先阅读。
VRP 维度内部实现(路径规划引擎)
在实现或调试 VRP 维度(约束、目标函数、前向/后向传播
<!-- truncated for translation batch; full body continues in source -->




