关于 cupynumeric-migration-readiness
这项只读技能在迁移前检查 NumPy 代码是否适合迁至 cuPyNumeric,并按扩展性、API 支持、阻碍项和重构需求生成结构化评估。
主要功能
- 01只读源码检查
- 02NumPy 写法扩展性分类
- 03核对 API 支持清单
- 04结构化迁移结论与发现
- 05提供重构方案建议
适用场景
- 01迁移前评估 GPU 适用性
- 02查找限制扩展性的 NumPy 写法
- 03规划 cuPyNumeric 重构
- 04检查 API 兼容性与迁移成本
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ promptingcompany/ nv-skills --skill cupynumeric-migration-readiness安装后在 Claude Code 中输入/cupynumeric-migration-readiness确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.gitignoreBENCHMARK.mdassets/api-support.mdsample_report.mdassets/examples/blocks_scaling.pyneeds_refactor.pyscales_well.pyevals/evals.jsonevals/files/api_gap_hotpath.pyblocks_scaling.pyconvergence_loop.pycupy_mixed.pydense_linalg.pydense_with_scipy_boundary.pygraph_workload.pyitem_sync.pyjacobi_heat.pymany_blocks.pymonte_carlo_bs.pymonte_carlo_good.pyneeds_refactor.pyscales_well.pysequential_recurrence.pysparse_sklearn.pytiny_array.pyunlisted_api.pyview_mutation.pyreferences/case-studies.mddecision-framework.mdexecution-model.md详细介绍
cuPyNumeric 迁移准备度
目的
请在迁移前使用此技能,而不是迁移过程中。 回答一个问题:用户现有的哪些 NumPy API 能在 cuPyNumeric 上实现扩展,哪些需要重构? 在用户投入数周工程时间进行移植之前,就应回答这个问题。为此,请阅读源代码,按各 NumPy 惯用写法在 Legate/NVIDIA GPU 技术栈上的预期多 GPU 扩展能力进行分类,对照随附的 API 支持清单,并给出结构化结论,说明每项发现的理由和相关方案指引。
这是一项静态、只读评估。 使用 Read、Grep 和 Glob 检查用户的源代码。不要运行用户的代码、修改或写入文件,也不要打印环境变量或机密信息。下方列出的 legate 和 cuPyNumeric Doctor 命令是建议用户运行的命令,不是此技能要执行的操作。
如果你之前从未使用过此技能,请先阅读 references/getting-started.md。
何时使用此技能
当用户即将将 NumPy 代码迁移到 GPU,并询问其能否在 cuPyNumeric/GPU 上扩展、是否应该迁移、哪些部分会受益、移植前必须做哪些改动,或移植是否值得时,使用此技能;用户提及移植前评估、扩展性分析、惯用写法分析、GPU 重构规划,或识别面向 GPU 的 NumPy 反模式时,也使用此技能。
当请求不是迁移前评估时,拒绝并引导用户:
- 迁移后的性能分析/性能剖析(“已经移植了,为什么这么慢?”)→ 指引用户使用
legate --profile,并参考上游的性能分析和调试指南。 - 自定义 CUDA/内核编写(“编写/优化 CUDA 内核”)
如果用户确实要迁移图计算/稀疏计算/ML/NLP 工作负载,则仍属适用范围:对其进行评估,并通过 Gate 4 给出 NOT RECOMMENDED。这是评估结论,不是拒绝请求。
指令
按顺序执行以下全部五个步骤。阅读用户的代码并从语义层面进行推理;不要只给出一句笼统的结论。
步骤 1 — 收集背景信息
扫描代码前先了解情况。以下每项都设有适用于典型工作负载的默认值;用户未主动提供具体信息时,使用默认值,不要因等待答复而停滞。
- 源代码位置。 未提供路径时,默认为当前工作目录。
- 运行时热路径数组的大致大小。 默认为 3,000 万至 5,000 万个元素。将用户提供的数字(或此默认值)映射到Gate 2 层级(每 GPU 6.5 万个元素的下限;单 GPU 实现实际加速需达到 1,000 万以上;多 GPU 需达到 1 亿以上)。
- 目标硬件。 默认为单节点、1–4 块 GPU。确认后再假设使用多节点。对于仅使用 CPU 的运行,询问每个节点的 RAM,而不是 FBMEM。
- 主要计算模式。 随机模板 / GEMM / Monte Carlo / 归约 / 与 SciPy 混合。请用户说明;否则在步骤 3 中根据代码推断。
在评估开头说明你采用的默认值,以便用户更正。如果某个值无法确定,请明确说明,并继续进行定性评估;除上述默认值外,不要编造数字。
第 2 步 — 加载 API 支持清单
阅读 assets/api-support.md,这是已提交的上游 NumPy 与 cuPyNumeric 对比表快照。对于代码调用的每个 NumPy API,找到对应行并查看开头的符号:
✓✓ numpy.X— 已实现,且支持多 GPU(最佳路径)。✓ numpy.X— 已实现,但仅支持单 GPU/CPU(多节点时需注意)。🟡 numpy.X — <note>— 部分支持;请阅读说明。✗ numpy.X— cuPyNumeric 分布式路径尚未实现。调用时的行为因版本而异(某些不支持的 API 会转由主机 NumPy 处理,其他则会引发异常)——无论哪种情况,在热路径中使用都会阻碍迁移。不要向用户承诺会静默回退到主机 NumPy。
如果 Fetched: 行显示的时间已超过约 90 天,请刷新快照——请参阅 Available Scripts 部分。
第 3 步 — 从语义上阅读代码
使用 Read 和 Grep 检查用户的文件,并根据 references/idioms-that-scale.md 和 references/idioms-that-block.md 对数组运算的每个部分进行分类(完整的理由和 R 编码见其中)。从语义上阅读,不要只靠正则表达式:标记前,先确认 arr 可追溯到 cupynumeric 数组(或别名为它的 np.*),并检查该访问是否位于热循环中。遵循以下规则:
- 将元素循环标记为阻碍项(
for i in range(n): arr[i] = ...);循环体经过向量化的 epoch/step/file 循环可视为正常——应区分两者。 - 标记标量同步——在热循环中对 cuPyNumeric 数组调用
.item()/float()/int()/bool()/complex()(每次迭代都会同步到主机);边界处允许使用。 - 标记归约条件——对数组归约结果进行
if/while判断(while np.max(err) > tol:)会在每次迭代时同步。 - 将循环中的可提升分配标记为可修复的低效操作。
- 标记运行时代码中用于分区/通信数组数据、且与
cupynumeric并用的mpi4py(R108)——但要先确认它会在热路径中调用 MPI;README、构建脚本或备用启动器中的 grep 命中可忽略。 - 将
reshape/asarray/flatten上的order=标记为 R109——无论该版本会发出警告还是静默忽略,都要标记。 - 在多 GPU 场景下,对
np.random.*的 INFO 始终引用 R304:默认情况下,跨 GPU 无法实现逐位一致的可复现性(--gpus N/LEGATE_GPUS是 Legate 启动器参数)。 - 标记数组上的 Python 内置函数(
sum/max/min/any/iter(arr))——会回退到主机迭代(R110;上游最佳实践)。允许使用len(arr)(查询形状;为确保对 0 维数组的安全性,优先使用arr.shape[0]/arr.size)。 - 标记热循环中混用
cupy和cupynumeric的情况(R111);这两个运行时不共享 GPU 内存,因此每次切换都会经过主机 NumPy。 - 查询代码调用的每个 NumPy API,确认其是否列在
assets/api-support.md中(符号说明见第 2 步)。
若要深入了解“为什么”,请阅读 references/gpu-stack.md(内存、SM、通信、分派)和 references/execution-model.md(延迟执行、同步点、映射器)。
步骤 4 — 生成结构化评估报告
按以下顺序提交报告。每项发现都引用 file:line,方便用户定位。
- 结论:用一句话概述——参见下方的“结论框架”。
- 可正常工作的部分(SCALES 发现):引用有代表性的代码行,让用户了解替换导入语句后哪些部分会加速。
- 阻碍项(BLOCKS 发现):每项都关联到
idioms-that-block.md和refactor-recipes.md中的一项方案。 - 可修复项(REFACTOR 发现):按方案分组;一项方案通常可以修复多个位置。
- 兼容性 / 成本说明(INFO 发现):SciPy 边界、仅支持单 GPU 的 linalg / FFT,以及 RNG 布局与
--gpus N的关系。 - API 支持缺口:代码调用的 API 中,按清单标注为未实现或仅支持单 GPU 的 API。
- 决策框架摘要:列出
references/decision-framework.md中的 Gate 1–6,并标记为通过 / 未通过 / 不确定。 - 建议的后续步骤:说明应优先应用哪些方案、是否先移植一个模块,以及何时启用 cuPyNumeric Doctor。
必须包含全部 8 个部分,即使结论是 READY 或 NOT RECOMMENDED。对于空白部分,单独一行写上 “此代码无相关内容” 或 “不适用 — 参见结论”;不要省略标题。标题是评估报告的固定结构。示例报告请参见 assets/sample_report.md。
步骤 5 — 移交 cuPyNumeric Doctor 进行运行时验证
用户应用方案并确保代码可以运行后,指导他们运行 cuPyNumeric Doctor:
CUPYNUMERIC_DOCTOR=1 CUPYNUMERIC_DOCTOR_FORMAT=json CUPYNUMERIC_DOCTOR_FILENAME=doctor-report.json legate --gpus 1 main.py
cuPyNumeric Doctor 可以捕获源代码审查无法发现的运行时问题(标量 .item 访问、ndarray 迭代、高级索引、nonzero 误用、导入 mpi4py、对视图进行原地操作)。以这句话结束评估:“现在启用 cuPyNumeric Doctor 运行;以下是需要关注的输出内容。”
评估框架
根据发现的类型定性给出评估结果,而非依据分数:
| 评估结果 | 适用情况 | 操作 |
|---|---|---|
| 就绪 | 没有阻塞项;重构项很少或没有 | 替换导入;进行基准测试 |
| 轻度重构 | 存在少量可通过配方修复的模式(R201–R206),或一两个简单的阻塞项 | 应用 refactor-recipes.md 中的 1–3 个配方;重新检查,直至就绪 |
| 重大重构 | 热路径中有多个阻塞项,或存在任何 R108(mpi4py)——需要重写,但不代表不适用 | 面向真实项目;每个模块预留 1–3 个工程师周 |
| 不建议 | 仅有两种失败情况:门槛 2(数组低于 65,536 的下限)或门槛 4(计算模式不适用)。大量阻塞项不会导致此结果 | 先调整结构,或改用其他运行时 |
按以下顺序应用;满足的第一项即为结果:
- 门槛 4 未通过(稀疏/图/ML/序列/字符串)→ 不建议。
- 门槛 2 未通过(热路径数组每个 GPU 少于 65,536 个元素,且没有可行的批处理方案)→ 不建议。
- 存在任何 R108(
mpi4py)→ 重大重构(成本在于重写并行层,而非不适用)。 - 热路径中存在多个阻塞项(R101–R111)→ 重大重构(数量不会使结果进一步升级——每个阻塞项都有对应的配方)。
- 存在一两个可通过配方修复的阻塞项(例如,R101–R104 元素循环/同步)→ 轻度重构。
- 只有重构模式(R201–R206)→ 轻度重构;配方都是机械性的。
- 没有阻塞项,也没有重构项 → 就绪。
- 热路径上有清单中未列出的 API → 降低一个等级(重大重构仍为重大重构,绝不会变成不建议)。仅适用于单 GPU 的 API 只对多节点场景有影响。
权衡发现的类型,而非数量。 热循环中的一个 R101 就比十个 R001 影响更大——它会破坏 R001 原本能够实现的扩展性。反过来,大量阻塞项加上 R108,仍然属于重大重构,而非不建议——等级衡量的是工程成本,而非绝望程度。只有未满足规模或计算模式要求时,才判定为不建议。完整框架见:references/decision-framework.md。
哪些可扩展,哪些会阻塞(一览)
- 可扩展(保持原样)——向量化逐元素运算、归约、矩阵乘法/einsum、
np.where、每个 GPU 上数据量较大的切片式模板计算arr[1:-1, 1:-1]、out=、布尔掩码索引。 - 阻塞项(迁移前移除)——元素循环、
np.vectorize、for row in arr、热循环中的.item()/.tolist()/bool(arr)、循环中的归约型if/while、arr[::2]、dtype=object、mpi4py、order=、min/max/sum(arr)。 - 重构项(应用配方)——循环内分配内存、循环中重新绑定
x = x + y、循环中的vstack/hstack/concatenate、np.nonzero()加索引、对diag/flip/flatten视图进行变更、热循环中的reshape。 - 信息项(成本提示,不构成阻塞)——SciPy 导入、单设备上的
linalg.qr/svd、单次变换的fft.*、按规模阈值判断的linalg.solve/cholesky。
完整分类见 idioms-that-scale.md 和 idioms-that-block.md。清单中未列出的 API 请直接略过(它们不在上游表格的范围内——标出只会造成干扰)。
阅读顺序
权威的按顺序阅读指南位于 references/getting-started.md — 请先通读一次,了解整体情况。
对于复杂评估,必读内容包括 idioms-that-block.md、refactor-recipes.md 和 decision-framework.md;其余文件(idioms-that-scale.md、gpu-stack.md、execution-model.md、partitioning-and-balance.md、case-studies.md)按需阅读。
局限性
- 不会运行 cuPyNumeric。 无需运行时;这是移植前检查。实际加速效果会在迁移后测量。
- 不会自动生成重构后的代码。 它会指出需要修改的内容并提供相应方案;由用户(或后续 Agent)应用这些方案。
- 不会分析工作负载性能。 如需运行时测量,请使用
legate.timing.time()和上游的性能分析和调试指南。 - 不能替代判断。 模式匹配可能漏掉日志记录中的隐式同步、隐藏
.tolist()的装饰器,以及依赖运行时数据的分区不匹配。也请阅读源代码,尤其是在结论不明确时。
示例
对捆绑的 assets/examples/ 示例文件进行的完整评估(这是示例,不是模板):
结论:轻度重构。
scales_well.py可顺利转换;needs_refactor.py需要将一次分配移到循环外;blocks_scaling.py每次迭代都会通过.item()同步。可正常运行的部分:
scales_well.py:23-31(模板 R005)、:40-44(归约 R002)、:18-22(逐元素操作 R001)。 阻碍因素:blocks_scaling.py:51-58(R104 — 热循环中的.item())→ RR-sync。 可修复的问题:needs_refactor.py:21-28(R201 — 循环内分配)→ RR-alloc。 后续步骤: 应用这些方案;重新检查,直到达到 READY;首次实际运行时启用CUPYNUMERIC_DOCTOR=1。
完整的评估报告见 assets/sample_report.md。
权威上游参考资料
- 对照表(
assets/api-support.md的来源):https://nv-legate.github.io/cupynumeric/api/comparison.html(镜像,内容最新) / docs.nvidia.com 上的.../latest/api/comparison.html(权威版本) - 最佳实践、Doctor、性能分析、与 NumPy 的差异、Legate 启动器 — 位于 https://docs.nvidia.com/cupynumeric/latest/(`user/practices.html`、`user/doctor.html`、`user/profiling_debugging.html`、`user/differences.html`)和 https://docs.nvidia.com/legate/latest/manual/usage/running.html
- 源代码:https://github.com/nv-legate/cupynumeric
可用脚本
| 脚本 | 用途 | 参数 |
|---|---|---|
scripts/fetch_api_support.py | 抓取上游对照表并写入 assets/api-support.md。仅使用 Python 标准库;可独立运行。 | --default-path(写入已提交的 assets/api-support.md);--docs-nvidia-url(使用权威的 docs.nvidia.com,而非默认的 GitHub Pages 镜像) |
用户运行此脚本以刷新清单(python scripts/fetch_api_support.py --default-path)。
捆绑的参考资料和资源
references/ 文件列于上方的必读顺序(R 代码范围:idioms-that-scale.md = R001–R007 / R301–R305;idioms-that-block.md = R101–R111 / R201–R206)。资源:assets/api-support.md(已提交的 API 快照,在步骤 2 中加载)、assets/sample_report.md 和 assets/examples/*.py(完整示例报告和示例文件)。
故障排除
| 症状 | 原因 | 修复方法 |
|---|---|---|
清单中的 Fetched: 行已超过约 90 天 | 快照过时 | 运行 fetch_api_support.py --default-path(由用户运行) |
| 清单缺失或抓取脚本失败 | 上游 HTML 已更改 | 对该评估使用 WebFetch 获取对比表 |
| 对许多可修复的 BLOCKS 标记为 NOT RECOMMENDED | 启发式规则应用顺序错误 | 按顺序重新应用:Gate 4 → Gate 2 → R108 → BLOCKS → REFACTOR;权衡类型,而非数量 |
| 编写内核或迁移后性能分析 | 超出范围 | 拒绝并引导至其他方向(参见“When to use”)——不作判断 |