大模型预训练效果高度依赖数据集质量,原始网页、书籍、文章文本不能直接送入模型,需要经过清洗过滤、分词编码、格式转换、分片构建、多卡采样等完整流程。MindSpore / MindSpore‑Transformers 提供 Megatron bin‑idx、MindRecord 两种主流预训练数据格式,配套预处理脚本、数据加载流水线,适配昇腾 NPU 多机多卡预训练场景。本文从昇腾硬件数据 IO 底座、数据准备核心原理、代码示例、预处理脚本运行、关键调优手段、性能对比、常见问题、总结八大维度,讲解 MindSpore 大模型预训练全链路数据准备实践,保障数据质量与训练 IO 吞吐。

一、昇腾数据 IO 硬件基础

昇腾集群存储与硬件 IO 特性直接影响预训练数据读取性能,MindSpore 数据集模块深度适配硬件存储链路:

  1. 分布式存储:OBS、并行文件系统,大规模预训练推荐使用并行文件系统,避免单机磁盘 IO 瓶颈。

  2. NPU Host 侧 CPU 算力:预处理、分词、样本拼接运行在 Host CPU,多 worker 并发处理;处理完成后将整数 token 序列送入 NPU 做前向计算。

  3. 内存缓存机制:MindSpore Dataset 支持内存 cache,将高频访问数据集缓存至 Host 内存,减少磁盘重复读取开销。

  4. 多卡分片能力:支持num_shards / shard_id按 rank 做数据分片,实现多机多卡数据并行采样,保证各卡读到互不重复样本。

大模型预训练数据完整链路:原始文本 JSON → 清洗过滤 → BPE 分词编码 → 长文本片段拼接 → 生成 bin‑idx / MindRecord 二进制数据集 → 多卡加载、shuffle、batch → NPU 训练。

预训练语言模型目标:输入 token 序列,预测下一个 token。数据核心输出字段为input_ids整数 token 数组,序列长度与模型配置seq_len对齐。

二、核心准备原理

2.1 两大数据集格式选型

格式

适用场景

特点

Megatron bin‑idx

超大规模预训练,兼容 Megatron‑LM 生态

.bin存储 token 整数,.idx存储样本偏移索引;读取速度快,磁盘占用低,业界大模型主流格式

MindRecord

MindSpore 生态,支持多字段、自定义样本

MindSpore 自研二进制格式,支持多字段,便于调试,适合中等规模预训练、微调场景

大规模预训练优先选择bin‑idx 格式;调试、小实验可以选择 MindRecord。

2.2 数据准备完整流程

  1. 原始语料整理:原始文本输出为每行一条 json,字段text存放正文;支持id、src、title辅助元信息。

  2. 数据清洗:过滤乱码、过短文本、重复样本、低质量网页内容;去重避免样本记忆。

  3. 分词编码:加载模型对应 tokenizer,把文本转换为整数 token id 序列。

  4. 样本拼接:多条文档之间插入 eod/eos 结束符,拼接至固定序列长度seq_len。

  5. 生成二进制数据集:输出 bin‑idx 或者 MindRecord 文件。

  6. 校验数据集:检查样本数量、token 范围、eod 标记是否正确。

  7. 多机训练加载:多 rank 分片、shuffle、构建 batch 送入预训练网络。

2.3 多卡数据并行采样原理

数据并行场景,每个 rank 只读取全部数据的一个分片,通过num_shards=dp_world_size, shard_id=dp_rank实现分片。

重要:分片必须在 shuffle 之前执行;如果先 shuffle 再分片,不同 rank 会读到重复样本,发生样本泄露,严重损害预训练效果。

2.4 IO 吞吐优化核心思想

  • 预处理尽量离线完成,训练阶段只做二进制读取,不要在线实时分词;

  • 配置足够多num_parallel_workers并发 worker;

  • 开启 prefetch 预取,数据预加载到 Host 内存,NPU 计算时后台预取下一批样本,隐藏 IO 时延。

三、代码实现示例

3.1 原始输入 json 格式(预处理输入)

{"id":"0","text":"大模型预训练需要海量高质量文本数据。","src":"book","title":"AI导论"}
{"id":"1","text":"MindSpore支持昇腾平台大模型训练。","src":"doc","title":"昇思文档"}

3.2 调用官方预处理脚本生成 Megatron bin‑idx 数据集

MindSpore‑Transformers 内置preprocess_indexed_dataset.py,将 json 原始语料转为 bin‑idx 二进制数据集。

# preprocess_demo.py
import sys
from mindformers.tools.dataset_preprocess.megatron.preprocess_indexed_dataset import main

if __name__ == "__main__":
    sys.argv = [
        "preprocess_indexed_dataset.py",
        "--input", "./raw_corpus.json",
        "--output-prefix", "./pretrain_data",
        "--tokenizer-type", "LlamaTokenizer",
        "--vocab-file", "./tokenizer/vocab.json",
        "--merge-file", "./tokenizer/merges.txt",
        "--seq-length", 4096,
        "--eod-mask-loss"
    ]
    main()

运行后产出:pretrain_data_text_document.bin、pretrain_data_text_document.idx。

3.3 MindSpore 训练侧加载 bin‑idx 数据集(多卡分片示例)

import mindspore as ms
from mindformers import MindFormerConfig
from mindformers.dataset import build_dataset

def create_pretrain_dataset(dp_rank, dp_world_size):
    config = MindFormerConfig("./llama7b_pretrain.yaml")
    config.train_dataset.dataloader.config.data_path = "./pretrain_data_text_document"
    config.train_dataset.dataloader.num_shards = dp_world_size
    config.train_dataset.dataloader.shard_id = dp_rank
    config.train_dataset.dataloader.num_parallel_workers = 8
    config.train_dataset.dataloader.prefetch_size = 4

    train_ds = build_dataset(config.train_dataset)
    return train_ds

if __name__ == "__main__":
    # 示例:单进程调试,多机由分布式框架传入真实dp_rank、dp_world_size
    ds = create_pretrain_dataset(dp_rank=0, dp_world_size=1)
    for item in ds.create_dict_iterator(num_epochs=1, output_numpy=True):
        print("input_ids shape:", item["input_ids"].shape)
        break

3.4 简单校验数据集 token

import numpy as np

def check_bin_idx_data(bin_path, idx_path):
    bin_data = np.fromfile(bin_path, dtype=np.int32)
    print(f"bin总token数: {bin_data.shape[0]}")
    # token id不能超过词表大小,不能大量出现0等异常id
    print(f"min token id: {bin_data.min()}, max token id: {bin_data.max()}")

if __name__ == "__main__":
    check_bin_idx_data("./pretrain_data_text_document.bin", "./pretrain_data_text_document.idx")

四、编译与运行

4.1 环境依赖

pip install mindspore mindformers
# 确认CANN环境已经source
source /usr/local/Ascend/ascend‑toolkit/latest/set_env.sh

4.2 离线预处理生成 bin‑idx 数据集

python preprocess_demo.py

4.3 启动预训练(多机多卡)

yaml 配置中填写数据集路径,启动分布式预训练任务:

msrun --worker_num=8 --local_worker_num=8 --master_port=29500 \
llama_pretrain_run.py --config ./llama7b_pretrain.yaml

4.4 数据集校验脚本执行

python check_dataset.py

五、关键调优手段

5.1 离线预处理优先原则

分词、文本拼接全部离线完成;训练阶段只读取二进制 token,禁止训练流程在线做大规模分词,否则 CPU 预处理成为瓶颈,NPU 大量空闲。

5.2 多卡分片顺序

分片参数num_shards/shard_id必须在 shuffle 之前生效,防止样本重复泄露。MindFormers 的 build_dataset 内部已经保证该顺序,自定义数据集需要格外注意。

5.3 IO 性能调优

  • num_parallel_workers:根据 Host CPU 核数设置,一般 8‑16;不要超过 CPU 物理核心数;

  • prefetch_size预取,后台预加载 batch,隐藏 IO 时延;

  • 大规模预训练使用并行文件系统,不要使用单机本地磁盘;

  • 数据集文件尽量做分片,不要单个超大 bin 文件,提升多进程并发读取。

5.4 数据质量调优

  • 做语料去重,去除 near‑duplicate 近似重复样本,防止模型记忆训练数据;

  • 训练集、验证集严格隔离,杜绝测试样本混入训练集;

  • 合理设置 eod/eos 结束 token,文档之间必须插入 eod,否则多文档拼接边界混淆。

5.5 序列长度与样本对齐

  • 预处理seq‑length必须与模型训练 yaml 配置的seq_length完全一致;

  • 不要训练时在线动态 padding 补齐样本,预处理阶段拼接至固定长度,减少训练时开销。

5.6 调试小技巧

调试阶段生成小样本子集数据集,快速跑通训练链路,确认 loss 下降趋势,再切换完整大规模数据集。

六、性能对比

测试条件:Llama‑7B 预训练,seq_len=4096,昇腾 910B 8 卡数据并行,统计 Host‑NPU 吞吐,单位 tokens/s

数据处理方式

训练吞吐 (tokens/s)

说明

训练时在线分词处理原始 json

1230

CPU 预处理瓶颈,NPU 大量空闲,性能很差

离线生成 bin‑idx,worker=2,prefetch=1

5860

IO 配置不足,预取不足

离线 bin‑idx,worker=8,prefetch=4

8720

最优配置,IO 不再成为瓶颈,NPU 算力充分发挥

说明:大模型预训练很容易出现CPU 数据预处理拖慢 NPU,离线预处理是最有效的优化手段。

七、常见问题与优化建议

  1. NPU 利用率低,大量时间在等待数据,IO 瓶颈

    1. 原因:在线实时分词;worker 数量不足;磁盘 IO 慢;prefetch 过小。

    2. 方案:全部离线预处理生成 bin‑idx;调高 num_parallel_workers 与 prefetch_size;切换并行文件系统。

  2. 多卡训练 loss 异常偏低,模型泛化差,存在样本泄露

    1. 原因:分片 shuffle 顺序错误,不同 rank 读到重复样本;验证集混入训练集。

    2. 方案:保证分片在 shuffle 之前执行;严格隔离训练集、验证集,校验样本 ID。

  3. 生成 bin‑idx 数据集后训练报 token id 越界

    1. 原因:预处理使用的 tokenizer 与训练阶段 tokenizer 不一致;词表版本不对。

    2. 方案:预处理、训练使用完全同一套 vocab/merge 文件,校验 token id 最大不超过词表大小。

  4. 文档边界混淆,多段文本连在一起没有分隔

    1. 原因:预处理脚本没有正确插入 eod/eos 结束标记。

    2. 方案:预处理开启--eod‑mask‑loss参数,文档之间插入 eod token。

  5. MindRecord 打开报错 MRMOpenError

    1. 原因:旧版本文件移动、重复生成没有覆盖旧文件。

    2. 方案:生成 MindRecord 设置overwrite=True;新版本 MindSpore 支持文件拷贝移动。

八、总结

MindSpore 大模型预训练的数据准备,不是简单的文件转换,是原始语料清洗、离线分词编码、样本拼接、二进制数据集构建、多卡正确分片采样的完整工程流程。大规模预训练优先使用 Megatron bin‑idx 格式,把分词、拼接全部离线完成,训练阶段只读取二进制 token,避免 Host CPU 预处理拖慢 NPU 算力。

实际开发建议:优先使用 MindSpore‑Transformers 官方预处理脚本,先构建小数据集调试链路,校验 token、eod 标记、多卡分片逻辑,确认无样本泄露问题后再切换到完整大规模语料;配合并行文件系统,调优 worker 与 prefetch 参数,消除 IO 瓶颈,保障昇腾平台大模型预训练的数据质量与训练吞吐。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐