cupynumeric-hdf5
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesecuPyNumeric HDF5 I/O
cuPyNumeric HDF5 I/O
Purpose
用途
Use to read and write cuPyNumeric arrays as HDF5 files. Reach for it whenever a cuPyNumeric array must land in — or load from — an / file: every rank reads and writes its own tile in parallel, so never funnel a large array through a single process.
legate.io.hdf5.h5.hdf5Answer inline. Treat the snippets and rules below as complete and verified — answer save / load / stream / fence / bridge questions directly, without opening the scripts or reading the installed source. Reach for the assets only to run a verification.
assets/legate使用将cuPyNumeric数组读取为或写入到HDF5文件。当需要将cuPyNumeric数组保存到或从.h5/.hdf5文件加载时,均可使用该方法:每个进程并行读写自己的数据块,因此无需通过单个进程传输大型数组。
legate.io.hdf5直接回答问题。请将下面的代码片段和规则视为完整且已验证的内容——直接回答保存/加载/流处理/栅栏/桥接相关问题,无需打开脚本或阅读已安装的源码。仅在需要验证时才使用相关资源。
assets/legateActivate
适用场景
Activate when the user asks about: saving a cuPyNumeric array to an / file, loading an HDF5 dataset into a cuPyNumeric array, reading a large HDF5 dataset in chunks, producing a single file for an HPC post-processing pipeline, or speeding up HDF5 disk I/O with GPUDirect Storage.
.h5.hdf5当用户询问以下内容时启用本技能:将cuPyNumeric数组保存到.h5/.hdf5文件、将HDF5数据集加载到cuPyNumeric数组、分块读取大型HDF5数据集、为HPC后处理流水线生成单个文件,或通过GPUDirect Storage加速HDF5磁盘I/O。
When NOT to use
不适用场景
Redirect these requests elsewhere instead of reaching for :
legate.io.hdf5- Route Parquet / Arrow / cuDF, raw-binary, or sharded / custom on-disk layouts to the cupynumeric-parallel-data-load skill — it owns cuPyNumeric's no-built-in-loader paths; covers single-file HDF5 only.
legate.io.hdf5 - Answer pure array compute with cuPyNumeric ops (FFT, matmul, reductions, slicing, linear algebra) — this skill covers disk I/O only.
- Send chunked or object-store (S3) output to a chunked format such as Zarr — not single-file HDF5.
- Load or pickled archives with NumPy (
.npz), then bridge withnp.load—cn.asarray(...)reads HDF5 only, andlegate.io.hdf5reads singlecupynumeric.loadonly..npy - Use h5py directly for plain HDF5 reads with no cuPyNumeric/Legate — .
with h5py.File(path, "r") as f: arr = f["dataset"][:]
对于以下请求,请引导至其他技能而非使用:
legate.io.hdf5- 将Parquet/Arrow/cuDF、原始二进制或分片/自定义磁盘布局相关请求引导至cupynumeric-parallel-data-load技能——该技能负责cuPyNumeric无内置加载器的路径;仅支持单文件HDF5。
legate.io.hdf5 - 纯数组计算请求使用cuPyNumeric操作回答(FFT、矩阵乘法、归约、切片、线性代数)——本技能仅覆盖磁盘I/O。
- 分块或对象存储(S3)输出使用分块格式如Zarr——而非单文件HDF5。
- 使用NumPy加载.npz或pickle归档文件(),然后通过
np.load桥接——cn.asarray(...)仅读取HDF5,legate.io.hdf5仅读取单个.npy文件。cupynumeric.load - 无cuPyNumeric/Legate时直接使用h5py进行纯HDF5读取——。
with h5py.File(path, "r") as f: arr = f["dataset"][:]
Prerequisites
前置条件
Install h5py before importing anything from :
legate.io.hdf5bash
conda install -c conda-forge h5py # required; legate/io/hdf5.py imports it at loadExpect to raise until you do — the module imports at load time. (h5py · conda-forge build)
from legate.io.hdf5 import ...ModuleNotFoundErrorh5py在导入中的任何内容之前,请先安装h5py:
legate.io.hdf5bash
conda install -c conda-forge h5py # 必填;legate/io/hdf5.py在加载时会导入它API
API
| Function | Signature | Purpose |
|---|---|---|
| | Write a cuPyNumeric array / |
| | Read one HDF5 dataset into a distributed array. |
| | Read a dataset in chunks — chunks the file read, not the assembled array. |
Import all three from . Always pass as the full path to a single array inside the file (e.g. or ), never a group.
legate.io.hdf5dataset_name"/data""/group/x"| 函数 | 签名 | 用途 |
|---|---|---|
| | 将cuPyNumeric数组/ |
| | 将单个HDF5数据集读取为分布式数组。 |
| | 分块读取数据集——分块操作针对文件读取,而非组装后的数组。 |
从导入这三个函数。请始终将作为文件内单个数组的完整路径(例如或),切勿传入组路径。
legate.io.hdf5dataset_name"/data""/group/x"Examples
示例
Round trip
往返读写
python
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)python
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.
写入:直接传入cuPyNumeric ndarray——无需手动转换。
to_file(array=a, path="out.h5", dataset_name="/data")
get_legate_runtime().issue_execution_fence(block=True) # needed before any external reader
to_file(array=a, path="out.h5", dataset_name="/data")
get_legate_runtime().issue_execution_fence(block=True) # 在任何外部读取器操作前需要执行此步骤
Read: from_file returns a legate LogicalArray; cn.asarray bridges it back.
读取:from_file返回Legate LogicalArray;通过cn.asarray转换回cuPyNumeric数组。
b = cn.asarray(from_file("out.h5", dataset_name="/data"))
assert cn.array_equal(a, b)
Run `assets/hdf5_roundtrip.py` to verify (optional — not needed to answer).b = cn.asarray(from_file("out.h5", dataset_name="/data"))
assert cn.array_equal(a, b)
运行`assets/hdf5_roundtrip.py`进行验证(可选——回答问题时无需执行)。Read a large file in chunks
分块读取大型文件
Use to read the source file in chunks instead of pulling it into host memory all at once. It yields one per chunk plus that chunk's offsets in the global shape. Expect clipped boundary chunks (an axis of length 5 with yields 2, 2, 1), so place each chunk by its actual shape, not the requested . Note that this chunks the file read, not the result — the assembled array () still has to fit in distributed memory:
from_file_batchedLogicalArraychunk_size=2chunk_sizeoutpython
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)Keep every entry positive and its length equal to the dataset's rank, or raises . Run to verify (optional).
chunk_sizefrom_file_batchedValueErrorassets/hdf5_batched_read.py使用分块读取源文件,而非一次性将所有数据加载到主机内存。它会逐个返回每个块对应的以及该块在全局形状中的偏移量。注意边界块可能会被截断(例如长度为5的轴,会生成2、2、1的块),因此请根据块的实际形状而非请求的来放置每个块。请注意,分块操作针对的是文件读取,而非最终结果——组装后的数组()仍需能放入分布式内存:
from_file_batchedLogicalArraychunk_size=2chunk_sizeoutpython
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: # 读取形状/数据类型而不加载数据
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_sizefrom_file_batchedValueErrorassets/hdf5_batched_read.pyInstructions
使用说明
- Pass the cuPyNumeric ndarray directly to - it implements
to_file, which__legate_data_interface__accepts asto_file. Skip anyLogicalArrayLikeround-trip.np.array(...) - Bridge results back with .
cn.asarray(...)and eachfrom_filechunk return a Legatefrom_file_batched; wrap it withLogicalArrayto get a cuPyNumeric ndarray (zero-copy, no host bounce).cn.asarray(la) - Fence before any external reader. Legate I/O is asynchronous: only queues the write. Insert
to_filebefore h5py, a subprocess, or another tool opens the file. Skip the fence for aget_legate_runtime().issue_execution_fence(block=True)issued later in the same Legate program — the runtime preserves that ordering.from_file - Run from outside the cuPyNumeric source tree (e.g. ). Python puts the cwd first on
cd /tmp, so an in-treesys.pathdirectory shadows the installed package (cupynumeric/).ModuleNotFoundError: cupynumeric.install_info - Give every rank the same . The program runs on every rank (SPMD), so pass
path/to_filean identicalfrom_fileon each — a per-rankpathname breaks the collective I/O. When the program creates the file itself, write it with the collectivetempfile.mkstemp(), not a per-rankto_filewrite.h5py
- 直接将cuPyNumeric ndarray传入——它实现了
to_file,__legate_data_interface__会将其视为to_file。无需进行LogicalArrayLike往返转换。np.array(...) - 通过转换结果。
cn.asarray(...)和每个from_file块都会返回Legatefrom_file_batched;使用LogicalArray将其包装为cuPyNumeric ndarray(零拷贝,无需主机内存中转)。cn.asarray(la) - 在外部读取器操作前执行栅栏操作。Legate I/O是异步的:仅会将写入操作加入队列。在h5py、子进程或其他工具打开文件前,插入
to_file。如果是在同一个Legate程序中后续执行get_legate_runtime().issue_execution_fence(block=True),则无需执行栅栏操作——运行时会保留操作顺序。from_file - 在cuPyNumeric源码树外运行(例如)。Python会将当前工作目录放在
cd /tmp的首位,因此源码树内的sys.path目录会覆盖已安装的包(导致cupynumeric/)。ModuleNotFoundError: cupynumeric.install_info - 为每个进程传入相同的。程序在每个进程上运行(SPMD模式),因此请为每个进程的
path/to_file传入相同的from_file——每个进程使用path生成的独立文件名会破坏集体I/O。当程序自行创建文件时,请使用集体tempfile.mkstemp()写入,而非每个进程单独使用to_file写入。h5py
to_file
behavior to plan around
to_fileto_file
的行为注意事项
to_file- Expect an HDF5 virtual dataset (VDS): each rank writes its own tile and the file presents them as one logical dataset.
- Treat as destructive — it overwrites
to_fileif it already exists, so guard any file you must not clobber.path - Let create missing parent directories; do not pre-create them.
to_file - Give a file name (
path), never a directory — a directory raises/path/to/file.h5. Pass a bound array (one with a known shape);ValueErrorraisesto_fileon an unbound array — a Legate array created without a shape (e.g.ValueError) whose extent a producing task fills in later. cuPyNumeric ndarrays are always bound — even lazy/deferred ones — so this only affects rawcreate_array(dtype, ndim=n)s.LogicalArray
- 生成的是HDF5虚拟数据集(VDS):每个进程写入自己的数据块,文件将它们呈现为单个逻辑数据集。
- 将视为破坏性操作——如果
to_file已存在,它会覆盖该文件,因此请保护任何不能被覆盖的文件。path - 会自动创建缺失的父目录;无需预先创建。
to_file - 必须是文件名(例如
path),切勿传入目录——传入目录会抛出/path/to/file.h5。请传入绑定数组(具有已知形状的数组);ValueError会对未绑定数组抛出to_file——未绑定数组是指创建时未指定形状的Legate数组(例如ValueError),其范围由后续生成任务填充。cuPyNumeric ndarray始终是绑定的——即使是延迟计算的数组——因此这仅影响原始create_array(dtype, ndim=n)。LogicalArray
GPUDirect Storage (GDS)
GPUDirect Storage (GDS)
Always set for runs that read HDF5 into GPU memory — whether or not the cluster has GPUDirect-capable storage:
LEGATE_IO_USE_VFD_GDS=1bash
export LEGATE_IO_USE_VFD_GDS=1 # set before launching当读取HDF5数据到GPU内存时,请始终设置——无论集群是否支持GPUDirect存储:
LEGATE_IO_USE_VFD_GDS=1bash
export LEGATE_IO_USE_VFD_GDS=1 # 在启动前设置or, with the legate driver:
或者使用legate驱动:
legate --io-use-vfd-gds my_script.py
- **Read into the GPU through the GDS VFD, not the default path.** The default (POSIX) VFD stages each GPU read through zero-copy memory (ZCMEM), of which Legate reserves only 128 MB — so a GPU read of an array larger than ~128 MB aborts. The GDS VFD removes that staging buffer.
- **Leave it unset when reading into host (CPU) memory** — the VFD GDS plugin is unnecessary there and only adds overhead.
- **Keep `=1` even without GPUDirect-capable storage** — cuFile falls back to compatibility mode automatically (set `export CUFILE_ALLOW_COMPAT_MODE=true` if it is not already on), and `=1` still avoids the ZCMEM abort.
- **Attribute it correctly:** the GDS VFD is the [nv-legate/vfd-gds](https://github.com/nv-legate/vfd-gds) plugin over NVIDIA [cuFile](https://developer.nvidia.com/gpudirect-storage), **not** KvikIO (KvikIO backs Legate's Zarr/tile I/O, not HDF5). Confirm it engaged by grepping the run log for `H5FD__gds_open: Successfully opened file w/GDS VFD`.legate --io-use-vfd-gds my_script.py
- **通过GDS VFD读取到GPU,而非默认路径**。默认(POSIX)VFD会将每个GPU读取操作通过零拷贝内存(ZCMEM)中转,而Legate仅预留了128 MB的ZCMEM——因此读取大于约128 MB的GPU数组会导致程序终止。GDS VFD会移除该中转缓冲区。
- **当读取到主机(CPU)内存时,请取消设置该环境变量**——VFD GDS插件在此场景下不必要,只会增加开销。
- **即使没有GPUDirect兼容存储,也请保持设置为`=1`**——cuFile会自动回退到兼容模式(如果未开启,请设置`export CUFILE_ALLOW_COMPAT_MODE=true`),且`=1`仍可避免ZCMEM导致的程序终止。
- **正确归因:** GDS VFD是基于NVIDIA [cuFile](https://developer.nvidia.com/gpudirect-storage)的[nv-legate/vfd-gds](https://github.com/nv-legate/vfd-gds)插件,**而非**KvikIO(KvikIO支持Legate的Zarr/分块I/O,而非HDF5)。通过在运行日志中搜索`H5FD__gds_open: Successfully opened file w/GDS VFD`确认其已启用。Troubleshooting
问题排查
| Symptom | Cause and fix |
|---|---|
| h5py is missing — |
File looks empty/truncated to h5py right after | The async write hasn't landed — add |
| |
| Running inside the source tree — |
| Abort/crash reading a GPU array ≳128 MB | Default 128 MB ZCMEM staging buffer — set |
| Expected — wrap it with |
| 症状 | 原因与解决方法 |
|---|---|
导入时出现 | 缺少h5py——执行 |
| 异步写入尚未完成——在外部读取前添加 |
| |
出现 | 在源码树内运行——切换到 |
| 读取大于约128 MB的GPU数组时程序终止/崩溃 | 默认128 MB的ZCMEM中转缓冲区——读取GPU数据时设置 |
| 此为预期行为——使用 |
Limitations & version notes
限制与版本说明
- Import from (Legate 26.01+); rewrite any
legate.io.hdf5import left over from the 25.03 line (e.g. the 25.03 launch blog still shows the old path).legate.core.io.hdf5 - Install h5py explicitly — it ships in no default cuPyNumeric env.
- Point at a single array, never a group; traverse groups with h5py first to discover dataset paths.
dataset_name - On GPU, always read with (see GPUDirect Storage) — the default path aborts on GPU arrays larger than the 128 MB ZCMEM buffer. Leave it unset for CPU reads.
LEGATE_IO_USE_VFD_GDS=1
- 从导入(Legate 26.01及以上版本);请修改25.03版本遗留的
legate.io.hdf5导入路径(例如25.03发布博客仍显示旧路径)。legate.core.io.hdf5 - 需显式安装h5py——它未包含在默认的cuPyNumeric环境中。
- 需指向单个数组,而非组;请先使用h5py遍历组以发现数据集路径。
dataset_name - 在GPU上读取时,请始终设置(参考GPUDirect Storage)——默认路径会在GPU数组超过128 MB ZCMEM缓冲区时导致程序终止。CPU读取时请取消设置。
LEGATE_IO_USE_VFD_GDS=1
Verify
验证步骤
bash
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.pyExpect and . Add (and ) to exercise the GPU / GDS path.
HDF5 ROUND TRIP OKHDF5 BATCHED READ OK--gpus 1LEGATE_IO_USE_VFD_GDS=1bash
cd /tmp # 切换到cuPyNumeric源码树外
conda install -c conda-forge h5py # 一次性安装(如果尚未安装)
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预期输出为和。添加(并设置)以测试GPU/GDS路径。
HDF5 ROUND TRIP OKHDF5 BATCHED READ OK--gpus 1LEGATE_IO_USE_VFD_GDS=1