【Apollo学习笔记】—— Cyber RT之调度

news2024/11/18 17:26:47

在这里插入图片描述

文章目录

  • 前言
    • 相关代码整理
  • 调度介绍
  • Cyber RT的改进
    • 实时操作系统
    • 资源限制&优先级
    • 协程
  • Cyber RT调度策略
    • 任务窃取
    • 两种任务类型
      • componen组件
      • 自定义任务
  • Cyber调度实践
    • 配置文件
    • DAG文件
    • cyber_launch文件
    • component组件
    • BUILD文件
  • 问题
  • 参考

前言

本文是对Cyber RT的学习记录,文章可能存在不严谨、不完善、有缺漏的部分,还请大家多多指出。
课程地址: https://apollo.baidu.com/community/course/outline/329?activeId=10200
更多还请参考:
[1] Apollo星火计划学习笔记——第三讲(Apollo Cyber RT 模块详解与实战)https://blog.csdn.net/sinat_52032317/article/details/126924375
[2] 【Apollo星火计划】—— Cyber基础概念|通信机制
https://blog.csdn.net/sinat_52032317/article/details/131878429?spm=1001.2014.3001.5501
[3] 第一章:Cyber RT基础入门与实践https://apollo.baidu.com/community/article/1093
[4] 第二章:Cyber RT通信机制解析与实践https://apollo.baidu.com/community/article/1094
[5] 第三章:Component组件认知与实践https://apollo.baidu.com/community/article/1103
[6] 第四章:Cyber RT之调度简介与实践https://apollo.baidu.com/community/article/1106

相关代码整理

链接: https://pan.baidu.com/s/1ENgXE4yQ1v4nJRjcfZtd8w?pwd=ht4c 提取码: ht4c

调度介绍

操作系统进行调度的目的是为了最大化利用系统资源(特别是CPU资源)。调度往往是对有限资源的妥协,本质是为了:效率最大化,兼顾公平。通过调度,可以减少任务的等待时间。

任务耗时长的放在前面执行会增加任务等待时间。因此最优的调度策略诞生了,它就是最短时间优先,每次最短时间的任务优先执行,这样可以保证任务总等待时间最短。

但此时,若一直有小任务被创建,被优先执行,耗时长的任务就会一直得不到执行,一直处于饥饿状态。如此便造成CPU 利用的不公平

同时还存在一个问题:任务的执行时间通常是不可知的

以上的问题引入新的方法:时间片轮转。交替执行各个任务,每个任务分配一小段CPU时间,时间用尽则退出,让给其它任务使用。
在这里插入图片描述

时间片轮转是一种CPU调度算法,其基本思想是将CPU时间分为若干个时间片,每个进程占用一个时间片,当时间片用完后,该进程被挂起,等待下一次到来。优点平均分配CPU时间,降低了进程等待时间缺点时间片设置过小会导致进程频繁切换降低CPU利用率和系统吞吐量时间片设置过大会导致进程响应时间过长

常见的时间片轮转算法包括固定时间片动态时间片。固定时间片是指每个进程占用的时间片长度相同,且在调度前预先设定好,如每个时间片长度为10ms;动态时间片则是根据进程是否需要更多时间来动态分配时间片长度。

Cyber RT的改进

实时操作系统

  • 实时操作系统,通过给linux打实时补丁,支持抢占。
  • 中断绑定,摄像头,激光雷达,串口等外设需要不停的处理中断,因此可以绑定中断处理程序在一个核上。

实时操作系统(RTOS)是一种专门设计用于实时应用的操作系统。它的优点和缺点如下所述:

优点

  1. 响应时间可控:实时操作系统能够保证任务的响应时间,使得实时应用能够在特定的时间要求下进行操作。这对于需要高度可靠性和确定性的应用非常重要,如航空航天、工业自动化等。
  2. 任务调度优化:RTOS具有灵活的任务调度算法,以确保关键任务得到及时处理,并避免资源的浪费。它可以根据任务的优先级和时间约束进行任务调度,提高系统的效率和性能。
  3. 可靠性和稳定性:实时操作系统经过精心设计和测试,以确保系统的可靠性和稳定性。它具有容错机制,能够处理错误和异常情况,保证系统的稳定运行。

缺点

  1. 复杂度高:实时操作系统的设计和开发比较复杂,需要考虑各种任务的调度、同步和通信等问题。这增加了系统开发的难度和成本。
  2. 资源占用:实时操作系统需要占用一定的系统资源,如内存、处理器时间等。对于资源有限的嵌入式系统来说,这可能会成为一个问题。
  3. 可扩展性差:一些实时操作系统在设计之初就考虑了特定的应用需求,因此它们的可扩展性可能较差。在面对不同应用需求时,可能需要进行定制或者选择其他RTOS。

总体来说,实时操作系统在处理实时应用方面具有很多优点,但也需要根据具体需求和系统环境来评估其是否适用。

中断绑定是一种将中断与对应处理程序绑定的机制,它的作用是使操作系统能够响应硬件设备和用户程序发出的中断请求,并执行相应的操作

中断绑定的优点包括:

  1. 提高系统的响应速度:操作系统可以快速响应硬件设备和用户程序发出的中断请求,减少了系统的响应时间。
  2. 提高系统的可靠性:通过中断绑定机制,可以确保中断请求被正确的分配到处理程序中,减少了系统发生故障的可能性。
  3. 提高系统的灵活性:不同的硬件设备和用户程序需要不同的中断处理程序,在执行中断绑定的过程中,可以灵活地为不同的中断请求分配不同的处理程序。

中断绑定的缺点包括:

  1. 中断响应的开销:中断绑定需要一定的时间开销,因为每次中断请求都需要查找相应的处理程序。
  2. 处理程序的占用资源:中断处理程序需要占用系统资源,当系统中同时存在多个中断请求时,可能会导致资源的竞争和冲突。
  3. 难以调试:如果中断绑定发生错误,很难进行调试,因为中断处理程序的执行过程很难跟踪和调试。

资源限制&优先级

Cgroup是 Linux 内核的一个特性,用于限制、记录和隔离一组进程的资源使用(CPU、内存、磁盘 I/O、网络等)。Cgroup 具有以下特性:

  • 资源限制 —— 您可以配置 cgroup,从而限制进程可以对特定资源(例如内存或 CPU)的使用量。
  • 优先级 —— 当资源发生冲突时,您可以控制一个进程相比另一个 cgroup 中的进程可以使用的资源量(CPU、磁盘或网络)。
  • 记录 —— 在 cgroup 级别监控和报告资源限制。
  • 控制 —— 您可以使用单个命令更改 cgroup 中所有进程的状态(冻结、停止或重新启动)。
pthread_setaffinity_np

    choreography_conf {
        choreography_processor_num: 8
        choreography_affinity: "range"
        choreography_cpuset: "0-7" # bind CPU cores 核
        choreography_processor_policy: "SCHED_FIFO" # policy: SCHED_OTHER,SCHED_RR,SCHED_FIFO 设置策略

协程

协程。用户态的线程,由用户控制切换。协程的定义可以参考go语言中的GMP模型。

协程(Coroutine)是一种轻量级的线程,它可以在同一个线程内实现多个任务的切换执行,从而达到高效利用资源的目的。协程常用于高并发、网络编程、异步处理等场景。

M,Machine,表示系统级线程,goroutine 是跑在 M 上的。P,processor,是 goroutine 执行所必须的上下文环境,可以理解为协程处理器,是用来执行 goroutine 的。

协程相对线程的优势

  • 系统消耗少。线程的切换用户态->中断->内核态,协程的切换只在用户态完成,减少了系统开销。
  • 轻量。协程占用资源比线程少,一个线程往往消耗几兆的内存。

自动驾驶系统需要不断地进行数据采集、处理和决策,同时还需要与车辆的各种硬件进行交互。这些操作通常会涉及到大量的 I/O 操作,包括网络通信、传感器数据采集和控制命令发送等,这些操作都可能会阻塞程序的执行。如果使用传统的线程或进程来处理这些操作,就会导致程序的性能不稳定,并可能出现死锁等问题。

协程是一种轻量级的多任务解决方案,能够避免多线程或多进程的开销和锁竞争等问题。在自动驾驶中,协程可以用于异步处理各种 I/O 操作,例如通过异步网络库处理网络通信、通过异步文件读写库处理文件读取等。由于协程能够在不同的任务之间进行切换,因此可以避免程序在等待 I/O 操作时被阻塞,从而提高了程序的性能和并发性能。同时,协程还能够提供更好的代码可读性和可维护性,因为它们能够使用更简洁和易于理解的代码来处理异步操作。综上所述,引入协程可以减少任务切换带来的开销,提高系统的响应速度和效率,同时也可以简化代码结构,提高代码的可读性和可维护性

Cyber RT调度策略

对应到GMP模型,Cyber的每个任务都被视为一个协程,协程在线程上运行,并且可以设置协程的优先级。协程通过一个多优先级队列来管理,每次从优先级最高的协程开始执行

任务窃取

为了提高效率,空闲的Processor会从饱和的Processor上偷取一半的任务过来执行,从而提高CPU利用率。

两种任务类型

componen组件

组件是Apollo中的最小执行单元,每个组件对应某一项特定的任务,例如定位、控制。多个组件联合起来可以实现更加复杂的功能,例如感知。Apollo一共有2种类型的组件:消息触发型和定时触发型。
PS:关于组件,可以参考这篇博客【Apollo学习笔记】—— Cyber RT之创建组件

自定义任务

如果在程序中想启动新的任务并发处理,可以使用cyber::Async接口,创建的任务会在协程池中由cyber统一调度管理。

class Foo {
 public:
  void RunOnce() {
    auto res = Async(&Foo::Task, this, 10);
    EXPECT_EQ(res.get(), 10);
  }

  uint32_t Task(const uint32_t& input) { return input; }
};

Cyber调度实践

实验步骤:

  1. 修改cyber/conf/example_sched_choreography.conf中的配置
  2. 启动./bazel-bin/cyber/examples/common_component_example/channel_prediction_writer发送消息
  3. 启动cyber_launch start cyber/examples/common_component_example/common.launch,其中包括4个组件,用于消费消息。

配置文件

cyber/conf目录下修改cyber/conf/example_sched_choreography.conf中的配置,通过更改配置可以设置任务的优先级,绑定的核心等。
文件内容为:

scheduler_conf {
    policy: "choreography"
    process_level_cpuset: "0"  # all threads in the process are on the cpuset
    threads: [
        {
            name: "lidar"
            cpuset: "1"
            policy: "SCHED_RR" # policy: SCHED_OTHER,SCHED_RR,SCHED_FIFO
            prio: 10
        }, {
            name: "shm"
            cpuset: "2"
            policy: "SCHED_FIFO"
            prio: 10
        }
    ]
    choreography_conf {
        choreography_processor_num: 4
        choreography_affinity: "range"
        choreography_cpuset: "0"
        choreography_processor_policy: "SCHED_RR" # policy: SCHED_OTHER,SCHED_RR,SCHED_FIFO
        choreography_processor_prio: 10

        pool_processor_num: 4
        pool_affinity: "range"
        pool_cpuset: "0"
        pool_processor_policy: "SCHED_OTHER"
        pool_processor_prio: 0

        tasks: [
            {
                name: "common0"
                processor: 0
                prio: 1
            },
            {
                name: "common1"
                processor: 0
                prio: 2
            },
            {
                name: "common2"
                processor: 0
                prio: 3
            },
            {
                name: "common3"
                processor: 0
                prio: 4
            }
        ]
    }
}

prio代表优先级,数字越大,优先级越大。

DAG文件

分别创建common0.dag、common1.dag、common2.dag、common3.dag四个文件。注意修改相应名称。

# Define all coms in DAG streaming.
    module_config {
    module_library : "/opt/apollo/neo/packages/test-dev/latest/lib/libcommon_component.so"
    components {
        class_name : "CommonComponentCroutine"
        config {
            name : "common0"
            readers {
                channel: "/apollo/driver"
            }
        }
      }
    }

cyber_launch文件

供参考

<cyber>
    <module>
        <name>common</name>
        <dag_conf>/opt/apollo/neo/packages/test-dev/latest/test_croutine/conf/common0.dag</dag_conf>
        <dag_conf>/opt/apollo/neo/packages/test-dev/latest/test_croutine/conf/common1.dag</dag_conf>
        <dag_conf>/opt/apollo/neo/packages/test-dev/latest/test_croutine/conf/common2.dag</dag_conf>
        <dag_conf>/opt/apollo/neo/packages/test-dev/latest/test_croutine/conf/common3.dag</dag_conf>
        <process_name>example_sched_choreography</process_name>
    </module>
</cyber>

<process_name>example_sched_choreography</process_name>这要写对

component组件

common_component.h

#include <memory>
#include "cyber/component/component.h"
#include "test/proto/examples.pb.h"

using apollo::cyber::Component;
using apollo::cyber::ComponentBase;
using apollo::cyber::test::proto::Driver;

class CommonComponentCroutine : public Component<Driver> {
 public:
  bool Init() override;
  bool Proc(const std::shared_ptr<Driver>& msg0) override;
};
CYBER_REGISTER_COMPONENT(CommonComponentCroutine)

common_component.cc

#include "test/test_croutine/common_component.h"
#include <bits/stdc++.h>
#include "cyber/croutine/croutine.h"
#include "cyber/time/rate.h"


using apollo::cyber::croutine::CRoutine;
using apollo::cyber::Rate;

bool CommonComponentCroutine::Init() {
  AINFO << "Commontest component init";
  return true;
}

bool CommonComponentCroutine::Proc(const std::shared_ptr<Driver>& msg0) {
  if (CRoutine::GetCurrentRoutine() != nullptr) {
    AINFO << "Name: " << CRoutine::GetCurrentRoutine()->name();
  }

  calculate task
  int i = 10000000;
  while (i) {
    log(i);
    --i;
  }
  // Rate rate(5.0);
  // rate.Sleep();
  AINFO << "Start common component Proc [" << msg0->msg_id() << "]";
  return true;
}

BUILD文件

供参考

load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
load("//tools/install:install.bzl", "install", "install_src_files")
load("//tools:cpplint.bzl", "cpplint")

package(default_visibility = ["//visibility:public"])

cc_binary( 
    name = "libcommon_component.so",
    linkshared = True,
    linkstatic = True,
    deps = [":common_component_lib"],
)

cc_library(
    name = "common_component_lib",
    srcs = ["common_component.cc"],
    hdrs = ["common_component.h"],
    visibility = ["//visibility:private"],
    deps = [
        "//cyber",
        "//test/proto:examples_cc_proto",
    ],
    alwayslink = True,
)

filegroup(
    name = "conf",
    srcs = [
        ":common0.dag",
        ":common1.dag",
        ":common2.dag",
        ":common3.dag",
        ":demo.launch",
    ],
)

install(
    name = "install",
    data = [
        ":conf",
    ],
    library_dest = "test/lib",
    data_dest = "test/test_croutine/conf",
    targets = [
        ":libcommon_component.so",
    ],
)

install_src_files(
    name = "install_src",
    src_dir = ["."],
    dest = "test/src/test_croutine",
    filter = "*",
)

问题

出现以下问题,导致无法加载.conf文件,采取了默认分配的方式。

E0802 22:03:10.314543 1670469 file.cc:106] [mainboard]Failed to parse file /opt/apollo/neo/packages/cyber/conf/example_sched_choreography.conf as binary proto

报错段

在这里插入图片描述
默认分配
在这里插入图片描述
结果

在这里插入图片描述
在这里插入图片描述

PS:该问题是在本地运行时出现的。在云实验平台上做正常。
已解决:配置文件有误,末尾多了一个,
结果:
在这里插入图片描述

参考

[1] 百度Apollo系统学习-Cyber RT 调度
https://blog.csdn.net/qq_25762163/article/details/103763525
[2] 技术文档丨Cyber RT车载系统CPU资源调度和数据与协程任务驱动模型https://developer.baidu.com/article/detail.html?id=290451

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/831191.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

4G WWAN设备类型

WWAN设备类型 USB dongle是设备接入互联网的重要方式之一&#xff0c;典型的通过USB接口与主设备连接&#xff0c;然后主设备通过4G/5G接入互联网&#xff0c;作为移动宽带设备&#xff0c;它有那些设备类型及暴露方式呢&#xff1f; 移动宽带设备类型&#xff1a;ModemManage…

无涯教程-Lua - nested语句函数

Lua编程语言允许在另一个循环中使用一个循环。以下部分显示了一些示例来说明这一概念。 nested loops - 语法 Lua中嵌套for循环语句的语法如下- for init,max/min value, increment dofor init,max/min value, incrementdostatement(s)endstatement(s) end Lua编程语言中的…

Podman权限问题导致的403报错思路与解决

问题 podman运行镜像&#xff0c;端口映射、卷映射无误&#xff0c;但在运行访问测试容器内http接口报错403. 查阅系统日志&#xff0c;存在多处容器相关的selinux访问被拒绝错误&#xff0c;sealert提示需要为几个进程的对象添加临时规则。 考虑是否为selinux问题&#xff…

语义分割文献整理

2014年文献 1.论文题目《Semantic Image Segmentation with Deep Convolutional Nets and Fully Connected CRFs》 1.1.网络别名《DeepLabV1》 1.2.论文引用 Chen L C, Papandreou G, Kokkinos I, et al. Semantic image segmentation with deep convolutional nets and fu…

AI赋能转型升级 助力打造“数智辽宁”——首次大模型研讨沙龙在沈成功举行

当前&#xff0c;以“ChatGPT”为代表的大模型正在引领新一轮全球人工智能技术发展浪潮&#xff0c;推动人工智能从以专用小模型定制训练为主的“手工作坊时代”&#xff0c;迈入以通用大模型预训练为主的“工业化时代”&#xff0c;正不断加速实体经济智能化升级&#xff0c;深…

(自控原理)控制系统的数学模型

目录 一、时域数学模型 1、线性元件微分方程的建立 2、微分方程的求解方法​编辑 3、非线性微分方程的线性化 二、复域数学模型 1、传递函数的定义 2、传递函数的标准形式 3、系统的典型环节的传递函数 4、传递函数的性质 5、控制系统数学模型的建立 6、由传递函数求…

【C++】带三维重建和还原的RIS/PACS源码

【PACS】集成三维影像后处理功能&#xff0c;包括三维多平面重建、三维容积重建、三维表面重建、三维虚拟内窥镜、最大/小密度投影、心脏动脉钙化分析等功能。系统功能强大&#xff0c;代码完整。 一、RIS/PACS系统简介 RIS/PACS系统在预约登记、分诊叫号、技师检查、诊断报告…

面向开发人员的远程桌面:随时随地安全编写代码

随着数字世界的不断发展&#xff0c;传统意义上的“工作场所”概念正在发生重大转变。这种转变在科技行业尤其明显&#xff0c;开发人员和软件工程师越来越倾向于选择远程或混合办公模式。 在这次重大转变中&#xff0c;远程桌面软件经证明是一项足以影响远程办公的技术。通过…

YOLOv5改进系列(18)——更换Neck之AFPN(全新渐进特征金字塔|超越PAFPN|实测涨点)

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制

使用Golang实现一套流程可配置,适用于广告、推荐系统的业务性框架——简单应用

在诸如广告、推荐等系统中&#xff0c;我们往往会涉及过滤、召回和排序等过程。随着系统业务变得复杂&#xff0c;代码的耦合和交错会让项目跌入难以维护的深渊。于是模块化设计是复杂系统的必备基础。这篇文章介绍的业务框架脱胎于线上多人协作开发、高并发的竞价广告系统&…

java系列之list集合分组

文章目录 前言一、list是什么&#xff1f;二、list集合分组总结 前言 在Java编程中&#xff0c;List集合是一种常用的数据结构&#xff0c;用于存储一组元素。有时候&#xff0c;我们需要对List集合中的元素进行分组操作&#xff0c;即将相同属性或特征的元素归类到一组。这种…

金三银四好时节,python面试10K+能不能得到?

嗨害大家好鸭&#xff01;我是小熊猫~ 金三银四好时节&#xff0c;面试10K能不能得到&#xff1f; 这次正逢面试季&#xff0c;这次给大家带来一个真实面试题 虽然最后上的班不一定是自己喜欢的&#xff0c; 但是工作还是要有哇&#xff01; 第三方库: requests >>>…

【C++杂货铺】string使用指南

文章目录 前言一、介绍二、string类的常用接口说明2.1 常见的构造接口2.2 与容量有关的接口2.3 与对象访问及遍历有关的操作2.4 与对象修改有关的操作2.5 与查找有关的接口2.6 string类的非成员函数2.7 与类型转换有关的接口 前言 在C语言中&#xff0c;字符串是以\0结尾的一些…

Win10、11集体翻车,祖传Bug连关机都不能

基本可以确定的是&#xff0c;微软将在2024年推出或名为 Win12 的下一代 Windows 。 Win10、11 的更新跨度肉眼可见放缓&#xff0c;可频率嘛&#xff0c;仍然一月几更。 如果你没有禁用更新&#xff0c;应该和小蝾一样&#xff0c;下班关机时经常有熟悉的选项。 不过在大多数…

分享之python 线程

Threading用于提供线程相关的操作&#xff0c;线程是应用程序中工作的最小单元。 1、threading模块 threading 模块建立在 _thread 模块之上。thread 模块以低级、原始的方式来处理和控制线程&#xff0c;而 threading 模块通过对 thread 进行二次封装&#xff0c;提供了更方…

ansible常见模块的运用

ansible常见模块的运用 一&#xff1a;Ansible简介二&#xff1a;ansible 环境安装部署管理端安装 ansibleansible 目录结构配置主机清单配置密钥对验证 三&#xff1a;ansible 命令行模块1&#xff0e;command 模块在远程主机执行命令&#xff0c;不支持管道&#xff0c;重定向…

这所国字头双一流,根本招不满,学硕都没人报!

一、学校及专业介绍 中国民航大学&#xff0c;位于天津市&#xff0c;是民航局、天津市、教育部共建高校&#xff0c;是天津市“双一流”建设高校和高水平特色大学建设高校。 1.1 招生情况 2023年中国民航大学电子信息与自动化学院&#xff0c;初试考806信号与系统的一共有两…

Windows环境下创建定时任务执行Python脚本

一、环境 以下演示使用的环境说明 Windows 操作系统&#xff1a;Win10 Python 环境&#xff1a;Python 3.7.7 二、脚本 准备Python脚本如下&#xff1a; import sys import datetimeformat_time datetime.datetime.now()with open(file"forpy.log",mode"a&qu…

单月涨粉345万,7月抖音爆款技巧是什么?

近期&#xff0c;抖音电商官方发布「七夕好礼季」的玩法攻略&#xff0c;助力商家抢跑七夕。如今&#xff0c;各类营销节点&#xff0c;成为商家实现生意爆发的关键。 那么&#xff0c;在没有营销节点加持的7月&#xff0c;那些表现突出的主播&#xff0c;持续畅销的商品&#…

解决elementUI图标按钮调整宽高后图标没有居中的问题

解决elementUI图标按钮调整宽高后图标没有居中的问题 1.情景再现2.解决2.1 重新设置新的padding2.2 flex布局 1.情景再现 我是用elementui的图标按钮组件&#xff0c;但是我想要的大小和官方给到的大小不一致。所以我给图标设置了一个width: 16px;height: 16px;的属性值&#…