如何在 NeMo Lhotse 数据加载中启用索引模式实现训练精确断点恢复
2026/9/14 16:52:11 网站建设 项目流程

如何在 NeMo Lhotse 数据加载中启用索引模式实现训练精确断点恢复

【免费下载链接】SpeechA scalable generative AI framework built for researchers and developers working on Large Language Models, Multimodal, and Speech AI (Automatic Speech Recognition and Text-to-Speech)项目地址: https://gitcode.com/GitHub_Trending/nem/Speech

用 Lhotse 数据加载器跑 NeMo ASR 训练时,数据流是无限的(没有传统意义的 epoch 边界),默认情况下断点恢复要走 Lhotse 的_fast_forward()重放——把 checkpoint 之前消费过的 batch 从头回放一遍(复杂度 O(N),N 是已消费的 batch 数)。启用索引模式indexed: true)并配合use_stateful_dataloader: true后,NeMo 会把整个数据加载管线(sampler 随机数状态、bucket 分配器状态、每个数据源的迭代游标、每个 worker 的预取队列)以 O(1) 的方式写入 checkpoint 并在恢复时精确还原,不再从 epoch 起点重放。

本文给出完整操作路径:构建.idx索引副档 → 在数据加载配置中开启两个开关 → 按恢复契约重启训练 → 用仓库自带脚本核对恢复进度。完整细节见 Lhotse Dataloading 文档。

前提条件:先确认你的数据满足索引模式要求

索引模式不是所有输入都支持。以下条件来自文档,不满足任一项就不要启用:

  • 输入类型受限。以下input_cfg类型支持indexed: true,且要求每个数据文件旁边都有.idx副档:nemo/nemo_tarred(JSONL manifest 需要manifest.json.idx,每个音频 tar 需要shard.tar.idx)、lhotse纯 JSONL、lhotse_sharparquet(不需要副档,但文件必须带 row-group 统计信息)、txt_jsonlmultimodal_conversationshare_gptshare_gpt_webdatasettxttxt_pair只支持流式读取,无法索引。
  • 文件必须未压缩.jsonl.gz.tar.gz等压缩文件只能流式读取,indexed: true要求可 seek 的未压缩文件;文档建议索引前先解压或重写。
  • 存储后端要支持索引读取与写入。本地文件系统开箱即用;对象存储(S3 等)和 AIStore 也可以,但.idx默认写在数据文件旁边,存储必须允许在该位置写入,否则要先在本地构建索引再上传。
  • 与部分选项互斥indexed: truenemo/nemo_tarred上的extra_fieldsslice_length不兼容——这两个选项会改写或扩展 cut,没有稳定索引,需要的话先在离线阶段预处理 manifest。

第一步:为数据文件构建 .idx 索引副档

仓库提供了批量脚本 build_indexes.py。它接收你的input_cfgYAML(支持嵌套group条目和条目内再引用其他 YAML),自动发现其中引用的所有 JSONL/tar 文件并逐一构建索引。副作用是只新增.idx文件,不修改任何数据文件;已有且非空的.idx会被跳过。

# 先把路径换成你实际的 input_cfg YAML 位置 # 预览将构建哪些索引,不写任何文件 python scripts/dataloading/build_indexes.py --dry-run path/to/input_cfg.yaml # 实际构建(默认 4 个并行 worker) python scripts/dataloading/build_indexes.py path/to/input_cfg.yaml # 已有索引也要重建 / 提高并行度 python scripts/dataloading/build_indexes.py --force --workers 16 path/to/input_cfg.yaml

构建失败会逐条打印[FAIL] <path>并以非零码退出;成功时按进度打印built N/M (xx%)心跳和最终汇总。

如果数据在 NFS、S3 等慢速或只读共享存储上,用--indexes-root把索引写到本地快速磁盘的镜像目录(目录结构镜像数据文件布局),而不是写在数据旁边:

python scripts/dataloading/build_indexes.py \ --indexes-root /scratch/idx path/to/input_cfg.yaml

也可以不用这个脚本,直接用 Lhotse CLI 逐文件构建,两种方式等价:

lhotse index jsonl path/to/cuts.jsonl lhotse index tar path/to/shard.tar lhotse index shar path/to/shar_dir/

第二步:在数据加载配置中开启索引模式

在实验 YAML 的train_ds顶层加两个开关即可。顶层的indexed: true会通过read_dataset_configpropagate_attrs级联传播到所有嵌套的input_cfg组,单个顶层标记就覆盖整条管线(个别数据源仍可按需单独覆盖):

model: train_ds: # 顶层开关:对下方所有数据源启用索引式精确恢复 indexed: true use_stateful_dataloader: true sample_rate: 16000 num_workers: 4 seed: 42 shard_seed: 42 # bucketing 等其余数据加载参数与平常一样,不受影响 use_bucketing: true num_buckets: 30 batch_duration: 1100 quadratic_duration: 30 input_cfg: - type: nemo_tarred manifest_filepath: /data/asr/manifest__OP_0..127_CL_.jsonl tarred_audio_filepaths: /data/asr/audio__OP_0..127_CL_.tar weight: 0.7 - type: lhotse cuts_path: /data/extra/cuts.jsonl weight: 0.3

(以上为文档给出的示例配置,路径换成你自己的数据。)

两个开关的作用:

  • indexed: true(默认False):让每个 adapter 走 Lhotse 的索引 manifest 路径,获得 O(1) 随机访问和基于 graph token 的精确恢复。对纯 JSONLcuts_path输入,它转发给CutSet.from_file(path, indexed=...);显式设为true时若缺少.idx会直接报错,这有助于尽早暴露漏建索引的问题。
  • use_stateful_dataloader: true(默认False):把 PyTorchDataLoader换成torchdata.stateful_dataloader.StatefulDataLoader,使每个 worker 的迭代器状态被写进 checkpoint,恢复时精确还原。与indexed: true搭配即得到完整的 O(1) 恢复。

如果第一步用了--indexes-root把索引导到了镜像目录,这里要对应设置indexes_root,运行时按<indexes_root>/<去掉协议前缀的数据路径>.idx查找索引,例如/shared/data/asr/manifest_0.jsonl -> /scratch/idx/shared/data/asr/manifest_0.jsonl.idx。该设置同样会级联到所有嵌套条目。

第三步:按恢复契约重启训练

文档给出的恢复契约(use_stateful_dataloader: true时):

  1. Lightning 的 checkpoint 会在 dataloader 键下保存完整的 Lhotse 迭代器图状态;
  2. 恢复后各迭代器位置直接前进到保存时的位置,不从位置 0 重放
  3. 已恢复状态待处理期间set_epoch是空操作,训练继续同一个 epoch 而不是重新开始;
  4. num_workersworld_size在保存与恢复之间必须一致——这是StatefulDataLoader的硬性要求,恢复时用与训练时相同的 worker 数和 GPU 数。

不启用索引模式时,管线退回 Lhotse 的_fast_forward()重放(O(N)),且只对num_workers一致性有要求,world_size不需要完全匹配。

验证恢复是否正确

仓库提供了两个只读/无副作用的核对工具。

核对 checkpoint 里的数据加载进度。analyze_resumable_checkpoint.py 从 checkpoint 中读出train_dataloader_per_rank状态,回答两个问题:混合数据中每个叶子数据源推进到了多少(总利用率、已完成 epoch 数、当前 epoch 进度百分比),以及实际消费比例与目标 blend 权重的偏差。它是只读的,不修改 checkpoint、索引或配置:

# --checkpoint 可为 checkpoint 文件、目录或 eval-step-N 目录; # --config 提供训练 YAML 以解析 blend 权重和数据源名称(索引副档在镜像目录时加 --indexes-root) python scripts/dataloading/analyze_resumable_checkpoint.py \ --checkpoint path/to/checkpoint \ --config path/to/train.yaml \ --output-dir /tmp/progress_summary

默认输出 Markdown 表格;--output-dir会同时写出summary.jsonsummary.mdsummary.csv

端到端验证精确恢复。validate_dataloader.py 按训练代码相同的入口get_lhotse_dataloader_from_config构建数据加载器,但挂在一个 no-op 的CutIdDataset上,逐 batch 把cut.id落成 JSONL,分三个阶段:baseline(从全新数据加载器迭代 N 个 batch,在--checkpoint-at处保存state_dict())、resumed(加载保存的状态继续迭代)、groundtruth(单 rank 穷举全部 cut)。由下游的 consolidate.py 把恢复后的窗口与 baseline 尾部做 diff,确认逐 batch 一致:

torchrun --standalone --nnodes=1 --nproc-per-node=4 \ scripts/dataloading/validate_dataloader.py \ --config 0909-en-only-id2.yaml \ --data-blend-dir /lustre/.../data_blends/ord \ --output-dir validation_out \ --phase baseline --run-idx 0 \ --steps 200 --checkpoint-at 100

(命令为脚本文档中的示例,--config指向的 YAML 需带有data.train_ds顶层结构,--data-blend-dir用于替换配置里的${data_blend_dir};后续resumed阶段再指定--state-dir指向保存的state_rank_NNN.pt。)

常见坑与限制

文档列出的、与索引模式直接相关的坑:

  1. 压缩文件无法索引.jsonl.gz/.tar.gz只能流式读取,开启indexed: true前先解压或重写。
  2. 恢复时num_workers/world_size不匹配:精确恢复要求两者与保存时一致;只有非索引的重放式恢复对num_workers的要求宽松一些。
  3. extra_fields/slice_lengthindexed: true互斥,需要它们就先离线预处理 manifest。
  4. 分片很多的数据集上,散落的大量.idx副档可能让启动阶段成为元数据瓶颈。文档给出可选进阶方案:先把副档构建好(可用--indexes-root集中存放),再用 convert_indexes_to_idxpack.py 把每个数据源的副档打包成一个.idxpack,运行时在配置里设置index_pack_root并在对应的外层input_cfg条目上声明index_pack。转换不重扫源文件;源数据、分片顺序或副档变化后必须重建 pack。
  5. 并行度与随机性设置不受索引模式影响,但要留意:DDP 之上叠加张量/流水线并行时必须用shard_seed: "randomized""trng"会让各并行 rank 的分片顺序不一致而死锁。

完成以上配置后,你的训练在每次 Lightning checkpoint 时就自动携带数据加载器的完整状态;中断后用相同拓扑(相同num_workers、相同 GPU 数)从 checkpoint 重启即可从断点精确继续,恢复后可用analyze_resumable_checkpoint.py抽查各数据源的推进比例是否符合预期的 blend 权重。

【免费下载链接】SpeechA scalable generative AI framework built for researchers and developers working on Large Language Models, Multimodal, and Speech AI (Automatic Speech Recognition and Text-to-Speech)项目地址: https://gitcode.com/GitHub_Trending/nem/Speech

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询