Rerun:用冻结 Manifest 构建 RerunMapDataset,跳过实时扫描加速多模态数据训练
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
本文为 Rerun 0.37 版本变更日志中 "RerunMapDatasetcan be built from a manifest" 这一特性的技术详解:讲解RerunMapDataset.from_manifest()如何通过冻结的Manifest跳过构建期的实时目录扫描与取数期的关键帧查找,从而加速基于目录服务器(catalog server)的 map-style 训练数据加载,并说明它与RerunIterableDataset.from_manifest在样本顺序语义上的关键差异,帮助你在 PyTorchDataLoader生态中正确选择两条加载路径。
背景:map-style 数据集的两类构造成本
RerunMapDataset是 Rerun 实验性 DataLoader 中由目录服务器支撑的 map-style 数据集,支持按全局索引随机访问,因此可以配合 PyTorch 的采样器生态(DistributedSampler、WeightedRandomSampler、SubsetRandomSampler等)使用,打乱与跨 worker 分片由DataLoader的 sampler 驱动。其类文档见 RerunMapDataset 定义。
在引入 Manifest 机制之前,以常规方式构造RerunMapDataset(source, index, fields, ...)需要付出两笔成本:
- 构建期实时扫描(live scan):构造函数会调用
SampleIndex.build(source, index, fields, ...)向目录服务器探测完整样本空间(见 构造函数实现)。数据集中 segment 越多、实体越大,这一步的往返查询越昂贵; - 取数期关键帧查找(per-batch keyframe lookup):每次
__getitems__对一组索引,需要先_locate_samples定位样本、再_fetch_prior_keyframes向服务器查询每个字段此前最近的关键帧,然后才能构建解码目标(见 非 Manifest 路径)。对视频这类稀疏关键帧字段,这是每批次都要重复的服务器往返。
Manifest机制的价值正在于此:它把一次经过校验的采样结果(验证过的样本集合、每个字段的冻结解码区间)固化成一个 Parquet 文件,之后的训练可以只读这个"快照",而不是重新探测线上目录。
API:RerunMapDataset.from_manifest
变更日志给出的签名与用法为:
manifest = Manifest.from_parquet("epoch.parquet") dataset = RerunMapDataset.from_manifest(manifest, source, fields) loader = DataLoader(dataset, batch_size=8, sampler=DistributedSampler(dataset))参数语义(见 from_manifest 文档与实现):
| 参数 | 类型 | 说明 |
|---|---|---|
manifest | Manifest | 冻结的 manifest,提供验证过的样本集合与冻结解码区间。可用Manifest.from_parquet(path)从磁盘加载,num_rows直接从 Parquet footer 读取、无需加载数据行(见 Manifest 实现) |
source | DataSource | 实时的目录连接。Manifest 只记录字段的 spec(规格),不记录解码器对象本身,所以实时连接与解码器必须在调用时提供 |
fields | dict[str, Field] | 以字段名为键的解码器映射 |
decode_threads | int \| None | 每个DataLoaderworker 内并发解码的字段数,默认由_resolve_decode_threads根据字段数推导 |
Manifest只能通过Manifest.generate()或Manifest.from_parquet()创建,直接实例化会抛出TypeError(见 create 限制),这保证了"冻结"语义:manifest 一旦生成,其样本集合与解码区间不再漂移。
源码级原理:两处被跳过的服务器往返
从源码结构看,from_manifest与常规构造的差异集中在两个层面:
1. 构造期不再构建完整样本索引。常规路径通过SampleIndex.build(source, index, fields, ...)向服务器探测全量样本空间;而from_manifest路径中:
# Query construction only needs the grid step / dtype, not the full sample space. self._sample_index = SampleIndex([], ns_per_sample=meta.ns_per_sample, ns_dtype=meta.ns_dtype)它只从manifest.metadata取出index_name、ns_per_sample、ns_dtype这些构建查询所需的网格参数,用一个空样本索引替代实时扫描(见 from_manifest 实现)。数据集长度同样直接取 manifest 的行数:__len__在self._manifest is not None时返回self._manifest.num_rows(len实现)。
2. 取数期不再做关键帧查找。__getitems__中 Manifest 分支直接走:
rows = self._manifest.to_arrow().take(indices) targets = targets_from_rows(rows, fields=self._fields, sample_index=self._sample_index)即从 manifest 的 Arrow 表中按全局索引take出预解析好的行,再由targets_from_rows重建解码目标(见 Manifest 取数分支)。相比之下,非 Manifest 分支需要_locate_samples+_fetch_prior_keyframes两阶段服务器查询(非 Manifest 分支)。随后两条路径共用同一套"取数—索引—解码"流水线:_build_query_plans→_fetch_queries_parallel→_index_fetched_block→_resolve_decode_requests_in_block→_decode_iter,保证解码语义完全一致。
另外,__getitems__是DataLoader在多索引请求时自动调用的批量接口(存在即优先于逐个__getitem__),因此每个 batch 仍然只产生一次服务器往返,Manifest 只是把往返的内容从"发现关键帧"收敛为"按冻结区间取数"。
关键语义差异:样本顺序不重放
这是该特性最容易被误用的地方,变更日志与源码 docstring 中都以醒目方式强调:
The manifest's recorded order isnotrespected here. Ordering and cross-worker sharding stay with the
DataLoader's sampler.
即 map-style 的from_manifest不重放 manifest 中记录的样本顺序:manifest 在这里只提供"哪些样本是有效的、每个字段解码哪个区间",而样本以什么顺序、被哪个 worker 消费,完全交给 sampler。因此:
- 如果你用
DistributedSampler分片训练,Manifest 路径与 Iterable 路径产出的样本集合相同,但逐样本顺序不可互相比对; - 如果你的训练要求可复现、可断点续训(严格复现某次 manifest 记录的采样运行),应改用
RerunIterableDataset.from_manifest(manifest, source, fields)。它按 manifest 冻结的顺序、分片与解码区间重放样本(顺序、分片、解码区间全部来自 manifest,见 IterableDataset.from_manifest 文档,以及_iter中 manifest 分支的yield from self._iter_manifest()(迭代入口))。
两者可对照如下:
| 维度 | RerunMapDataset.from_manifest | RerunIterableDataset.from_manifest |
|---|---|---|
| 随机访问 | 支持,按全局索引__getitem__ | 不支持,顺序流式产出 |
| 采样器生态(shuffle/分布式/加权) | 交给DataLoadersampler | 内部按 manifest 冻结的顺序与分片重放 |
| 是否复现 manifest 记录的运行顺序 | 否 | 是 |
| 典型用途 | 需要DistributedSampler/子集采样的常规训练 | 可复现、可断点续训的训练 |
| 共同性能收益 | 跳过构建期 live scan 与取数期关键帧查找 | 同左 |
使用前提与注意事项
- Manifest 与源数据的一致性:manifest 固化的是生成时刻的样本集合与解码区间。若数据集内容发生变化(实体删除、字段缺失),manifest 路径不会重新校验线上状态;变更日志中同时收录的相关条目指出 Manifest 重放保持严格语义——若某个被记录为必需的字段无法再解析,迭代会直接报错并要求用户重新生成 manifest,而不是静默改变冻结的样本顺序(见 0.37 变更日志)。
- 视频数据集的配套优化:同一版本还引入了 manifest 生成提速——生成时不再扫描
VideoStream:sample时间戳,避免构建 manifest 时传输昂贵的已编码视频数据(见 变更日志条目),与本文的"构建期免扫描"共同覆盖了 manifest 生命周期两端的成本。 - 实验性 API:
RerunMapDataset、Manifest等位于rerun.experimental.dataloader包下,行为与命名可能随版本调整,生产使用建议锁定 Rerun 版本。 - 更完整的训练数据加载工作流(
DataSource、Field、解码器、shuffle 策略等)参见 Rerun 官方 howto 文档 dataloader.md。
相关源码与文档索引
- 变更日志原文(已合并条目):changeset-0-37.md 中 RerunMapDataset can be built from a manifest
- map-style 数据集实现:_map_dataset.py
- iterable 数据集实现:_iterable_dataset.py
- Manifest 实现:manifest/_manifest.py
- 训练数据加载 howto:dataloader.md
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考