尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

ROS2 的零拷贝与共享内存:可能没你想象的有用

ROS2 的零拷贝与共享内存:可能没你想象的有用 1. 引言在 ROS2 的实时控制、传感器融合等场景中话题通信延迟往往是系统性能的瓶颈。很多开发者把「零拷贝」和「共享内存」视为降低延迟的灵丹妙药认为只要用上它们延迟就能大幅下降。然而实际效果可能远没有你想象的那么有用有的方案支持不完整、问题一堆有的方案只对特定消息类型有效还有的方案在多数场景下甚至不如默认的 UDP 传输。本文将从机制原理出发分别梳理 ROS2 中零拷贝的两种形态、共享内存在三大 RMW 实现Fast DDS、Cyclone DDS、Zenoh中的支持情况。2. 先厘清概念零拷贝 ≠ 共享内存很多资料把两者混用但严格来说零拷贝Zero-Copy是一种数据传递方式目标是减少数据在内存中的复制次数。它可以通过共享内存实现也可以通过消息对象所有权转移实现甚至可以在同一进程内直接传递指针。共享内存Shared Memory是一种底层通信载体即多个进程/节点通过映射同一块物理内存来交换数据。用了共享内存也不代表就零拷贝了比如ROS2从rcl用户代码到底层DDS就可能仍然有拷贝而DDS内部话题通信可以是udp、tcp或者共享内存。3. ROS2中的“零拷贝”有两种ROS2 中的「零拷贝」实际上包含两层3.1 形态一RMW 到 DDS 层的零拷贝Loaned Message这是从rmw层到 DDS 层的零拷贝通过Loaned MessageAPI 实现。原理默认情况下publish()会把用户数据拷贝进 DDS 中间件的发送缓冲区take()时又会从接收缓冲区拷贝到用户内存。Loaned Message 允许用户直接借用 DDS 内部缓冲区进行读写省去这两次拷贝。配置方式需要 RMW 实现支持 loaned message且发布方和订阅方都要显式使用LoanedMessageAPI。现状支持情况一塌糊涂问题很多实际价值有限。不同 RMW 对 loaned message 的支持程度不一致目前只有fastdds支持且subscriber端存在问题是默认关闭的。官方文档也明确指出这一特性仍处于演进阶段很多实现并不完整。关键限制Loaned Message只支持 PODPlain Old Data类型消息也就是固定大小fixed-size的消息。像string、点云、图像这类含有动态数组/可变长度字段的消息底层无法直接借用 DDS 缓冲区都不支持零拷贝。如果确实想对这类大数据走零拷贝只能改用固定长度的自定义消息如ros2_shm_msg但这类消息与标准话题消息不兼容会破坏与其它节点的互操作性实际工程中往往得不偿失。来源ROS2 官方文档About QoS 与 Zero-Copy 相关章节ros2/rmw 仓库 README 中关于 loaned message 的说明ros2/ros2 仓库相关 issue 中关于 loaned message 支持不完整的讨论3.2 形态二同进程内多节点通信Intra-Process Composable Node这是 ROS2 中真正实用、效果显著的零拷贝形态适用于同一进程内的多个节点通信。原理当use_intra_process_commtrue时同进程内的节点通信完全跳过 DDS直接在进程内转移消息对象的所有权。此时根本没有 DDS 参与也就没有序列化/反序列化和网络拷贝的开销。实现方式使用Composable Node可组合节点通过component_container加载多个节点到同一进程。这与 ROS1 的Nodelet机制非常相似。进一步优化在 intra-process 模式下还可以额外开启零拷贝——通过unique_ptr传递消息对象避免在进程内再次拷贝。用法与 ROS1 Nodelet 的boost::shared_ptr零拷贝传递类似。关键点这种形态下没有 DDS 的事是 ROS2 框架在进程内直接转移消息对象。它才是 ROS2 官方推荐、实际可用的零拷贝方案。来源ROS2 官方文档Intra-Process Communicationros2/rclcpp 仓库 README 中关于 Composable Node 的说明ros2/rclcpp 仓库IntraProcess 相关源码与文档4. 共享内存三大 RMW 的支持现状ROS2使用的底层DDS或者zenoh都有各自的共享内存方式替换udp通信或者tcp在不同 RMW 实现中的支持情况差异巨大。下面分别说明。4.1 Fast DDSROS2 默认 RMW默认情况Fast DDS 是 ROS2 的默认 RMW默认开启共享内存传输Shared Memory Transport。关键限制默认的共享内存 segment 大小仅为256KB。对于超过该大小的消息如图像、点云可能会延迟和丢包。配置方式可以通过 XML 配置文件调整共享内存 segment 大小但需要手动修改 Fast DDS 的配置文件并正确加载。来源eProsima/Fast-DDS 仓库 READMEFast DDS 官方文档Shared Memory Transportros2/rmw_fastrtps 仓库4.2 Cyclone DDS默认情况Cyclone DDS默认使用 UDP 传输不开启共享内存。开启方法需要手动配置 Cyclone DDS 的Roudi守护进程并配置共享内存 segment。具体做法是在 CycloneDDS XML 配置中启用SharedMemory传输并启动roudi进程。潜在问题开启共享内存后话题和服务可能存在丢包问题小舒实测并不好用。来源eclipse-cyclonedds/cyclonedds 仓库 READMECyclone DDS 官方文档Shared Memoryros2/rmw_cyclonedds 仓库 中相关 issue4.3 Zenohrmw_zenoh默认情况rmw_zenoh默认使用 TCP 通信不开启共享内存。开启方法需要在 Zenoh 的配置中显式启用共享内存传输并配置相应的共享内存参数。潜在问题与 Cyclone DDS 类似开启共享内存后话题和服务可能存在丢包问题至少在2026年实际可用性还不行。来源eclipse-zenoh/rmw_zenoh 仓库 READMEeclipse-zenoh/zenoh 仓库Zenoh 官方文档Shared Memory5. 对比总结方案原理配置方式成熟度适用场景Loaned MessageRMW→DDS借用 DDS 内部缓冲区显式使用 LoanedMessage API低问题多不推荐Intra-Process unique_ptr进程内转移消息对象所有权use_intra_process_commtrue Composable Node高官方推荐同进程多节点Fast DDS 共享内存共享内存传输默认开启segment 仅 256KB中需调大 segment默认 RMW小消息Cyclone DDS 共享内存Roudi 共享内存手动配置 XML 启动 roudi低可能丢包需谨慎评估Zenoh 共享内存共享内存传输手动配置低可能丢包需谨慎评估6. 效果评估这些方法到底能省多少延迟并不是用了共享内存或零拷贝延迟就一定大幅下降。6.1 共享内存 vs UDP并非总是更快很多人默认「共享内存一定比网络传输快」但实际测试往往并非如此尤其是高频小数据场景高频小消息一条几十字节的话题UDP 的发送/接收路径本身开销极小瓶颈往往在序列化、调度、锁竞争等环节而不是网络拷贝本身。此时共享内存省下的那一次 memcpy 微乎其微反而可能因为共享内存的同步机制如信号量、锁、缓存一致性引入额外开销实测延迟甚至可能不如 UDP。大数据消息对于图像、点云这类动辄几百 KB 到几 MB 的消息网络传输需要多次分片、拷贝、重组共享内存可以显著减少拷贝次数收益非常明显。这也是为什么共享内存在感知、导航等大数据场景下才真正值得投入。6.2 多进程间的零拷贝很难实现价值不大很多人会问能不能在多个独立进程之间也实现零拷贝答案是很难而且通常不值得跨进程共享内存本身不意味着零拷贝即使两个进程通过共享内存交换数据从rcl用户代码到 DDS 中间件之间仍然可能存在拷贝序列化/反序列化也绕不开。共享内存只是省掉了网络栈的拷贝并没有消除整条链路上的所有拷贝。真正的零拷贝依赖进程内对象所有权转移只有把多个节点放进同一个进程Composable Node use_intra_process_commtrue才能通过unique_ptr直接转移消息对象彻底跳过序列化和拷贝。一旦跨进程这套机制就失效了。跨进程零拷贝的实现成本极高需要自定义传输层、管理共享内存生命周期、处理并发与同步复杂度远超收益。实践中几乎没有人这么做。因此如果你想让多个节点享受零拷贝最务实的做法是把它们组合进同一个进程如果必须跨进程老老实实用共享内存或网络传输并接受相应的拷贝开销。6.3 综合评估方案延迟收益适用消息实现成本综合评价Intra-Process unique_ptr极高跳过 DDS 与序列化任意尤其高频小消息低组合节点即可✅ 首选Fast DDS 共享内存中大数据明显小数据可能不如 UDP大消息图像、点云低默认开启需调大 segmentCyclone DDS 共享内存中但可能丢包大消息中配置 XML roudi需谨慎评估Zenoh 共享内存中但可能丢包大消息中手动配置需谨慎评估Loaned Message理论高实际不完整任意高API 支持差❌ 不推荐一句话总结减小通信延迟优先把节点组合进同一进程走 Intra-Process 零拷贝跨进程场景下共享内存只对大数据消息有明显收益高频小数据未必比 UDP 快。
返回列表