3. 自动驾驶运行时基础

自动驾驶系统不是“一个程序跑在一台电脑上”这么简单。它同时承载感知、定位、预测、规划、控制、诊断、日志、人机交互等多条数据链路,每条链路又由若干算法模块组成。要让这些模块在毫秒级周期内稳定协同,必须依赖一套运行时(Runtime)作为底座。运行时负责把静态代码变成可调度、可通信、可观测、可治理的动态系统。

运行时 = 进程/线程管理 + 通信中间件 + 调度策略 + 资源隔离 + 时间基准 + 生命周期治理。它决定了模块“能不能按时拿到数据、能不能按时算完、能不能按时发出去”。

一、运行时概念:从“程序”到“任务系统”

传统程序以函数调用为主线,而自动驾驶运行时以数据流驱动为主线。一个感知模块启动后,通常不是被主函数反复调用,而是等待输入通道(Channel)上有新帧数据到达,触发回调,完成计算后再把结果写入输出通道。运行时需要回答四个问题:谁在运行、数据从哪来、什么时候执行、资源给多少。

  • 执行单元:进程、线程、协程、任务(Task)是不同粒度的执行载体。
  • 通信单元:Channel、Service、Parameter、Component 是模块间交互的基本抽象。
  • 时间单元:系统时钟、单调时钟、仿真时钟、时间戳与周期。
  • 资源单元:CPU 亲和性、内存池、GPU 流、网络带宽、锁与队列。

二、进程与线程模型:隔离与并发的权衡

Apollo Cyber RT 采用“进程内多线程 + 跨进程通信”的混合模型。每个 Component 可以配置为独立进程,也可以多个 Component 共享同一进程。独立进程隔离性好,单模块崩溃不易拖垮全局,但跨进程通信开销更大;共享进程通信快、内存共享方便,但故障域更大,需要更严格的线程安全与资源治理。

线程模型上,Cyber RT 提供调度器(Scheduler)与任务(Task)抽象。每个 Component 的回调被封装为 Task,由调度器根据优先级、周期、数据依赖分配到不同线程或线程池。常见策略包括:

  • 周期调度:按固定频率触发,适合控制、诊断等强周期任务。
  • 事件调度:数据到达即触发,适合感知、预测等数据驱动任务。
  • 优先级调度:安全关键任务优先获得 CPU 时间片。
  • 线程池复用:避免频繁创建销毁线程,降低抖动。
# Cyber RT 中一个典型 Component 的调度配置示意
components:
  - name: perception_obstacle_detector
    interval: 100ms          # 周期 100ms,即 10Hz
    priority: HIGH           # 高优先级
    affinity: "0-3"          # 绑定 CPU 0~3
    process_level: 1         # 独立进程
  - name: planning
    interval: 100ms
    priority: CRITICAL
    affinity: "4-5"
    process_level: 0         # 共享进程

三、实时性要求:硬实时、软实时与抖动

自动驾驶的实时性并非“越快越好”,而是“在截止时间前稳定完成”。控制周期通常为 10ms~100ms,感知为 50ms~100ms,规划为 100ms 左右。若某帧超时,轻则降级,重则导致车辆行为异常。因此运行时必须关注:

  • 端到端延迟:从传感器采样到执行器输出的总时间。
  • 抖动(Jitter):周期任务实际触发时间与理论时间的偏差。
  • 截止时间错过率:超时帧占比,是比平均延迟更关键的指标。
  • 优先级反转:低优先级任务持锁导致高优先级任务阻塞。
常见误区:只优化平均耗时,忽略最坏情况(WCET)。自动驾驶安全评估看的是“最坏情况下是否仍能满足截止时间”,而不是“大多数时候很快”。

四、资源调度:CPU、内存与通信的协同治理

资源调度的目标是在有限算力下,让关键链路获得确定性保障。Apollo Cyber RT 通过 CPU 亲和性、优先级、线程池、内存池、零拷贝通信等手段降低抖动。下表给出常见资源与治理手段的对应关系:

资源类型 典型问题 治理手段 观测指标
CPU 抢占、迁移、抖动 亲和性绑定、优先级、隔离核 CPU 利用率、上下文切换
内存 频繁分配、碎片、OOM 内存池、预分配、对象复用 分配次数、峰值内存
通信 拷贝、排队、丢帧 零拷贝、共享内存、QoS 队列 队列深度、丢帧率、延迟
GPU 流竞争、同步等待 多流并行、批处理、显存池 GPU 利用率、显存占用

五、Apollo Cyber RT 运行时概述

Cyber RT 是 Apollo 面向自动驾驶场景自研的运行时框架,核心设计围绕“高并发、低延迟、确定性”。它提供 Component 模型、Channel 通信、Service 调用、Parameter 服务、调度器、录制回放(Record/Replay)、监控与诊断等能力。其典型数据流如下:传感器驱动写入 Channel,感知 Component 订阅并计算,结果再写入下游 Channel,规划控制依次消费,最终输出到执行器。

Apollo Cyber RT 运行时:数据流 + 调度 + 资源治理 传感器驱动 LiDAR / Camera / Radar Channel 通信 发布 / 订阅 · 零拷贝 感知 Component 检测 / 分割 / 跟踪 预测与规划 行为预测 / 轨迹规划 控制 Component 横纵向控制 执行器 / 底盘 转向 / 制动 / 驱动 Scheduler 调度器 优先级 · 周期 · 线程池 资源治理 CPU 亲和 · 内存池 时间基准 · 录制回放 · 监控诊断 · 日志追踪 端到端延迟 · 抖动 · 丢帧率 · 截止时间错过率 数据流 调度/资源控制

从图中可以看出,Cyber RT 把“数据流”和“调度控制流”分开表达:数据沿 Channel 从传感器流向执行器,调度器与资源治理则横向作用于各 Component,保证关键任务获得确定性执行。时间基准、录制回放与监控诊断贯穿全链路,是排障与复盘的基础。

六、案例与排障:一次规划超时的复盘

某次实车测试中,规划模块偶发 200ms 超时。排查发现:感知与规划共享同一进程,感知的线程池占满 CPU,导致规划 Task 排队。解决方式是拆分进程、为规划绑定独立 CPU 核并提升优先级,同时将感知输出改为零拷贝共享内存。调整后规划抖动从 80ms 降至 15ms 以内。

# 排障常用观测命令(示意)
cyber_monitor                 # 查看 Channel 频率与延迟
cyber_node list               # 查看节点与进程
top -H -p <pid>               # 查看线程级 CPU 占用
cat /proc/<pid>/status        # 查看上下文切换与内存
治理口诀:先定周期与截止时间,再定优先级与亲和性,最后用监控验证抖动与丢帧。不要先调参数,再补指标。

总结来看,运行时是自动驾驶系统的“操作系统级底座”。理解进程与线程模型,才能合理划分故障域;理解实时性要求,才能设定正确的优化目标;理解资源调度,才能让关键链路获得确定性;理解 Cyber RT 的 Component、Channel 与 Scheduler,才能把算法模块真正组织成可治理的工程系统。