从 data.proto 可以看到,OdpsDataset 是 默认值(default = OdpsDataset),OdpsDatasetV1 是后来加的编号 4,实际上是保留的旧版兼容入口。
核心原因有以下几点:
1. 性能差距巨大
| 维度 | OdpsDatasetV1 (common_io) | OdpsDataset (Storage API) |
| 读取方式 | 逐行 Python 循环 _do_read_with_retry() |
批量 Arrow RecordBatch(C++ 层一次数万行) |
| 序列化 | 每行独立序列化 → Python 对象 → pa.array |
Arrow IPC 列式格式,零拷贝 |
| 压缩 | 无 | LZ4_FRAME(减少 ~60% 网络传输) |
| 列裁剪 | 弱(selected_cols 字符串传入) |
强(required_data_columns 服务端只发需要的列) |
训练时数据量大(数十亿样本),V1 的逐行 Python 循环会成为严重瓶颈,数据加载速度远跟不上 GPU 计算速度。
2. 训练必需的断点续训(Checkpoint)
V2 支持完整的断点续训机制:
- 每个 batch 注入 source_id(input_path#session_id:start)追踪读取位置
- load_state_dict / _restore_sessions 可从中断处恢复读取
- Session 有效期内可精确恢复到上次读取的行
V1 没有任何 checkpoint 支持,训练中断后只能从头开始。
3. 分布式训练支持
V2 内置分布式协调:
- Rank 0 创建 session → broadcast_object_list 广播 sessionid 给所有 worker
- calc_slice_intervals 精确的行级分片,确保多 worker 不重复不遗漏
- Session 刷新守护线程(_refresh_sessions_daemon)防止长时间训练 session 超时
V1 只有简单的 slice_id / slice_count,没有分布式协调,多机训练时容易出问题。
4. 复杂类型支持
V1 只支持 5 种基础类型(bigint, double, boolean, string, datetime),训练中常见的 ARRAY<BIGINT>、MAP<STRING,FLOAT> 等特征类型无法直接读取,需要预先序列化为字符串。
V2 支持 30+ 种类型,包括嵌套的 ARRAY<ARRAY<T>> 和 MAP<K,V>,直接读取无需额外预处理。
5. V1 的存在意义
V1 保留下来主要是为了兼容旧版 PAI 平台环境,那些环境只有 common_io 而没有新版 Storage API SDK。新的训练任务都应该使用 OdpsDataset(默认值)。
总结
OdpsDataset 是生产训练的唯一合理选择,V1 在性能、断点续训、分布式、类型支持上全面落后,仅作为旧环境的兜底方案保留。