当前位置: 首页 > news >正文

Parquet 范式:大语言模型训练数据格式优化的基础解析

在这里插入图片描述

摘要

将数据格式转换为 Apache Parquet 并非一种随意的偏好,而是针对大规模数据处理(尤其是大语言模型 (LLM) 训练)的一项基础性能优化。Parquet 格式通过其列式存储架构,在 I/O 效率、存储成本和查询性能方面提供了数量级的提升。

本报告的结论是,Parquet 的使用并不仅限于强化学习 (RLHF) 阶段,而是贯穿 LLM 数据生命周期所有阶段(包括预训练、监督微调 (SFT) 和 RLHF)的最佳实践。

这种广泛采用的核心原因在于 Parquet 卓越的 I/O 性能——通过列裁剪和谓词下推显著减少数据读取量——以及其高效的压缩机制。更重要的是,Parquet 是现代 LLM 数据工具(如 Hugging Face datasets 库)性能模型的核心。该库利用 Parquet、Apache Arrow 和内存映射 (mmap) 技术的组合,实现了在极低内存占用下处理海量数据集的能力。


I. 基础范式:解构列式存储与行式存储

选择数据格式是一种算法优化,它决定了数据在磁盘上的物理布局如何与计算模式(如模型训练)相匹配。Parquet 的设计初衷是解决 CSV 或 JSON 等传统行式格式在分析工作负载中的根本性低效问题。

A. 行式格式 (CSV/JSON) 在分析型负载下的低效

CSV 和 JSON 等传统格式以“行”为单位存储数据。例如,一个 CSV 文件在磁盘上的布局是:
row1_colA, row1_colB, row1_colC... \n row2_colA, row2_colB, row2_colC...

这种布局非常适合“在线事务处理”(OLTP) 系统,例如需要读取或写入单个完整记录(如一条客户订单)的场景。

然而,LLM 数据处理是典型的“在线分析处理”(OLAP) 工作负载。训练作业通常不关心某一个文档的所有信息;它关心的是十亿个文档的*“text”列*。在行式格式中,为了读取“text”列,系统必须从磁盘读取每一(包括“url”、“timestamp”和“metadata”等所有其他列),在内存中解析它们,然后丢弃大部分不相关的数据。在 TB 级数据集上,这会导致灾难性的 I/O 浪费和计算开销。

B. Parquet 架构:行组、列块与元数据

Parquet 是一种开源、语言无关的列式存储格式,其灵感源于 Google 的 Dremel 论文。它采用了一种混合结构,并非纯粹的列式。

一个 Parquet 文件首先被水平分区成大型的行组 (Row Groups)(例如,128 MB 到 1 GB)。在每个行组内部,数据被垂直存储为列块 (Column Chunks)。文件的末尾包含一个元数据页脚,其中记录了 schema 信息,以及至关重要的——每个列块的统计信息(例如最小值、最大值)。

这种混合模型是一个巧妙的折中:

  • 行组成为并行处理的基本工作单元(例如,一个 Spark 执行器可以处理一个行组)。
  • 列块提供了列式存储的 I/O 效率。

C. I/O “银弹”:列裁剪与谓词下推

Parquet 的架构实现了两种强大的 I/O 优化技术,这是 CSV 或 JSON 无法做到的。

  1. 列裁剪 (Column Pruning)
    列裁剪是一种“垂直跳过”。由于数据是按列块存储的,当查询只需要 column_Acolumn_C 时,系统可以完全跳过磁盘上 column_B 的数据块。

    对于一个包含 ['text', 'url', 'timestamp', 'metadata_json'] 列的 LLM 预训练数据集,一个只读取 ['text'] 列的训练脚本,将自动“裁剪”掉所有其他列的数据。这可能意味着跳过了磁盘上 90% 的数据,只读取必要的内容,从而极大地减少了 I/O。

  2. 谓词下推 (Predicate Pushdown)
    谓词下推是一种“水平跳过”。它将查询中的过滤条件(即“谓词”,例如 WHERE language = 'en')下推到存储层,在数据被读取之前进行过滤。

    Parquet 文件元数据中存储的统计信息(最小值/最大值)是实现这一功能的关键。当查询引擎(如 Spark、DuckDB 或 PyArrow)看到一个过滤器(例如 WHERE token_count > 512)时,它会首先检查元数据。如果某个 1 GB 大小的行组的元数据显示其 token_count_max = 400,引擎就“知道”这个行组中没有任何数据能满足查询条件。因此,引擎会跳过读取这整个 1 GB 的数据块,甚至不会触碰相关的磁盘区域。

D. “秘密武器”:编码与压缩

Parquet 的高压缩比并不仅仅是应用了 Gzip。它在每个列块上应用压缩,由于列中存储的是同质(类型相同)的数据,因此压缩效率远高于压缩混合了各种类型数据的 CSV 文件。

这是一个两级过程:

  1. 编码 (Encoding - L1): 在压缩之前,Parquet 会根据数据特征应用特定的编码方案。

    • 字典编码 (Dictionary Encoding): 适用于低基数(重复值多)的列,如“language”或“source”。例如,一列 ['en', 'en', 'fr', 'en'] 会被替换为 Dictionary: ['en', 'fr']Data: [0, 0, 1, 0]
    • 游程编码 (Run-Length Encoding, RLE): 适用于有连续重复值的列(如排序后的数据)。例如 [0, 0, 0, 0, 1, 1, 1] 变为 (0, 4), (1, 3)
    • 增量编码 (Delta Encoding): 适用于时间戳或 ID 等序列数据。
  2. 压缩 (Compression - L2): 经过编码的数据(现在主要是小整数)被送入一个标准压缩器,如 Snappy(速度快,压缩比适中)、Gzip(速度慢,压缩比高)或 ZSTD(现代压缩算法,压缩比高且解压速度快)。

对于 LLM 的文本数据,ZSTD 被认为是一个“绝佳的选择”,因为它无论使用何种编码方式,都能提供比 Snappy 更小的文件体积。这种“先编码,后压缩”的策略是 Parquet 文件体积远小于 CSV 的核心原因。

E. 原生处理复杂嵌套数据

LLM 的原始数据通常是复杂的嵌套 JSON。Parquet 使用了 Dremel 论文中的“记录粉碎和组装”算法 (record-shredding and assembly),该算法基于“重复级别”和“定义级别”,能够将复杂的嵌套结构(如 struct 和 array)“压平”并存储为扁平的列。

这意味着原始 JSON 的结构信息(例如 {'user': {'name': 'A'}, 'posts': [{'id': 1}, {'id': 2}]})不会丢失。Parquet 会将其“粉碎”为 user.nameposts.id 等扁平列,并在读取时使用元数据完美地重建原始的嵌套结构。


II. 定量影响:Parquet 的数据驱动案例

从理论转向实践,Parquet 带来的影响是具体且可量化的。一项针对 1TB 数据集的直接 A/B 测试(CSV vs Parquet)展示了惊人的结果。

A. 99% 的缩减:存储、性能与成本

分析显示,Parquet 在所有关键指标上都实现了数量级的优化。

表 1:CSV 与 Parquet 性能的定量比较(基于 1TB 数据集)

指标存储为 CSV存储为 Parquet优势(因子/百分比)
存储大小1 TB130 GB节省 87% 存储空间
查询运行时间236 秒6.78 秒速度提升 34.8 倍
数据扫描量1.15 TB2.51 GB减少 99.8% 数据扫描
查询成本$5.75$0.01节省 99.7% 成本

(数据来源:[1])

这种性能提升存在清晰的因果链:

  • 87% 的存储缩减是编码和压缩(章节 I.D)的直接结果。
  • 99.8% 的数据扫描量缩减是列裁剪和谓词下推(章节 I.C)的直接结果。
  • 34.8 倍的速度提升是“数据扫描量缩减 99.8%”的必然结果。

需要注意的是,其他分析(例如 [5] 中对 DuckDB 的分析)显示了更保守的估计,约为 5 倍的体积缩减和 3 倍的扫描速度提升。这并不矛盾。[1] 的测试很可能代表了“最佳情况”的分析型查询(例如 SELECT AVG(one_column)),此时列裁剪的优势最大。3 倍至 34 倍的范围代表了从全表扫描到高选择性查询的真实性能增益区间。


III. 关键链接:Parquet 在现代 LLM 数据加载栈中的地位

Parquet 不仅仅是一个文件格式,它是现代 LLM 数据加载栈(尤其是 Hugging Face)得以实现高性能的关键组件。

A. “Parquet-on-Disk, Arrow-in-Memory” 管道

在实际应用中,Parquet 与 Apache Arrow 协同工作:

  • Parquet 是优化的磁盘存储格式。
  • Apache Arrow 是一种内存中的列式格式。
  • PyArrow 是用于读写 Parquet 的 Python 库。

读取操作的流程是:PyArrow 读取磁盘上的 Parquet 列块,对其进行解压(例如 ZSTD)和解码(例如 RLE),然后将其加载为 Arrow 的内存中数组。

一旦数据进入 Arrow 的内存格式,它就可以通过零复制读取 (zero-copy reads) [7] 传递给其他工具,如 Pandas、NumPy 乃至 PyTorch。这意味着 PyTorch 可以获得一个指向 Arrow 数组中数据的直接指针,而无需进行任何序列化、反序列化或内存复制。这个过程为饥渴的 GPU 提供了极高的数据加载吞吐量,节省了数十亿的 CPU 周期。

B. Hugging Face datasets 与内存映射 (mmap) 的“魔法”

Hugging Face datasets 库是 LLM 生态的事实标准,它将 Arrow 作为其本地缓存系统。该库会自动将其他格式(如 CSV/JSON)转换为 Parquet,然后再转换为其 Arrow 缓存。

这套机制是 LLM 从业者感受到的“魔法”的来源:

  1. 用户运行 load_dataset("some_dataset.jsonl")
  2. datasets 库解析该 JSONL 文件,并将其转换为 Arrow 格式的缓存文件,存储在磁盘上。
  3. 该 Arrow 缓存文件随后被内存映射 (memory-mapped, mmap)

内存映射 (mmap) 是一种操作系统功能,它将磁盘上的文件映射到进程的虚拟内存地址空间。关键在于,数据并不会被加载到 RAM 中。当 Python 代码请求 dataset[500_000_000](第 5 亿条记录)时,操作系统会接管 I/O,只从磁盘中调入包含该记录的那一个数据块。

[8] 中的一个例子极具说服力:加载完整的英文维基百科数据集(18 GB),仅占用了 50 MB 的 RAM。这 50 MB 只是用于元数据和指针;18 GB 的数据仍然在磁盘上,但可以通过虚拟内存被即时访问。

需要注意的是,正如 [9] 所澄清的,Parquet 文件本身(由于其压缩和编码)无法被直接高效地 mmap。它必须首先被读取、解压和解码为一个可 mmap 的格式——而 datasets 库的 Arrow 缓存正是这个格式。

因此,Parquet 是高效的存储格式,而 Arrow(通过 mmap)是高效的内存访问层

C. 流式处理与分布式训练

在(100GB+)大规模分布式训练中,Parquet 是云存储的理想选择。然而,一些框架(如 MosaicML 的 StreamingDataset)认为,对于超大规模的随机打乱和随机访问,Parquet 等格式“存在不足” [14],并因此提出了它们自己的分片格式 (MDS)。

这并非矛盾。Parquet 是行业标准的、经过处理和分词的数据集“真理之源”。当需要将这些数据流式传输到数千个 GPU 时,可能会发生进一步的转换,将其变为针对流式传输优化的格式(如 MDS)。但这个流式转换的输入源,几乎总是 Parquet 文件。


IV. Parquet 在 LLM 全生命周期中的角色

通过分析 LLM 开发的每个阶段所使用的数据集格式,可以清晰地看到一个演进趋势。认为 Parquet 只在特定阶段(如 RLHF)使用的观点是片面的。

A. 阶段 1:预训练(数 TB 的挑战)

  • 历史背景:
    • C4 数据集: 最初以 JSON 格式发布,大小约 305GB [10]。
    • The Pile 数据集: 最初以 JSONLines (JSONL) 格式发布,并使用 zstandard 压缩(.jsonl.zst),大小为 825 GiB [11]。
  • 现代标准:
    • RefinedWeb 数据集(用于 Falcon LLM): 这是一个解压后达 2.8TB 的海量数据集 [12],用于训练高性能的 Falcon 模型。该数据集原生以 Parquet 格式分发

表 2:大型预训练数据集格式的演进

数据集主要用途原始格式 (Crawl)发布/处理格式大小
C4T5 预训练(Common Crawl)JSON~305GB [10]
The PileGPT-Neo/J 预训练多种来源JSONLines (.jsonl.zst) [11]825 GiB [11]
RefinedWebFalcon 预训练WARC/WET [12]Parquet [12]2.8TB [12]

结论: 行业趋势清晰可见。如表 2 所示,虽然早期的基石数据集 (C4, Pile) 使用 JSON/JSONL,但最新、规模最大的数据集 (RefinedWeb) 已经标准化为 Parquet。

这是一个合乎逻辑的演进:在 300GB 时,JSON/JSONL 虽然慢,但尚可管理;在 825GB 时,它已成为严重瓶颈;而在 2.8TB+ 的规模下,基于 JSON 的格式在计算和成本上是不可行的。RefinedWeb 的创建者选择了 Parquet,因为只有 Parquet 能够高效地处理该规模的数据,允许研究人员利用谓词下推(例如按 URL 过滤)和列裁剪(只选择 ‘text’ 列)。

B. 阶段 2:监督微调 (SFT)

SFT 需要结构化的“输入-输出”对,或“提示-完成”对 (prompt-completion)。这通常是 {'prompt': '...', 'response': '...'} 结构。

虽然一个 SFT 数据集可能很小(例如 10,000 行),可以存储为 JSONL,但所有支持 Parquet 的理由依然成立。这些数据是高度结构化和列式的 (‘prompt’, ‘response’)。

随着 SFT 数据集从 1 万行增长到 1000 万行,使用 Parquet 成为最佳实践。它允许 datasets 库使用 mmap 节省内存,并允许分词器仅在 ‘prompt’ 列上运行(通过列裁剪),而无需将 ‘response’ 列加载到内存中。

C. 阶段 3:对齐与强化学习 (RLHF)

这是 Parquet 优势最明显的领域之一。

  1. 奖励模型 (RM) 训练: RLHF 的第一步是训练一个奖励模型。这需要一个“偏好数据集”。这种格式是高度结构化的,通常是 {'prompt': '...', 'chosen_response': '...', 'rejected_response': '...'}

    这是一个完美的 Parquet 用例。它是一个具有 3-4 个文本列的表格。章节 I.C(列裁剪)和 I.D(压缩)的所有论点均适用。研究人员可以高效地查询仅提示,或仅被选中的回复。

  2. PPO (策略) 训练: 最后一步是使用 PPO 算法来微调 LLM。这个过程涉及从数据集中流式传输提示 (prompts) 到模型,然后生成响应(一个“轨迹”)。

    直接证据: 一个生产级的 RL 库的 ppo_trainer.yaml 配置文件 [15] 明确地将训练和验证数据的路径定义为:

    data.train_files: ~/data/rlhf/gsm8k/train.parquet
    data.val_files: ~/data/rlhf/gsm8k/test.parquet
    

综合结论: Parquet 确实在 RLHF 中被广泛使用。然而,其因果关系经常被误解。

Parquet 不是因为它是 RLHF 才被使用,而是因为 RLHF(如同预训练和 SFT)是一个高吞吐量、分析规模的数据处理任务。使其成为大数据分析 [1] 和现代预训练数据集 [12] 默认选择的那些特性,同样使其成为处理 RLHF 结构化、列式数据的显而易见、合乎逻辑的选择。


V. 综合分析与最终建议

A. 最终结论

  1. 为什么要转换? 因为 Parquet 的列式架构(章节 I)在存储、成本和 I/O 性能方面提供了数量级的改进(章节 II)。一个 1TB 的 CSV 变成了 130GB 的 Parquet,一个 4 分钟的查询变成了 6 秒的查询,因为数据扫描量减少了 99% [1]。

  2. 适用阶段: 认为 Parquet “只用于 RLHF”的观点是片面的。

    • RLHF: 是的,它在 RLHF 中被明确使用 [15],因为偏好数据(prompt, chosen, rejected)是完美的列式数据。
    • SFT: 它是 SFT 的最佳实践,因为 prompt/response 对也是完美的列式数据。
    • 预训练: 它已成为最先进的、数 TB 规模的预训练数据集(如 RefinedWeb)的新标准 [12],取代了老旧、低效的 JSON/JSONL 格式 [10, 11]。
  3. 统一因素(真正的“为什么”): Parquet 之所以无处不在,真正的核心原因是 Hugging Face datasets。该库是 LLM 生态系统中加载数据的事实标准。其整个高性能模型都建立在 Parquet-on-disk -> Arrow-in-memory -> mmap 这一管道之上 [8, 9]。

    正是这个管道,允许单个研究人员在笔记本电脑上仅用几十 MB 的 RAM 就能加载 TB 级的海量数据集 [8]。因此,将数据转换为 Parquet 是解锁整个 MLOps 工具链全部性能的第一步。

B. 战略建议:LLM 数据处理管道

基于此分析,推荐采用以下标准化的 LLM 数据处理流程:

  • 摄入(原始): 你的源数据(JSON, CSV, WET 文件)是原始、未经处理的层。
  • 处理(分词): 使用分布式框架(如 Spark)或 datasets.map() 来清洗、过滤和分词这些原始数据。
  • 标准化(存储): 将处理过的、分词后的、结构化的数据保存为 Parquet 格式(推荐使用 ZSTD 压缩)。这个 Parquet 数据集成为你的“黄金标准”真理之源。
  • 训练(加载): 在所有训练阶段(预训练、SFT、RLHF),将你的 datasets 加载器 [8] 或流式加载器 [14] 指向这个 Parquet 数据集。这将利用 Parquet->Arrow->mmap 管道 [9] 实现最大的 I/O 效率,确保你的 GPU 永远不会“挨饿”。
http://www.dtcms.com/a/593281.html

相关文章:

  • 网站备案的核验单做HH的网站
  • 基于MATLAB的JPEG图像压缩实现
  • 个人网站的建设中铁建设集团有限公司官方网站
  • 耐达讯自动化Profibus转光纤连接伺服驱动器,让电力行业通信效率飙升10倍!
  • 专为AWD攻防演练比赛设计的综合性工具箱,集成漏洞利用、流量监控、自动化攻击等功能
  • 冶金车间“迷雾”重重?耐达讯自动化Profibus转光纤为HMI点亮“透视眼”!
  • 第一章 网络安全概念及规范
  • 中国发行稳定币对金融行业网络安全布局的影响及新的业务增长点分析
  • 华为网站建设和阿里云哪个好投资理财网站模板
  • 近期思考:如何自我提升呢?三年以后有大变化?
  • Ansible主机清单:自动化管理的核心基石
  • 专做高中知识的网站腾讯朋友圈广告代理
  • 「日拱一码」146 SVR调参注意事项与技巧
  • 谷歌云大规模分布式存储系统:定义、特性与技术挑战解析
  • 山东省住房和城乡建设厅服务网站百度网络公司
  • 网站平台需要做无形资产吗 怎么做网站里做个子网页怎么做
  • 在 AEDT 中对用于模拟的作业进行排队
  • FastAPI × Loguru:从“能跑”到“可运维”的日志实战
  • 怎样设立网站网站开发 策划是干嘛的
  • 【大数据技术04】数据可视化
  • qml 网站开发宝塔网站301重定向怎么做
  • 《数据结构:从0到1》-09-队列
  • 安徽建站模板广州市网站制作
  • Vue 项目实战《尚医通》,完成医院科室业务,页面自动滚动到指定位置,笔记22
  • 国产化Word处理控件Spire.Doc教程:使用Java将RTF文件转换为PDF的全面教程
  • Redis 生产环境安全基线配置指南:从风险分析到实操加固
  • java使用poi-tl模版+vform自定义表单生成word,使用LibreOffice导出为pdf,批量下载为压缩文件
  • 济南专业的网站建设公司wordpress快速发布
  • 帝国cms手机网站模板保洁公司开发app
  • 【必收藏】RAG技术全景图:从NaiveRAG到AgenticRAG的演进与工程实践指南