cupynumeric-migration-readiness について
cuPyNumeric への移植前に、既存の NumPy コードを読み取り専用で評価するスキルです。スケーリング特性、API 対応状況、阻害要因、リファクタリング要件を分類し、構造化したレポートを作成します。
主な機能
- 01読み取り専用のソース確認
- 02NumPy の記述パターンを分類
- 03API サポート一覧との照合
- 04構造化された移行判定と所見
- 05リファクタリング手順の提案
活用シーン
- 01移植前の GPU 適性評価
- 02スケーリングを妨げる NumPy 記述の発見
- 03cuPyNumeric 向け改修の計画
- 04API 互換性と移行コストの確認
インストール
コマンドをコピーしてターミナルで実行します。
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 スタックでどの程度スケールすると見込まれるかを分類し、付属の 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 と判定してください。これは評価結果であり、対応を断るケースではありません。
手順
以下の 5 つのステップを順番に実行してください。ユーザーのコードを読み、意味に基づいて検討してください。一度きりの文章による判定を出してはいけません。
Step 1 — コンテキストを収集する
コードを調査する前に情報を聞き取ります。以下の各項目には一般的なワークロードに合わせたデフォルト値があります。ユーザーから具体的な情報が示されていない場合はデフォルトを使用し、質問への回答を待って作業を止めないでください。
- ソースの場所。 パスが指定されていない場合は、現在の作業ディレクトリをデフォルトにします。
- 実行時のホットパス配列のおおよそのサイズ。 デフォルトは 3,000 万〜5,000 万要素です。ユーザーの数値(またはこのデフォルト)を Gate 2 の段階に当てはめます(GPU あたり 65K が下限、単一 GPU で実際に速度向上する目安は 1,000 万以上、マルチ GPU では 1 億以上)。
- 対象ハードウェア。 デフォルトは単一ノードの GPU 1〜4 基です。マルチノードを想定する前に確認してください。CPU のみで実行する場合は、FBMEM の代わりにノードあたりの RAM について尋ねます。
- 主な計算パターン。 ステンシル/GEMM/モンテカルロ/リダクション/SciPy を含む混合処理です。ユーザーにパターンを挙げてもらいます。挙げられない場合は、Step 3 でコードから推測します。
評価の冒頭に、適用したデフォルト値を明記し、ユーザーが訂正できるようにしてください。値を特定できない場合は、その旨を明確に伝え、定性的な評価のみを進めます。上記のデフォルト以外の数値を捏造してはいけません。
ステップ 2 — API サポートマニフェストを読み込む
上流の NumPy と cuPyNumeric の比較表をコミットしたスナップショットである assets/api-support.md を読みます。コードが呼び出す NumPy API ごとに該当行を探し、先頭の記号を確認します。
✓✓ numpy.X— 実装済みで、マルチ GPU で動作します(最適な経路です)。✓ numpy.X— 実装済みですが、シングル GPU/CPU 専用です(マルチノードでは注意が必要です)。🟡 numpy.X — <note>— 部分的にサポートされています。注記を確認してください。✗ numpy.X— cuPyNumeric の分散実行経路では実装されていません。呼び出し時の挙動はバージョンによって異なります(サポート対象外の API の一部はホスト NumPy にフォールバックし、ほかは例外を発生させます)。いずれにしても、ホットパスでの使用は移行を妨げます。ホスト NumPy へのサイレントなフォールバックが起きるとユーザーに約束してはいけません。
Fetched: 行の日付が約 90 日以上前の場合は、スナップショットを更新します。利用可能なスクリプトのセクションを参照してください。
ステップ 3 — コードを意味的に読み取る
references/idioms-that-scale.md と references/idioms-that-block.md(詳しい根拠と R コードはこちら)に照らし合わせて、ユーザーのファイルを Read と Grep で調べ、配列演算の各箇所を分類します。正規表現だけに頼らず、意味を読み取ってください。問題を指摘する前に、arr が cupynumeric 配列(または cupynumeric にエイリアスされた np.*)に由来することを確認し、そのアクセスがホットループ内にあるかを確認します。次のルールを適用してください。
- 要素ごとのループを指摘します(
for i in range(n): arr[i] = ...)。ベクトル化された本体を持つエポック/ステップ/ファイルのループは問題ありません。両者を区別してください。 - スカラー同期を指摘します — ホットループ内で 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)は許容します(shape の参照です。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、
--gpus Nに対する RNG の構成。 - API サポートの不足 — コードが呼び出している API のうち、マニフェストによると未実装、またはシングル GPU のみ対応のもの。
- 判定フレームワークの要約 —
references/decision-framework.mdのゲート 1~6 を合格/不合格/不確実で示してください。 - 推奨する次の手順 — どのレシピを先に適用するか、最初に一つのモジュールを移植するかどうか、cuPyNumeric Doctor に相談するタイミング。
8 つのセクションすべてを必ず記載してください。判定が READY または NOT RECOMMENDED の場合も同様です。空のセクションには、1 行で 「このコードには該当なし」 または 「該当なし — 判定を参照」 と記載してください。見出しを省略しないでください。見出しはレポートの採点における構造上の要件です。実例については 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 を有効にして実行し、出力で確認すべき点は以下のとおりです。」で評価を締めくくってください。
判定フレームワーク
スコアではなく、見つかった項目の種類から判定を定性的に割り当てます。
| 判定 | 条件 | 対応 |
|---|---|---|
| READY | BLOCKS なし、REFACTOR が少数またはなし | インポートを置き換え、ベンチマークを実施します |
| LIGHT REFACTOR | レシピで修正可能なパターンが少数(R201~R206)、または単純な BLOCKS が 1~2 件 | refactor-recipes.md のレシピを 1~3 件適用し、READY になるまで再確認します |
| SIGNIFICANT REFACTOR | ホットパスに複数の BLOCKS がある、または R108(mpi4py)が 1 件でもある — 除外ではなく書き換えが必要です | 実プロジェクトでは、モジュールあたり 1~3 エンジニア週を見込みます |
| NOT RECOMMENDED | 該当する失敗は 2 種類のみです:Gate 2(配列が 65,536 要素の下限未満)または Gate 4(計算パターンが不適切)。BLOCKS が多数あっても、この判定にはなりません | 先に構造を変更するか、別のランタイムを使用します |
以下を順に適用します。最初に該当したものを採用します。
- Gate 4 に失敗(sparse / graph / ML / sequential / string)→ NOT RECOMMENDED。
- Gate 2 に失敗(ホットパスの配列が GPU あたり 65,536 要素未満で、現実的なバッチ処理の手段がない)→ NOT RECOMMENDED。
- R108(
mpi4py)が1 件でもある → SIGNIFICANT REFACTOR(コストとなるのは並列処理レイヤーの書き換えであり、除外ではありません)。 - ホットパス全体に 複数の BLOCKS(R101~R111)がある → SIGNIFICANT REFACTOR(件数が増えてもこれ以上の判定にはなりません — 各 BLOCKS には文書化されたレシピがあります)。
- レシピで修正可能な BLOCKS が 1~2 件(例:R101~R104 の要素ループ/同期)→ LIGHT REFACTOR。
- REFACTOR パターンのみ(R201~R206)→ LIGHT REFACTOR。レシピに沿った機械的な修正で対応できます。
- BLOCKS も REFACTOR もない → READY。
- ホットパスで使用する API がマニフェストにない → 1 段階下げます(SIGNIFICANT は SIGNIFICANT のままで、NOT RECOMMENDED にはなりません)。単一 GPU 専用 API が問題になるのはマルチノードの場合のみです。
件数ではなく、見つかった項目の種類を重視してください。 ホットループ内の R101 1 件は R001 の 10 件より重大です。R001 がもたらすはずだったスケーリングを損なうためです。一方、BLOCKS が多数あって R108 もある場合でも、判定は依然として SIGNIFICANT であり、NOT RECOMMENDED ではありません — 各段階はエンジニアリングコストを示すもので、絶望度を示すものではありません。NOT RECOMMENDED となるのは、サイズまたは計算パターンの失敗がある場合です。フレームワーク全体については、references/decision-framework.md を参照してください。
スケーリングするものと妨げになるもの(一目で確認)
- SCALES(そのまま使用) — ベクトル化された要素単位の演算、リダクション、matmul / einsum、
np.where、GPU あたりのサイズが大きいステンシルのスライスarr[1:-1, 1:-1]、out=、ブールマスクによるインデックス指定。 - BLOCKS(移行前に取り除く) — 要素ループ、
np.vectorize、for row in arr、ホットループ内の.item()/.tolist()/bool(arr)、ループ内でリダクションを行うif/while、arr[::2]、dtype=object、mpi4py、order=、min/max/sum(arr)。 - REFACTOR(レシピを適用) — ループ内でのメモリ割り当て、ループ内での
x = x + yによる再束縛、ループ内でのvstack/hstack/concatenate、np.nonzero()とインデックス指定の組み合わせ、diag/flip/flattenのビュー変更、ホットループ内のreshape。 - INFO(コストに関する注記であり、妨げにはなりません) — 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 は実行しません。 ランタイムは不要です。これは移植前のチェックです。実際の高速化の測定は、移行後に行います。
- リファクタリング後のコードを自動生成しません。 変更箇所を特定してレシピを示します。適用するのはユーザー(または後続のエージェント)です。
- ワークロードをプロファイルしません。 実行時の測定には
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(既定の GitHub Pages ミラーの代わりに、正規版の docs.nvidia.com を使用します) |
ユーザーはこれを実行してマニフェストを更新します(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 します |
| 修正可能な BLOCK が多いにもかかわらず NOT RECOMMENDED と判定される | ヒューリスティクスの適用順が間違っています | 順序を適用し直します:Gate 4 → Gate 2 → R108 → BLOCKS → REFACTOR。件数ではなく、種類を考慮します |
| カーネルの作成または移行後のプロファイリング | 対象範囲外です | 対応を断り、「使用するタイミング」を案内します — 判定は行いません |