cupynumeric-hdf5 について
Legate を介して HDF5 データセットを読み書きする cuPyNumeric 向けスキルです。分散環境での単一ファイル I/O と分割読み込みに対応し、同期や GPU 読み込みの要件も説明します。
主な機能
- 01分散配列を HDF5 仮想データセットとして書き込み
- 02HDF5 データセットを分散配列に読み込み
- 03データセットを分割して読み込み
- 04LogicalArray の結果を cuPyNumeric に変換
- 05GPU 読み込みで GDS VFD を使用
活用シーン
- 01HPC の後処理向けに分散配列を保存
- 02大規模な HDF5 データセットを分割読み込み
- 03大規模配列の GPU 読み込みでホスト経由の一時保存を回避
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nvidia/ skills --skill cupynumeric-hdf5インストール後、Claude Code で/cupynumeric-hdf5を入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
BENCHMARK.mdskill-card.mdskill.oms.sigassets/hdf5_batched_read.pyhdf5_roundtrip.pyevals/evals.json詳細
cuPyNumeric HDF5 入出力
目的
legate.io.hdf5 を使用して、cuPyNumeric 配列を HDF5 ファイルとして読み書きします。cuPyNumeric 配列を .h5/.hdf5 ファイルに保存する、またはそこから読み込む必要があるときに使用してください。各ランクが並列で独自のタイルを読み書きするため、大きな配列を単一プロセスに集約する必要はありません。
そのまま回答してください。 以下のスニペットとルールは完全かつ検証済みのものとして扱い、保存/読み込み/ストリーミング/同期/ブリッジに関する質問には、assets/ スクリプトを開いたり、インストール済みの legate のソースを読んだりせずに直接回答してください。検証を実行する場合に限り、assets を使用してください。
使用する場面
ユーザーから次のような質問があった場合に使用してください。cuPyNumeric 配列を .h5/.hdf5 ファイルに保存する、HDF5 データセットを cuPyNumeric 配列に読み込む、大きな HDF5 データセットをチャンク単位で読み込む、HPC の後処理パイプライン向けに単一ファイルを生成する、GPUDirect Storage で HDF5 のディスク I/O を高速化する。
使用しない場面
次のリクエストには legate.io.hdf5 を使わず、適切な方法を案内してください。
- Parquet/Arrow/cuDF、raw binary、またはシャード化/カスタムのオンディスク形式は、cupynumeric-parallel-data-load スキルに案内してください — cuPyNumeric に組み込みローダーがない形式を扱うのはこのスキルです。
legate.io.hdf5が扱うのは単一ファイルの HDF5 のみです。 - 純粋な配列計算には cuPyNumeric の演算を使用してください(FFT、行列積、リダクション、スライス、線形代数)— このスキルが扱うのはディスク I/O のみです。
- チャンク化された形式(Zarr など)には、チャンク化された出力やオブジェクトストレージ(S3)への出力を案内してください — 単一ファイルの HDF5 ではありません。
.npzや pickle 形式のアーカイブは NumPy(np.load)で読み込み、その後cn.asarray(...)でブリッジしてください —legate.io.hdf5が読み込むのは HDF5 のみで、cupynumeric.loadが読み込むのは単一の.npyのみです。- cuPyNumeric/Legate を使わない通常の HDF5 読み込みには h5py を直接使用してください —
with h5py.File(path, "r") as f: arr = f["dataset"][:]。
前提条件
legate.io.hdf5 から何かをインポートする前に h5py をインストールしてください。
conda install -c conda-forge h5py # required; legate/io/hdf5.py imports it at load
インストールするまでは from legate.io.hdf5 import ... が ModuleNotFoundError を発生させます。モジュールの読み込み時に h5py をインポートするためです。(h5py · conda-forge build)
API
| 関数 | シグネチャ | 目的 |
|---|---|---|
to_file | to_file(array, path, dataset_name) | cuPyNumeric 配列/LogicalArray を仮想データセット(VDS)として単一の HDF5 ファイルに書き込みます — 各ランクが独自のタイルを書き込みます。 |
from_file | from_file(path, dataset_name) -> LogicalArray | HDF5 データセットを分散配列に読み込みます。 |
from_file_batched | from_file_batched(path, dataset_name, chunk_size) -> Iterator[(LogicalArray, offsets)] | データセットをチャンク単位で読み込みます — チャンク化するのはファイルの読み込みであり、組み立て後の配列ではありません。 |
3 つすべてを legate.io.hdf5 からインポートしてください。dataset_name には、ファイル内の単一配列への完全なパス(例:"/data" または "/group/x")を必ず指定し、グループは指定しないでください。
例
往復処理
import cupynumeric as cn
from legate.core import get_legate_runtime
from legate.io.hdf5 import from_file, to_file
a = cn.arange(64, dtype=cn.float32).reshape(8, 8)
# Write: pass the cuPyNumeric ndarray straight in - no manual conversion.
to_file(array=a, path="out.h5", dataset_name="/data")
get_legate_runtime().issue_execution_fence(block=True) # needed before any external reader
# Read: from_file returns a legate LogicalArray; cn.asarray bridges it back.
b = cn.asarray(from_file("out.h5", dataset_name="/data"))
assert cn.array_equal(a, b)
検証するには assets/hdf5_roundtrip.py を実行してください(任意 — 回答に実行は不要です)。
大きなファイルをチャンク単位で読み込む
from_file_batched を使用すると、ソースファイル全体を一度にホストメモリへ読み込まず、チャンク単位で読み込めます。チャンクごとに 1 つの LogicalArray と、そのチャンクのグローバル形状におけるオフセットが返されます。境界のチャンクは指定サイズより小さくなることがあります(長さ 5 の軸で chunk_size=2 の場合、2、2、1 となります)。そのため、要求した chunk_size ではなく、実際の形状に基づいて各チャンクを配置してください。チャンク化されるのはファイルの読み込みであり、結果ではない点に注意してください。組み立て後の配列(out)は、引き続き分散メモリに収まる必要があります。
import h5py
import cupynumeric as cn
from legate.core import get_legate_runtime
from legate.io.hdf5 import from_file_batched
with h5py.File("big.h5", "r") as f: # read shape/dtype without loading data
shape, dtype = f["data"].shape, f["data"].dtype
out = cn.empty(shape, dtype=dtype)
for chunk, (r0, c0) in from_file_batched("big.h5", "data", chunk_size=(4096, 4096)):
out[r0:r0 + chunk.shape[0], c0:c0 + chunk.shape[1]] = cn.asarray(chunk)
get_legate_runtime().issue_execution_fence(block=True)
chunk_size の各要素は正の値とし、その長さはデータセットのランクと一致させてください。そうでない場合、from_file_batched は ValueError を発生させます。検証するには assets/hdf5_batched_read.py を実行してください(任意)。
手順
- cuPyNumeric ndarray をそのまま
to_fileに渡してください。これは__legate_data_interface__を実装しており、to_fileはLogicalArrayLikeとして受け取れます。np.array(...)を経由する変換は避けてください。 - 結果を
cn.asarray(...)で変換してください。from_fileとfrom_file_batchedの各チャンクは LegateLogicalArrayを返します。cn.asarray(la)でラップすると、cuPyNumeric ndarray を取得できます(ゼロコピーで、ホストメモリを経由しません)。 - 外部リーダーを使う前にフェンスを挿入してください。 Legate の I/O は非同期です。
to_fileは書き込みをキューに追加するだけです。h5py、サブプロセス、または別のツールでファイルを開く前に、get_legate_runtime().issue_execution_fence(block=True)を挿入してください。同じ Legate プログラム内で後から実行するfrom_fileにはフェンスは不要です。ランタイムが順序を維持します。 - cuPyNumeric のソースツリーの外から実行してください(例:
cd /tmp)。Python はカレントディレクトリをsys.pathの先頭に置くため、ツリー内のcupynumeric/ディレクトリがインストール済みパッケージを隠し、ModuleNotFoundError: cupynumeric.install_infoが発生します。 - すべてのランクに同じ
pathを指定してください。 プログラムはすべてのランクで実行される(SPMD)ため、各ランクで同一のpathをto_file/from_fileに渡してください。ランクごとに異なるtempfile.mkstemp()名を使うと、集合 I/O が機能しません。プログラム自身がファイルを作成する場合は、ランクごとのh5py書き込みではなく、集合的なto_fileで書き込んでください。
to_file の動作に関する注意点
- HDF5 の**仮想データセット(VDS)**が作成される想定です。各ランクがそれぞれのタイルを書き込み、ファイル上では単一の論理データセットとして表示されます。
to_fileは破壊的な操作として扱ってください。pathがすでに存在する場合は上書きされるため、上書きしてはいけないファイルには保護措置を講じてください。to_fileに不足している親ディレクトリを作成させてください。事前に作成しないでください。pathにはディレクトリではなくファイル名(/path/to/file.h5)を指定してください。ディレクトリを指定するとValueErrorが発生します。バインド済みの配列(形状が既知の配列)を渡してください。形状を指定せずに作成した Legate 配列(例:create_array(dtype, ndim=n))で、後続の生成タスクが範囲を設定するものなど、未バインドの配列を渡すと、to_fileはValueErrorを発生させます。cuPyNumeric ndarray は常にバインド済みです(遅延/延期評価のものも含みます)。そのため、これは生のLogicalArrayにのみ影響します。
GPUDirect Storage(GDS)
HDF5 を GPU メモリに読み込む実行では、クラスターに GPUDirect 対応ストレージがあるかどうかにかかわらず、必ず LEGATE_IO_USE_VFD_GDS=1 を設定してください。
export LEGATE_IO_USE_VFD_GDS=1 # set before launching
# or, with the legate driver:
legate --io-use-vfd-gds my_script.py
- デフォルトの経路ではなく、GDS VFD を通じて GPU に読み込んでください。 デフォルトの POSIX VFD は、GPU 読み込みのたびにゼロコピー・メモリ(ZCMEM)を経由します。Legate が予約する ZCMEM はわずか 128 MB なので、約 128 MB を超える配列を GPU に読み込むと異常終了します。GDS VFD はこのステージングバッファーを使用しません。
- ホスト(CPU)メモリに読み込む場合は、設定を解除してください。 その場合、VFD GDS プラグインは不要で、オーバーヘッドが増えるだけです。
- GPUDirect 対応ストレージがなくても
=1を維持してください。 cuFile は自動的に互換モードにフォールバックします(まだ有効でない場合はexport CUFILE_ALLOW_COMPAT_MODE=trueを設定してください)。また、=1によって ZCMEM の異常終了も回避できます。 - 正しく表記してください。 GDS VFD は、NVIDIA の cuFile 上で動作する nv-legate/vfd-gds プラグインであり、KvikIO ではありません(KvikIO は Legate の Zarr/タイル I/O を支えますが、HDF5 には使われません)。実際に有効になったことは、実行ログで
H5FD__gds_open: Successfully opened file w/GDS VFDを検索して確認してください。
トラブルシューティング
| 症状 | 原因と対処方法 |
|---|---|
インポート時に ModuleNotFoundError: No module named 'h5py' が発生する | h5py がありません — conda install -c conda-forge h5py を実行してください。 |
to_file の直後、h5py でファイルを開くと空または途中で切れているように見える | 非同期書き込みが完了していません — 外部から読み取る前に get_legate_runtime().issue_execution_fence(block=True) を追加してください。 |
to_file で ValueError が発生する | path がディレクトリです — results/data.h5 のようにファイルパスを指定してください。 |
ModuleNotFoundError: No module named 'cupynumeric.install_info' が発生する | ソースツリー内で実行しています — cd /tmp(リポジトリ外の任意のディレクトリ)を実行してください。 |
| ≳128 MB の GPU 配列を読み取ると異常終了またはクラッシュする | デフォルトの 128 MB ZCMEM ステージングバッファが原因です — GPU から読み取る場合は LEGATE_IO_USE_VFD_GDS=1 を設定してください。 |
from_file が LogicalArray(...) を返す | これは想定どおりです — cn.asarray(...) でラップしてください。 |
制限事項とバージョンに関する注意
legate.io.hdf5からインポートしてください(Legate 26.01 以降)。25.03 系で使われていたlegate.core.io.hdf5のインポートが残っている場合は書き換えてください(たとえば、25.03 のローンチブログには古いパスが記載されています)。- h5py は明示的にインストールしてください — デフォルトの cuPyNumeric 環境には含まれていません。
dataset_nameには単一の配列を指定し、グループは指定しないでください。グループをたどってデータセットのパスを特定するには、最初に h5py を使用してください。- GPU では、常に
LEGATE_IO_USE_VFD_GDS=1を設定して読み取ってください(GPUDirect Storage(GDS)を参照)。デフォルトの方法では、128 MB の ZCMEM バッファを超える GPU 配列を読み取ると異常終了します。CPU から読み取る場合は、この環境変数を設定しないでください。
検証
cd /tmp # outside the cupynumeric source tree
conda install -c conda-forge h5py # one-time, if not already present
LEGATE_CONFIG="--cpus 4" LEGATE_AUTO_CONFIG=0 python <skill>/assets/hdf5_roundtrip.py
LEGATE_CONFIG="--cpus 4" LEGATE_AUTO_CONFIG=0 python <skill>/assets/hdf5_batched_read.py
HDF5 ROUND TRIP OK と HDF5 BATCHED READ OK が表示されることを確認してください。GPU/GDS の経路をテストするには、--gpus 1(および LEGATE_IO_USE_VFD_GDS=1)を追加してください。