Apache Arrow 格式详解:Tensor 与 SparseTensor 消息的二进制布局、弃用状态与迁移路径
Apache Arrow 格式详解Tensor 与 SparseTensor 消息的二进制布局、弃用状态与迁移路径【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrow导读本文深入解析 Apache Arrow 格式规范中两个**不属于列式格式Columnar format**的特殊数据结构——Tensor稠密多维数组与SparseTensor稀疏多维数组消息。它们位于 format/Tensor.fbs 与 format/SparseTensor.fbs 两个 Flatbuffers 协议定义文件中为需要跨进程共享数组之外的数据结构的应用提供了一套通用的 IPC 元数据机制。读完本文你将掌握这两种消息的字段结构、独立封装时的 64 字节对齐规则、三种稀疏索引格式COO / CSX / CSF的底层约定以及官方给出的弃用状态与推荐迁移路径arrow.fixed_shape_tensor扩展类型。为什么这些结构不属于列式格式Apache Arrow 的核心是列式内存格式Columnar format见 docs/source/format/Columnar.rst它用Schema、RecordBatch、DictionaryBatch等消息承载由等长数组组成的表。但 Arrow 的 Flatbuffers 协议定义文件里还为其他类型的数据结构定义了元数据目的是让其他种类的应用也能复用 Arrow 通用的进程间通信IPC机制内存共享、封装消息、Flatbuffers 序列化等。这两类结构被明确声明为不构成列式格式的一部分Tensor多维数组dense ndarray的元数据SparseTensor稀疏多维数组的元数据。一个关键的实现事实是大多数 Arrow 语言实现并不支持这两类消息类型。从 format/Message.fbs 的MessageHeaderunion 可以看到消息头同时容纳Schema、DictionaryBatch、RecordBatch、Tensor、SparseTensor五种类型但官方注释明确写道Arrow implementations do not need to implement all of the message types... For maximum compatibility, it is best to send data using RecordBatch.即为了最大兼容性应优先使用RecordBatch传输数据。弃用deprecated状态格式文档 在开篇即以deprecated指令标注下文描述的 IPC 特性均已弃用理由是它们与 Arrow 的其他概念如列式格式组合得不好dont compose well。因此在阅读或使用这些消息时应将其视为历史遗留的互操作机制而不是 Arrow 现在推荐的数据承载方式。封装消息与 64 字节对齐规则两种消息在独立封装standalone encapsulated message传输时都复用 Columnar 规范 中定义的封装 IPC 格式。标准封装格式为continuation: 0xFFFFFFFF metadata_size: little-endian int32 metadata_flatbuffer: bytes padding message body其中 32 位 continuation 指示符0xFFFFFFFF与 32 位小端长度前缀共同解决 Flatbuffers 的 8 字节对齐要求整个序列化消息必须是 8 的倍数以便消息可以在流之间搬移。Tensor 消息的额外要求将张量数据体tensor body的起始偏移额外对齐到64 字节的倍数metadata prefix and metadata PADDING tensor bodySparseTensor 消息的额外要求稀疏索引sparse index和稀疏张量数据体sparse tensor body的起始偏移若写入共享内存区域都对齐到64 字节的倍数metadata prefix and metadata PADDING sparse index PADDING sparse tensor body64 字节对齐通常是为了配合 SIMD 指令或特定硬件/共享内存区域shared memory region的访问要求。需要注意的是稀疏索引内部的具体布局取决于所使用的稀疏格式见下文。Tensor稠密多维数组消息Tensor消息用于承载**定宽值fixed-size values**构成的多维数组例如一个 NumPy ndarray。注意它只支持定宽值类型不支持字符串或嵌套类型。Flatbuffers 字段结构依据 format/Tensor.fbs其结构定义如下字段类型必填说明typeType是单个值单元的数据类型仅支持定宽值类型无字符串、无嵌套类型shape[TensorDim]是张量各维度可选命名strides[long]否沿每个维度前进一个值单元所需的非负字节偏移省略时默认为行主序C 风格row-majordataBuffer是张量数据的位置与大小其中TensorDim由两个字段组成size: long该维度的长度name: string维度名称可选。strides字段使得非连续布局如切片后的 ndarray也可以被精确描述省略时按行主序解释这正是 C/C 数组与 NumPy 默认布局的存储方式。与 C 实现的对应C 侧 cpp/src/arrow/tensor.h 中class ARROW_EXPORT Tensor的构造参数与 fbs 定义一一对应构造签名接受type、datastd::shared_ptrBuffer、shape、可选的strides与dim_names提供strides()、dim_names()访问器以及is_contiguous()判断张量是否连续CalculateValueOffset依据 strides 计算给定下标index的数据偏移offset index[i] * strides[i]。也就是说元数据层面shape/strides/dim_names与数据缓冲Buffer完全解耦与列式格式中元数据 内存缓冲的思想一致。此外该头文件还提供TableToTensor与RecordBatchToTensor辅助函数可以把表/记录批转换为张量支持null_to_nan、row_major等参数可作为从列式数据构造 Tensor 消息的入口。为什么被弃用arrow.fixed_shape_tensor扩展类型官方在 format/Tensor.fbs 与 格式文档 中一致指出The recommended way to pass tensors over Arrow IPC is using RecordBatch columns with thearrow.fixed_shape_tensorcanonical type.即推荐用携带arrow.fixed_shape_tensor规范扩展类型的 RecordBatch 列来传输张量。该扩展定义在 docs/source/format/CanonicalExtensions.rst存储类型FixedSizeList其中value_type为单个张量元素的类型list_size为张量 shape 各维乘积扩展类型参数value_type元素类型、shape物理形状数组可选dim_names维度名与permutation维度重排描述逻辑布局与物理行主序布局的对应关系序列化元数据为 JSON例如{ shape: [2, 5]}、{ shape: [100, 200, 500], dim_names: [C, H, W]}元素按行主序C 连续存储。这样张量就组合进了列式格式可以像普通列一样参与 RecordBatch、流式传输与各类算子这正是Tensor消息所欠缺的组合能力。SparseTensor稀疏多维数组消息SparseTensor表示元素通常几乎全为零的多维数组只存储非零值与索引。与Tensor不同它目前没有推荐的替代方案官方表示如有强需求可到开发邮件列表讨论。依据 format/SparseTensor.fbs其结构为字段类型必填说明typeType是值单元的数据类型仅支持定宽类型shape[TensorDim]是张量各维度可选命名non_zero_lengthlong否稀疏张量中非零值的数量sparseIndexSparseTensorIndex是稀疏索引union三选一dataBuffer是张量数据的位置与大小稀疏索引是一个 union包含三种格式SparseTensorIndexCOO坐标格式、SparseMatrixIndexCSX压缩稀疏矩阵格式、SparseTensorIndexCSF压缩稀疏纤维格式。COOCoordinate 坐标格式SparseTensorIndexCOO将索引列表表示为一个N×M 矩阵其中 N 为非零值个数、M 为稀疏张量的维度数。字段包括indicesType: Int必填索引矩阵中值的类型indicesStrides: [long]索引矩阵的 strides省略时默认行主序indicesBuffer: Buffer必填索引矩阵数据的位置与大小isCanonical: bool为真时索引按字典序行主序排序且无重复条目为假时可能无序或含重复。fbs 注释给出了一个完整示例设 X 为 2×3×4×5 的张量含 6 个非零值其索引矩阵为 4×6X[0, 1, 2, 0] : 1 X[1, 1, 2, 3] : 2 ... indices [[0, 0, 0, 0, 1, 1], [1, 1, 1, 2, 1, 2], [2, 2, 3, 1, 2, 0], [0, 1, 0, 0, 3, 4]]关于isCanonical的排序语义规范特别指出该排序与 TensorFlow 的SparseTensor相同但与 SciPycoo_matrix的规范形式相反SciPy 采用列主序。CSX压缩稀疏矩阵格式仅限二维SparseMatrixIndexCSX是矩阵专用的压缩稀疏格式通过compressedAxis: SparseMatrixCompressedAxis枚举选择压缩行Row即 CSR还是压缩列Column即 CSC。字段包括indptrType: Int必填indptr 数组中值的类型indptrBuffer: Buffer必填行范围索引数组——第 i 行数据从indptr[i]到indptr[i1]数组长度为 1 行数索引值类型为 longindicesType: Int必填indices 数组中值的类型indicesBuffer: Buffer必填非零值对应的列索引数组每行内按字典序排列。fbs 给出了 6×4 矩阵示例X : [[0, 1, 2, 0], [0, 0, 3, 0], ... [0, 9, 0, 0]] values(X) [1, 2, 3, 4, 5, 6, 7, 8, 9] indptr(X) [0, 2, 3, 5, 5, 8, 10] indices(X) [1, 2, 2, 1, 3, 0, 2, 3, 1]注意第 4 行全为零因此indptr中出现相邻相等值5, 5——这正是空行在 indptr 中的自然表达。CSF压缩稀疏纤维格式高维推广SparseTensorIndexCSF是压缩稀疏行CSR索引在高维上的推广递归地将张量的每一维压缩为一组前缀树从根到叶的每条路径构成一个非零索引。实现上由两组 buffer 数组和一个整数数组组成indptrType: Int必填与indptrBuffers: [Buffer]必填存储稀疏结构每两个连续维度对应一个 bufferindptrBuffers[dim][i]与indptrBuffers[dim][i1]界定indicesBuffers[dim1]中某节点的子节点范围indicesType: Int必填与indicesBuffers: [Buffer]必填每个张量维度对应一个 buffer存储节点值axisOrder: [int]必填生成前缀树时各维被遍历的顺序。fbs 中以 2×3×4×5、含 8 个非零值的张量为例展示了前缀树及其三个数组indptrBuffers(X) [[0, 2, 3], [0, 1, 3, 4], [0, 2, 4, 5, 8]] indicesBuffers(X) [[0, 1], [0, 1, 1], [0, 0, 1, 1], [1, 2, 0, 2, 0, 0, 1, 2]] axisOrder(X) [0, 1, 2, 3]CSF 的用途是支持高效的张量分解/运算规范引用了 Smith 2017 年的 KNL 相关工作其设计目标是让高维稀疏张量的存储与遍历更紧凑。C 侧实现对应C 侧 cpp/src/arrow/sparse_tensor.h 实现了class ARROW_EXPORT SparseTensor及SparseTensorCOO、SparseTensorCSR、SparseTensorCSC、SparseTensorCSF等具体类与 fbs 中的 COO / CSXRow/Column/ CSF 一一对应。这也印证了该消息类型是为需要共享稀疏张量的应用准备的 IPC 元数据且实现范围由各语言自行决定。各消息类型的支持状态速览消息类型所属格式状态替代方案Tensor非列式格式已弃用deprecatedRecordBatcharrow.fixed_shape_tensor扩展类型列SparseTensor非列式格式已弃用deprecated目前无推荐替代可在开发邮件列表讨论RecordBatch/Schema/DictionaryBatch列式格式活跃支持—需要强调虽然Tensor/SparseTensor消息已弃用但Flatbuffers 协议定义仍保留在 format/ 目录中MessageHeaderunion 依然包含它们用于向后兼容——读取方即使不支持也能通过 union 元数据识别消息类型并安全跳过这与 Arrow 的前向兼容承诺一致。实践建议传输稠密张量不要使用Tensor消息改为将张量作为arrow.fixed_shape_tensor扩展类型列放入 RecordBatch。这样可复用标准列式 IPC、流式与文件格式且FixedSizeList存储天然支持行主序多元素块。理解稀疏表示若需与遗留系统交互或解析旧数据重点掌握 COO通用、直观、CSX二维矩阵高效与 CSF高维三种索引的 buffer 组织方式以及isCanonical/ indptr 的边界语义。对齐要求若自行构造独立封装消息务必遵守 64 字节对齐Tensor 的数据体SparseTensor 的索引与数据体且整体保持 8 字节对齐的封装格式否则无法保证跨进程/跨流可靠搬移。兼容性考量大多数 Arrow 实现不支持这两类消息因此面向生态互操作时优先使用列式消息承载数据这是官方在 format/Message.fbs 中反复强调的最大兼容性原则。参考依据仓库内格式文档主体docs/source/format/Other.rst列式格式与封装消息规范docs/source/format/Columnar.rstEncapsulated message format一节Flatbuffers 协议定义format/Tensor.fbs、format/SparseTensor.fbs、format/Message.fbs、format/Schema.fbs推荐替代方案docs/source/format/CanonicalExtensions.rstarrow.fixed_shape_tensorC 实现cpp/src/arrow/tensor.h、cpp/src/arrow/sparse_tensor.h【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →