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使用来读写以HDF5文件存储的cuPyNumeric数组。当需要将cuPyNumeric数组保存到/文件或从中加载时,均可使用该工具:每个进程(rank)会并行读写自己的数据块,因此无需通过单个进程传输大型数组。
legate.io.hdf5.h5.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数组保存到/文件、将HDF5数据集加载到cuPyNumeric数组、分块读取大型HDF5数据集、为HPC后处理流水线生成单个文件,或通过GPUDirect Storage加速HDF5磁盘I/O。
.h5.hdf5When 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 - 纯数组计算请求(如FFT、矩阵乘法、归约、切片、线性代数),请使用cuPyNumeric运算处理 — 本技能仅覆盖磁盘I/O场景。
- 分块或对象存储(S3)输出,请使用Zarr等分块格式 — 不要使用单文件HDF5。
- 或pickle归档文件,请使用NumPy加载(
.npz),再通过np.load转换 —cn.asarray(...)仅读取HDF5文件,而legate.io.hdf5仅读取单个cupynumeric.load文件。.npy - 未搭配cuPyNumeric/Legate的纯HDF5读取需求,请直接使用h5py — 示例代码:。
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 # required; legate/io/hdf5.py imports it at load如果未安装h5py,执行会触发 — 该模块在加载时会导入h5py。(h5py · conda-forge构建版)
from legate.io.hdf5 import ...ModuleNotFoundErrorAPI
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.
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
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.
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)
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: # 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_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分块都会返回Legate的from_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 ndarrays始终是绑定的——即使是延迟计算的数组也是如此——因此这仅会影响原始的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 # set before launchingor, with the legate driver:
or, with the legate driver:
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)——默认路径在读取大于128 MB ZCMEM缓冲区的GPU数组时会导致程序终止。读取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 # 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预期会输出和。添加(以及)可测试GPU/GDS路径。
HDF5 ROUND TRIP OKHDF5 BATCHED READ OK--gpus 1LEGATE_IO_USE_VFD_GDS=1