Apache Arrow MATLAB 接口设计解析:从 C++ 内存直通到跨语言零拷贝共享

发布时间:2026/9/14 6:29:57
Apache Arrow MATLAB 接口设计解析:从 C++ 内存直通到跨语言零拷贝共享 Apache Arrow MATLAB 接口设计解析从 C 内存直通到跨语言零拷贝共享【免费下载链接】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 仓库中的 MATLAB 接口设计文档为核心梳理 MATLAB Interface for Apache Arrow 的三大目标用例Arrow 内存交互、文件序列化、跨语言内存共享与arrow.*/arrow::matlab::*双层 API 设计并结合仓库中matlab/目录的真实源码MEX 网关、Proxy 层、arrow.cC Data Interface 封装与测试用例说明该设计在当前代码库中的落地方式、构建流程与验证手段。读完本文你将掌握在 MATLAB 中创建/操作 Arrow 列式内存、读写 Feather 文件以及通过 C Data Interface 与 PyArrow 进行零拷贝数据交换的完整技术路线。一、文档定位与设计目标设计文档 matlab_interface_for_apache_arrow_design.md 给出了 MATLAB 接 Arrow C 库的高层路线图。其核心定位是提供一组打包的arrow.*类和函数让 MATLAB 用户能够直接与 Arrow C 库交互操作 Arrow 内存。文档归纳了三个基础用例为后续更高级的能力打下基础UC1Arrow 内存交互使用 MATLAB 代码创建、访问、删除 Arrow 内存UC2文件读写使用 MATLAB 代码将 Arrow 内存序列化/反序列化到 Parquet、Feather、JSON、CSV 等文件格式UC3跨语言共享将 MATLABtable表示的内存表格数据以最小开销理想情况下零拷贝转移到 Python、R、Rust 等其他语言。文档同时给出了一个高层能力路线图标明各用例的优先级能力用例时间框架Arrow 内存交互Arrow Memory InteractionUC1近期文件读写File Reading/WritingUC2近期进程内/进程外内存共享In/Out-of-Process Memory SharingUC3中期从仓库现状看该路线图已基本落地matlab/README.md 明确列出当前版本已支持的能力——一部分Array类型与 MATLAB 数组类型的互转、MATLABtable与arrow.tabular.RecordBatch的互转、Field/Schema/Type的创建以及 Feather V1 文件的读写。二、双层 API 设计MATLAB 层与 C 层设计文档提出的 API 面分为两层这一“MATLAB 类 MEX/C 包装”的分层结构在仓库源码中得到了一一对应。2.1 MATLAB API文档规划暴露给 MATLAB 用户的 API 包括arrow.Buffer、arrow.Array、arrow.RecordBatch、arrow.Table、arrow.Field、arrow.Schemaarrow.type.DataType及其具体子类arrow.type.Float64、arrow.type.String、arrow.type.Date、arrow.type.Time等arrow.memory.getTotalBytesAllocated、arrow.memory.allocateBuffer等内存管理函数当前仓库matlab/src/matlab/arrow/目录下实现了其中的主体array/含Float64Array.m、Int8Array.m、StringArray.m、ListArray.m等 20 余个数组类、tabular/RecordBatch.m、Table.m、Schema.m、type/Type.m、Field.m及各具体类型、buffer/Buffer.m等与文档设计高度吻合。2.2 C APIwrap/unwrap文档强调为了让 MATLAB 与 Arrow C 库交互接口必须暴露一组用于在 MATLABmxArray数据与 Arrow C 类型之间进行包装/解包的 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在源码中这一层落在 matlab/src/cpp/arrow/matlab/proxy/wrap.harrow::matlab::proxy命名空间提供了wrap()与wrap_and_manage()两组重载分别针对arrow::Array与arrow::DataType后者会额外把代理对象注册进 ProxyManager并返回一个包含ProxyIDuint64和TypeIDint32两个字段的mda::StructArray回传给 MATLAB 一侧。从源码结构看MATLAB 类并不直接持有 C 对象指针而是持有一个隐藏的Proxy句柄对象例如 Writer.m 中的properties(Hidden, SetAccessprivate) Proxy真正的 Arrow C 对象由 MEX 进程侧的 ProxyManager 统一托管。MEX 入口实现在 gateway.cc各功能域array/、tabular/、io/feather/、io/ipc/、io/csv/、c/都有对应的 proxy 子目录。这种“MATLAB 端薄壳 C 端代理管理器”的架构正是文档中 wrap/unwrap 设计的具体工程化。三、UC1Arrow 内存交互3.1 工厂函数arrow.array与类型分派文档的 UC1 设计MATLAB 开发者可以从“普通”的 MATLAB 数组例如double类型的数值行向量创建arrow.Array然后对它进行索引/切片、获取类型、从工作区清除等操作。arrow.array工厂函数根据输入数组的 MATLAB 类型返回抽象类arrow.Array的类型特定具体子类——例如传入 double 数组会返回arrow.Float64Array。文档中的原始示例 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.一个关键语义在文档中专门标注MATLAB 的 missing 值NaN、NaT、undefined在构造arrow.Array子类实例时会自动转换为 ArrowNULL。这解释了为什么示例中把第 4 个元素设为NaN后切片显示为NULL。该工厂函数在仓库中的实现见 array.m先调用convertCellstrToString把 cellstr 归一化为 string 数组然后按class(data)的 switch 分支分派到对应的fromMATLAB静态方法logical→arrow.array.BooleanArrayuint8~uint64、int8~int64→ 对应UInt*/Int*Arraysingle/double→Float32Array/Float64Arraystring→StringArraydatetime→TimestampArrayduration→Time64Arraytable→StructArraycell→ListArray其他类型抛出arrow:array:UnsupportedMATLABType错误matlab/README.md 中给出了完整的 MATLAB/Arrow 类型映射表datetime还可映射到Date32Array/Date64Arrayduration可映射到Time32Array并演示了构造时显式指定 validity 掩码的用法matlabArray int8([122, -1, 456, -10, 789]); validElements matlabArray 0; % 逻辑有效性掩码 arrowArray arrow.array(matlabArray, ValidvalidElements); % Int8Array with 5 elements and 2 null values: % 122 | null | 127 | null | 127反向转换则通过toMATLAB(arrowArray)完成例如把BooleanArray转回logical数组。四、UC2文件序列化工作流4.1 标准工作流table → Table → Writer → Feather 文件文档给出的写入流程分两步。第一步把 MATLABtable直接转换为 Arrow 表格对象文档写作arrow.tabular.Table通过arrow.table之类函数完成 Weight [10; 24; 10; 12; 18]; Radius [80; 135; 65; 70; 150]; Density [10.2; 20.5; 11.2; 13.7; 17.8]; % Create a MATLAB table T table(Weight, Radius, Density); % Create an arrow.tabular.Table from the MATLAB table AT arrow.table(T);第二步构造arrow.internal.io.feather.Writer并写入磁盘% 从 Table 生成 RecordBatch recordBatch arrow.recordBatch(AT); filename data.feather; % 以 Feather V1 格式写出 writer arrow.internal.io.feather.Writer(filename); writer.write(recordBatch);读回同样通过arrow.internal.io.feather.Reader reader arrow.internal.io.feather.Reader(filename); newBatch reader.read(); % Read in the first RecordBatch AT table(newBatch); % 转回 MATLAB table当前仓库中这一流程有可直接运行的高层封装 featherwrite.mfeatherwrite(filename, t)内部依次执行arrow.recordBatch(t)→ 构造arrow.internal.io.feather.Writer→writer.write(recordBatch)与设计文档描述完全一致。值得注意的演进细节是该函数目前会发出弃用警告建议改用arrow.io.ipc.RecordBatchFileWriter写 Feather V2即 Arrow IPC文件——这说明仓库实现已经走到了文档“Near Term”路线图之后。对应的 MATLAB 侧类为 Writer.m其构造函数通过arrow.internal.proxy.create(arrow.io.feather.proxy.Writer, args)创建 C 代理write方法只传递RecordBatchProxyID句柄跨语言数据传递全部走句柄而非复制数据。C 侧代理实现位于 writer.cc 与 reader.cc。round-trip 测试可在 tRoundTrip.m 与 tfeather.m 中查看验证写盘—读回的一致性。4.2 高级用户工作流用 MEX 实现新的文件支持文档还描述了一条面向高级用户的扩展路径要新增 Feather V1 写支持用户需要编写一个 MEX 函数例如featherwriteMEX在其中用arrow::matlab::unwrap_table把 MATLAB 表示的 Arrow 内存arrow.Table解包为 C 的arrow::Table再交给 Arrow C 库的对应 API如arrow::ipc::feather::WriteTable完成落盘读取方向可类比实现arrow.internal.io.feather.Reader。4.3 面向普通用户的高层接口文档总结道MATLAB 接口暴露的大量 API 是面向高级用户的“构建块”高级用户可以用这些积木搭出面向日常用户的高层接口featherwrite就是例子。仓库中 featherwrite.m / featherread.m 正是这种分层理念的产物用户只需featherwrite(data.feather, T)底层则由 RecordBatch 代理 → Feather 代理 Writer → Arrow C IPC 库逐层完成。五、UC3跨语言内存共享文档将本地内存共享划分为进程内与进程外两类分别依托 Arrow C Data Interface 与 Arrow IPC 文件格式。5.1 进程内共享C Data Interface 零拷贝桥接MATLAB 支持在其进程内运行 Python 代码py引擎。由于 MATLAB 与 Python 共享同一虚拟地址空间可借助 Apache Arrow C Data Interface——一种在同一个虚拟地址空间内跨语言共享 Arrow 数据与元数据的轻量 C API——高效交换内存。该接口由两个 C 风格结构体ArrowArray数据与ArrowSchema元数据组成。MATLAB → PyArrow 方向把arrow.Array导出的 C 结构体内存地址直接传给 Python由pyarrow.Array._import_from_c静态方法包装成pyarrow.Array全程无底层数据拷贝。Python 侧脚本与 MATLAB 文件同目录# Filename: import_from_c.py import pyarrow as pa array pa.Array._import_from_c(arrayMemoryAddress, schemaMemoryAddress)MATLAB 侧 AA arrow.array([1, 2, 3, 4, 5]); % 创建 C Data Interface 结构体的容器 cArray arrow.c.Array(); cSchema arrow.c.Schema(); % 导出取得 ArrowArray / ArrowSchema 的内存地址 AA.export(cArray.Address, cSchema.Address); % 用 pyrunfile 执行外部 Python 脚本完成导入 PA pyrunfile(import_from_c.py, array, arrayMemoryAddresscArray.Address, schemaMemoryAddresscSchema.Address);PyArrow → MATLAB 方向Python 侧调用PA._export_to_c(arrayMemoryAddress, schemaMemoryAddress)填充 C 结构体# Filename: export_to_c.py import pyarrow as pa PA._export_to_c(arrayMemoryAddress, schemaMemoryAddress)MATLAB 侧再把地址交给静态导入方法构造出零拷贝的arrow.Array PA py.pyarrow.array([1, 2, 3, 4, 5]); cArray arrow.c.Array(); cSchema arrow.c.Schema(); pyrunfile(export_to_c.py, PAPA, arrayMemoryAddresscArray.Address, schemaMemoryAddresscSchema.Address); AA arrow.array.Array.import(cArray, cSchema);文档特别指出一个 MATLAB 语言的坑_export_to_c/_import_from_c以下划线开头而 MATLAB 变量/成员名不允许以下划线开头因此这些 Python 调用无法在 MATLAB 中直接发起只能借助pyrunfile执行外部脚本间接完成。在仓库中arrow.c包的实际实现印证了这一设计c/Array.m 注释明确其“Wrapper for an Arrow C Data Interface format ArrowArray C struct pointer”对外暴露一个只读的Address(1,1) uint64属性由 C 代理arrow.c.proxy.Array的getAddress()返回arrow.c.Schema同构。C 侧对应 matlab/src/cpp/arrow/matlab/c/proxy/ 下的 4 对头文件/实现文件。往返正确性由 tRoundTrip.m、tRoundTripRecordBatch.m 等 C Data Interface 往返测试覆盖。5.2 进程外共享内存映射的 Arrow IPC 文件针对多进程“数据处理流水线”中的大表文档给出第二种方案把arrow.Table序列化为Arrow IPC 文件格式再由另一个进程中运行 PyArrow 以内存映射zero-copy方式读取。由于 Arrow IPC 文件格式是内存中 Arrow 格式在磁盘上的 1:1 映射内存映射后几乎无需自定义反序列化/转换即可构造pyarrow.Table因此开销极低。文档示例% 构造 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); % 写为 Arrow IPC 文件 recordBatch arrow.recordBatch(AT); filename data.arrow; writer arrow.io.ipc.RecordBatchFileWriter(filename, recordBatch.Schema); writer.writeRecordBatch(recordBatch); writer.close(); % Close the writer -- dont forget this step! % 在独立 Python 进程中运行 pyenv(ExecutionMode, OutOfProcess); % 内存映射 IPC 文件 memoryMappedFile py.pyarrow.memory_map(data.arrow); recordBatchFileReader py.pyarrow.ipc.open_file(memoryMappedFile); PAT recordBatchFileReader.read_all(); % 一次性读回 pyarrow.Table仓库中的 matlab/src/matlab/arrow/io/ipc/5 个类文件与 C 侧 matlab/src/cpp/arrow/matlab/io/ipc/ 实现了RecordBatchFileWriter/RecordBatchStreamReader等 IPC 读写类配套测试见 tRecordBatchWriter.m、tRecordBatchFileReader.m、tRecordBatchStreamReader.m。六、测试、文档与安装6.1 测试基础设施文档要求至少包含三层测试保障MATLAB Class-Based Unit Tests——测试类放在test/目录如 tArray.m、tBuffer.m、tTable.m、类型特性测试 traits/内部 C 代码通过 MEX 函数从 MATLAB 单元测试中调用tGateway.m 即直接测 MEX 网关MATLAB CI Workflows——仓库根目录compose.yaml与 CI 脚本 matlab_build.sh / matlab_test.sh 支撑持续构建与测试Integration Testing——遵循 Arrow 生态的集成测试规范。更多细节见设计文档引用的 测试规范。本地运行方式为在arrow/matlab目录下启动 MATLAB 后执行 runtests(test, IncludeSubFolderstrue);6.2 文档要求文档列出的文档范围包括MATLAB Help Text、API reference、MATLAB 与 C API 使用示例、构建与安装 README、构建系统文档、CI 集成文档。仓库中 matlab/README.md 已覆盖状态说明、类型映射表、前置条件、构建/安装/测试与大量可复制运行的使用示例。6.3 安装与构建文档的理想目标是让用户无需手动编译 MEX 即可安装类比 JavaScript 用户经npm安装apache-arrow、Rust 用户经cargo安装arrowcrate走 MATLAB Add-On Explorer 渠道短期内则维护清晰的构建说明并通过 CI 定期产出 Windows/macOS/Linux 的预构建 MEX。结合仓库实际当前构建流程由 matlab/CMakeLists.txt 定义可确认的关键事实要求 CMake ≥ 3.25、C20 编译器先find_package(Arrow QUIET)找不到 Arrow 时通过ExternalProject_Add从 cpp/ 源码目录现场构建 Arrow C 库CMakeLists.txt#L21-L99通过find_package(Matlab REQUIRED COMPONENTS MAIN_PROGRAM)定位 MATLAB 头文件与libmex编译 MEX 网关安装目录为${CMAKE_INSTALL_PREFIX}/arrow_matlab安装时把 src/matlab/ 整树拷入并自动把安装目录加入 MATLAB Search Path由 CMake 开关MATLAB_ADD_INSTALL_DIR_TO_SEARCH_PATH默认 ON或MATLAB_ADD_INSTALL_DIR_TO_STARTUP_FILE默认 OFF写入 userpath 的startup.m控制见 CMakeLists.txt#L234-L270版本变量为MLARROW_VERSION 26.0.0-SNAPSHOT。命令行操作流程与 matlab/README.md 一致$ cmake -S . -B build $ cmake --build build --config Release $ cmake --build build --config Release --target install若因文件系统权限导致自动加入 Search Path 失败可用addpath手动添加安装目录。七、小结设计与实现的对齐情况从设计文档到仓库代码的映射关系可以概括为三条主线UC1 已落地arrow/array/ 提供全部数值/布尔/字符串/时间/结构体/列表数组类array.m 工厂函数按 MATLAB 类名分派NaN 等 missing 值语义与文档一致UC2 已落地并演进featherwrite.m/featherread.m 与 io/feather/ 代理实现了文档的 Feather 工作流且已引导用户迁移到arrow.io.ipc.RecordBatchFileWriterFeather V2/IPCUC3 以 C Data Interface 落地arrow/c/ 的Array/Schema地址容器 arrow.c.proxy.*C 代理实现了文档中的arrow.c.Array/arrow.c.Schema配合pyrunfile绕过 MATLAB 下划线命名限制往返测试 tRoundTrip.m 保证跨语言数据一致性进程外路径则由io/ipc/的 RecordBatch 文件/流读写器支撑。整体架构上MATLAB 端类只持有 Proxy 句柄C 端由 MEX 网关gateway.cc与 ProxyManager 统一管理 Arrow C 对象的生命周期这正是文档中wrap_*/unwrap_*C API 一节所设想的工程形态也保证了clear一个 MATLAB 对象时能正确释放 C 侧 Arrow 内存——文档 UC1 示例末尾clear AA注释“释放 Arrow C 内存”的承诺由此得到架构层面的保障。【免费下载链接】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),仅供参考