模块设计:输入与分箱¶
1. 职责¶
把用户数值矩阵转换为稳定、紧凑的分箱表示,并定义所有权、缺失值、边界和序列化语义。分箱结果是 CPU oracle 与 MPS 后端的共同输入。
2. 输入不变量¶
rows > 0、features > 0;rows × features × itemsize使用检查过的 64 位算术;- 0.2.0 输入全部有限;
- 不支持的 dtype 在分配大内存前拒绝;
- 行数和特征数不得超过内部索引类型上限。
3. 分箱算法¶
0.2.0 使用确定性分位数边界:
- 按特征读取有限值;
- 以稳定规则生成最多
max_bins - 1个切分边界; - 去除相同边界,常量特征只产生一个有效 bin;
- 使用固定的
upper_bound/lower_bound语义映射值; - 相同输入、参数和版本必须产生相同边界与 bin。
算法只实现一次。并行化可以改变执行顺序,但不能改变边界规则。
4. 内部表示¶
max_bins <= 256使用uint8_t;257..65536使用uint16_t;- 超过范围在 0.2.0 拒绝;
- 边界使用连续
float32或冻结后的精度; - 特征元数据记录 offset 和有效 bin 数。
训练布局默认 feature-major,以连续读取单特征样本;最终决定需通过布局基准。模型格式只保存边界,不保存训练布局。
5. 数据所有权¶
- Python 输入只在同步验证与转换期间借用;
BinnedDataset拥有其分箱内存;- 不得保存用户临时 buffer 的裸指针;
- 若零复制条件不满足,必须明确复制并可诊断;
- 上传设备后,host 数据的释放时机由训练会话统一管理。
6. 缓存¶
0.2.0 首先支持进程内复用。磁盘分箱缓存只有完成以下条件后才能启用:
- fingerprint 覆盖数据内容、形状、dtype、分箱参数和格式版本;
- 原子写入与校验;
- 不缓存标签;
- 用户可查询和清理;
- 损坏或不匹配时重建。
7. 错误与安全¶
- 所有 offset 和 stride 运算检查溢出;
- 不允许 NaN 在不同平台被映射到不同 bin;
- 分配前估算 host 与 device 峰值;
- 错误消息说明数据形状、所需类型与限制,不打印原始数据。
8. 验收¶
- 手算边界、常量、重复值、极端偏斜、最大 bin 和非连续输入测试;
- 同一数据重复执行得到完全一致的 bin;
- CPU oracle 与 MPS 使用相同只读视图;
- 无越界、悬空指针或隐藏的多份全量复制。