ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于 Apache Arrow 的 MATLAB 接口设计指南:从 arrow.* 包到跨语言零拷贝内存共享

基于 Apache Arrow 的 MATLAB 接口设计指南:从 arrow.* 包到跨语言零拷贝内存共享 基于 Apache Arrow 的 MATLAB 接口设计指南从 arrow.* 包到跨语言零拷贝内存共享【免费下载链接】arrowApache Arrow is a multi-language toolbox for accelerated data interchange and in-memory processing项目地址: https://gitcode.com/gh_mirrors/arrow13/arrowApache Arrow 是一个面向加速数据交换与内存分析的跨语言工具箱其 MATLAB 接口MATLAB Interface for Apache Arrow旨在让 MATLAB 用户直接创建、访问与释放 Arrow 内存并通过 Arrow 生态的列式内存格式与文件格式Feather、Parquet、IPC同 Python、R、Rust 等语言高效互通。本文以仓库中的设计文档 matlab/doc/matlab_interface_for_apache_arrow_design.md 为主线结合matlab/目录下的真实源码完整讲解其设计动机、API 骨架、三大核心用例UC1/UC2/UC3的落地路径以及测试、文档与安装规划帮助读者掌握该接口的设计全貌与工程实现细节。设计背景与目标设计文档将 Apache Arrow 的列式分析能力定位为构建 MATLAB 接口的出发点并明确聚焦三个为未来更高级用例奠基的核心场景UC1使用 MATLAB 代码创建、访问和删除 Arrow 内存。UC2使用 MATLAB 代码将 Arrow 内存序列化/反序列化到 Parquet、Feather、JSON、CSV 等文件格式。UC3将以 MATLABtable表示的内存表格数据以最小开销理想情况下为零拷贝迁移到 Python、R、Rust 等其他语言。这三个用例共同决定了接口的形态既要有面向普通用户的数组与表格对象模型也要有面向文件读写的 IO 能力还要有面向跨语言内存共享的 C 级互操作层。总体设计arrow.*包与 C 包装层设计文档设想了一套以arrow.*命名的包化类与函数使用户能够通过 MATLAB 代码与 Arrow C 库的核心功能交互。这一设计在当前仓库中已经落地为matlab/src/matlab/arrow/目录下的真实实现MATLAB 中前缀目录即对应包命名空间。MATLAB API 骨架文档列出的 MATLAB API 与仓库实际实现的对应关系如下设计文档中的 API仓库中的实际路径arrow.Buffermatlab/src/matlab/arrow/buffer/Buffer.marrow.Arraymatlab/src/matlab/arrow/array/Array.marrow.RecordBatchmatlab/src/matlab/arrow/tabular/RecordBatch.marrow.Tablematlab/src/matlab/arrow/tabular/Table.marrow.Field/arrow.Schemamatlab/src/matlab/arrow/type/Field.m、matlab/src/matlab/arrow/tabular/Schema.marrow.type.DataType及子类matlab/src/matlab/arrow/type/Type.m 及其下Float64Type.m、StringType.m、Date32Type.m、Time32Type.m、TimestampType.m等arrow.memory.*对应 C 侧内存分配MATLAB 侧以arrow.buffer.Buffer的fromMATLAB静态工厂等方式呈现从实现看arrow.type包下提供了完整的数据类型体系包括BooleanType、NumericTypeFloat32/64、Int8/16/32/64、UInt8/16/32/64、StringType、ListType、StructType、TemporalTypeDate32/64、Time32/64、Timestamp以及配套的traits目录用于把类型 ID 映射到对应的数组代理类与构造器——这正对应文档中返回类型特定的、arrow.Array抽象类的具体子类的描述。C API 设计为了让 MATLAB 与 Arrow C 库交互设计文档提出需要一组用于在 MATLABmxArray与 Arrow C 类型之间包装/解包wrap/unwrap的 C API例如arrow::matlab::is_array/is_record_batch/is_tablearrow::matlab::unwrap_array/wrap_arrayarrow::matlab::unwrap_record_batch/wrap_record_batcharrow::matlab::unwrap_table/wrap_table需要说明的是从当前仓库的 C 源码结构看matlab/src/cpp/arrow/matlab/最终落地时采用了一种代理proxy模式而非文档示例中的unwrap/wrap命名C 侧按功能域组织为array/proxy/、tabular/proxy/含table.cc、record_batch.cc、schema.cc、buffer/proxy/、type/proxy/、io/feather/proxy/、io/ipc/proxy/、io/csv/proxy/、c/proxy/等模块并通过mex/gateway.cc与proxy/factory.cc统一注册MATLAB 侧则通过libmexclass.proxy.Proxy持有对应 C 代理的 ID 来调用底层能力。文档中的unwrap/wrap是设计阶段的功能示意其把 MATLAB 对象解析为 Arrow C 对象的语义在 proxy 实现中得到等价承接。用例详解一UC1用 MATLAB 代码创建与操作 Arrow 内存文档描述了 UC1 的核心场景MATLAB 开发者可以用普通的 MATLAB 数组例如double类型的数值行向量创建arrow.Array然后对其进行索引/切片、获取类型、从工作区清除等操作。arrow.array工厂函数会根据输入数组的 MATLAB 类型返回arrow.Array抽象类的类型特定具体子类。arrow.array工厂函数的分发逻辑仓库中的 matlab/src/matlab/arrow/array.m 完整实现了这一分发机制logical→arrow.array.BooleanArrayuint8/16/32/64→ 对应的UInt*Arrayint8/16/32/64→ 对应的Int*Arraysingle→Float32Arraydouble→Float64Arraystring以及cellstr通过convertCellstrToString支持→StringArraydatetime→TimestampArrayduration→Time64Arraytable→StructArraycell→ListArray其他类型抛出arrow:array:UnsupportedMATLABType错误例如向arrow.array传入double数组会得到arrow.Float64Array与文档示例一致。missing 值自动转为 Arrow NULL文档特别指出MATLAB 的missing值如NaN、NaT、undefined在构造arrow.Array子类实例时会自动转换为 Arrow 的NULL值。这一点在源码中也有迹可循matlab/src/matlab/arrow/array/Array.m 暴露了Valid有效性位图依赖属性并通过NumElements与Valid统计NumNulls用于显示头信息底层代理C 侧array/proxy/负责把 MATLAB 的缺失值编码进 Arrow 的有效性位图中。文档示例的完整运行设计文档给出了一个可复现的 MATLAB 会话示例 A randi(100, 1, 5) A 82 91 13 92 64 class(A) ans double A(4) NaN; % Set the fourth element to NaN. AA arrow.array(A); % Create an arrow.Array from A. class(AA) ans arrow.Float64Array AA(3:5) % Extract elements at indices 3 to 5 from AA. ans 13 NULL 64 clear AA; % Clear AA from workspace and release Arrow C memory.索引AA(3:5)得到13 NULL 64其中索引 4 处正是NaN被转换为 ArrowNULL后的显示结果。clear AA会释放底层 C 代理从而回收 Arrow C 内存。从源码看Array.m中的NumElements、Valid、Type三个依赖属性为这类操作提供了基础元数据toString/displayScalarObject实现了带NULL标记的展示逻辑。用例详解二UC2MATLAB 数据与 Feather 等文件格式的序列化UC2 的目标是让 MATLAB 数据能够通过 Arrow 内存序列化到磁盘文件如 Feather、Parquet并能读回。设计文档给出了从 MATLABtable到 Feather 文件的完整开发流程。方式一用arrow.Array组合成arrow.Table开发者可以先为每个表变量构造arrow.Array再组合成arrow.Table Var1 arrow.array([foo; bar; baz]); Var2 arrow.array([today; today 1; today 2]); Var3 arrow.array([10; 20; 30]); AT arrow.Table(Var1, Var2, Var3);方式二直接从 MATLABtable转换文档设想了arrow.matlab2arrow这样的转换函数从当前仓库实现看这一职责由 matlab/src/matlab/arrow/table.m 承担——它接收一个 MATLABtable通过istable校验调用arrow.tabular.internal.decompose将各列拆解为arrow.Array收集列名后创建arrow.tabular.Table代理 Weight [10; 24; 10; 12; 18]; Radius [80; 135; 65; 70; 150]; Density [10.2; 20.5; 11.2; 13.7; 17.8]; T table(Weight, Radius, Density); % Create a MATLAB table AT arrow.table(T); % Create an arrow.Table反向转换则由 matlab/src/matlab/arrow/tabular/Table.m 的table()/toMATLAB()方法完成它逐列取出ChunkedArray并调用toMATLAB再用makeValidVariableNames与makeValidDimensionNames生成合法的 MATLAB 变量名与维度名后组装回 MATLABtable。写入与读取 Feather 文件文档示例中通过arrow.FeatherTableWriter写入、通过arrow.FeatherTableReader读取 featherTableWriter arrow.FeatherTableWriter(); featherTableWriter.write(AT, data.feather); featherTableReader arrow.FeatherTableReader(data.feather); AT featherTableReader.read();在当前仓库中Feather 读写的底层实现位于 C 侧 matlab/src/cpp/arrow/matlab/io/feather/proxy/writer.cc 与reader.cc基于 Arrow C 的arrow::ipc::feather能力MATLAB 侧则由 matlab/src/matlab/arrow/internal/io/feather/Writer.m 等内部类封装同时在包根目录提供了面向普通用户的顶层函数 matlab/src/matlab/featherwrite.m 与 matlab/src/matlab/featherread.m这正是下文高级工作流中设想的featherwrite高层接口。高级用户工作流编写 MEX 函数扩展写入能力文档指出要新增写入 Feather 文件这类能力高级 MATLAB 用户需要编写一个可被 MATLAB 直接调用的MEX 函数例如featherwriteMEX在 MEX 函数内部使用arrow::matlab::unwrap_table把 MATLAB 侧的arrow.Table转换为 C 侧的arrow::Table将 Carrow::Table交给 Arrow C 库的写入 API如arrow::ipc::feather::WriteTable完成落盘。读取方向arrow.FeatherTableReader遵循相同思路。这与仓库中 C 侧按proxy 面向 MEX 的 gateway组织的方式一致mex/gateway.cc是 MEX 入口的枢纽各功能域的 proxy 类持有真实的 Arrow C 对象MATLAB 调用经libmexclass代理转发到这些 proxy 方法。赋能高层工作流设计文档的核心思想是分层面向高级用户的构建块 APIarrow.*类与 C API面向日常用户的薄封装如featherwrite。文档用一张代码流图Code flow diagram总结了高级用户需要创作的各个部分——从arrow.Table解包、MEX 函数、调用 Arrow C 写入 API再到暴露给普通 MATLAB 用户的高层函数。当前仓库 matlab/src/matlab/featherwrite.m 与featherread.m的存在即是该高层工作流设计的直接产物测试方面matlab/test/tfeather.m 以及matlab/test/arrow下的用例对读写往返roundtrip进行了验证。用例详解三UC3进程内与进程外的内存共享Arrow 支持多种本地内存共享方式文档将其划分为两大类进程内内存共享In-Process Memory Sharing进程外内存共享Out-of-Process Memory Sharing进程内共享借助 Arrow C Data Interface 与 PyArrow 零拷贝互通MATLAB 支持在 MATLAB 进程内运行 Python 代码因此 MATLAB 与 Python 共享同一虚拟地址空间理论上可以在两者之间高效共享 Arrow 内存。Arrow 为此定义了C Data Interface——一套轻量级的 C API用于在同一地址空间内的多种语言之间共享 Arrow 数据与元数据。其核心是两个 C 风格结构体ArrowArray表示 Arrow 数据内容遵循 Arrow Columnar FormatArrowSchema表示相关的元数据类型、字段等。MATLAB → PyArrow 方向调用arrow.Array的exportToCDataInterface方法把数组导出为 C Data Interface 格式得到两个结构体的内存地址这些地址可以直接传给 Python不复制底层数据再通过pyarrow.Array._import_from_c构造pyarrow.Array% Create a MATLAB arrow.Array. AA arrow.array([1, 2, 3, 4, 5]); % Export the MATLAB arrow.Array to the C Data Interface format, returning the % memory addresses of the required ArrowArray and ArrowSchema C-style structs. [arrayMemoryAddress, schemaMemoryAddress] AA.exportToCDataInterface(); % Import the memory addresses of the C Data Interface format structs to create a pyarrow.Array. PA py.pyarrow.Array._import_from_c(arrayMemoryAddress, schemaMemoryAddress);PyArrow → MATLAB 方向先用pyarrow.Array._export_to_c导出再把地址交给arrow.Array.importFromCDataInterface静态方法零拷贝构造 MATLABarrow.Array% Make a pyarrow.Array. PA py.pyarrow.array([1, 2, 3, 4, 5]); % Create ArrowArray and ArrowSchema C-style structs adhering to the Arrow C Data Interface format. array py.pyarrow.cffi.ffi.new(struct ArrowArray*) arrayMemoryAddress py.int(py.pyarrow.cffi.ffi.cast(uintptr_t, array)); schema py.pyarrow.cffi.ffi.new(struct ArrowSchema*) schemaMemoryAddress py.int(py.pyarrow.cffi.ffi.cast(uintptr_t, schema)); % Export the pyarrow.Array to the C Data Interface format, populating the required ArrowArray and ArrowShema structs. PA.export_to_c(arrayMemoryAddress, schemaMemoryAddress) % Import the C Data Interface structs to create a MATLAB arrow.Array. AA arrow.Array.importFromCDataInterface(arrayMemoryAddress, schemaMemoryAddress);第二个示例改编自 PyArrow 的test_cffi.py测试用例。在仓库源码中这一互操作能力有完整的实现支撑MATLAB 侧 matlab/src/matlab/arrow/c/Array.m 是 C Data Interface 中ArrowArray结构体指针的包装提供Address属性arrow.c.Schema对应ArrowSchemaArray.m 的export(obj, cArrowArrayAddress, cArrowSchemaAddress)方法把地址传给代理执行导出而静态方法importArray.m借助arrow.c.internal.ArrayImporter完成导入C 侧 matlab/src/cpp/arrow/matlab/c/proxy/array.cc、array_importer.cc、schema.cc则直接操作ArrowArray/ArrowSchema结构体并接入 Arrow C 的 C Data Interface 支持。进程外共享内存映射 IPC 文件对于多进程数据处理流水线中的大表文档推荐将arrow.Table序列化为Arrow IPC File Format再由独立进程中的 PyArrow 对文件做内存映射memory-mapped零拷贝读取。由于 IPC File Format 与内存中的 Arrow 格式是磁盘上 1:1 的映射内存映射读取无需自定义反序列化/转换即可构造pyarrow.Table性能极高。% Create a MATLAB arrow.Table. Var1 arrow.array([foo, bar, baz]); Var2 arrow.array([today, today 1, today 2]); Var3 arrow.array([10, 20, 30]); AT arrow.Table(Var1, Var2, Var3); % Write the MATLAB arrow.Table to the Arrow IPC File Format on disk. arrow.ipcwrite(AT, data.arrow); % Run Python in a separate process. pyenv(ExecutionMode, OutOfProcess); % Memory map the Arrow IPC File. memoryMappedFile py.pyarrow.memory_map(data.arrow); % Construct pyarrow.ipc.RecordBatchFileReader to read the Arrow IPC File. recordBatchFileReader py.pyarrow.ipc.open_file(memoryMappedFile); % Read all record batches from the Arrow IPC File in one-shot and return a pyarrow.Table. PAT recordBatchFileReader.read_all()文档设想的arrow.ipcwrite在仓库中的对应实现是 matlab/src/matlab/arrow/io/ipc/RecordBatchFileWriter.m它接受文件名与arrow.tabular.Schema构造提供writeRecordBatch、writeTable以及按输入类型自动分发的write方法并在close时关闭底层文件读取方向对应 RecordBatchFileReader.m。C 侧 matlab/src/cpp/arrow/matlab/io/ipc/proxy/record_batch_file_writer.cc 与record_batch_file_reader.cc封装了 Arrow C 的 IPC 读写能力实现writeTable时会把 MATLAB 的arrow.Table代理转换为 Carrow::Table后再写入——与 UC2 中unwrap 后调用 C API的思想一脉相承。测试、文档与安装策略测试基础设施设计文档要求至少包含三类测试基础设施MATLAB 类化单元测试Class-Based Unit Testsmatlab/test/目录即为此服务其中tfeather.m等测试文件覆盖 Feather 读写等核心功能MATLAB CI 工作流仓库ci/docker/与ci/scripts/中与 MATLAB 相关的构建/测试脚本如c_glib_test.sh等配套完成持续集成集成测试Integration Testing文档建议参考 Apache Arrow 官方的集成测试格式验证跨语言的一致性。实现要点为了测试内部 C 代码可以用 MEX 函数从 MATLAB 类化单元测试中调用 C 代码——这与 UC2 中MEX 函数作为 MATLAB 与 C 桥梁的设计完全一致。文档规划为保证可用性、可发现性与可访问性设计文档规划了以下文档工作MATLAB API 的Help TextMATLAB API 参考手册MATLAB 与 C API 的使用示例面向构建与安装的 README构建系统文档CI 集成文档。安装方式文档的长期目标是让 MATLAB 用户无需编译 MEX 函数或进行任何手动配置即可安装其机制与 JavaScript 用户通过npm安装apache-arrow、Rust 用户通过cargo安装arrowcrate 类似——即通过 MATLAB 的Add-On Explorer安装可选软件包。在尚无可直接安装的 MATLAB Add-On 的短期阶段规划包括在仓库中维护最新、清晰、面向近期 MATLAB 版本的构建与安装说明即 matlab/README.md 与 matlab/CMakeLists.txt 所承载的内容通过 CI 工作流为 Windows、Mac、Linux 定期构建预编译的 MEX 函数让用户无需手动从头构建 MEX 接口即可体验最新功能。路线图设计文档以一张路线图表总结各能力的开发计划CapabilityUse CaseTimeframeArrow Memory InteractionUC1Near TermFile Reading/WritingUC2Near TermIn/Out-of-Process Memory SharingUC3Mid Term对照当前仓库的代码成熟度可以推断UC1 与 UC2 所依赖的数组体系、arrow.table/Table、Feather 读写featherwrite/featherread与 IPC 读写arrow.io.ipc.*已经具备完整实现UC3 所依赖的 C Data Interface 导入/导出arrow.c.Array、Array.export、Array.import也已在 C 与 MATLAB 双层落地。整体上设计文档描绘的包化 API proxy 式 C 桥接 高层薄封装的三层架构在仓库中均有对应的工程实体可供读者进一步深入研读。【免费下载链接】arrowApache Arrow is a multi-language toolbox for accelerated data interchange and in-memory processing项目地址: https://gitcode.com/gh_mirrors/arrow13/arrow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表