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

在这里插入图片描述

文章目录

  • 前言
    • 相关代码整理
  • 调度介绍
  • 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kafka的零拷贝

传统的IO模型 如果要把磁盘中的某个文件发送到远程服务器需要经历以下几个步骤 (1) 从磁盘中读取文件的内容&#xff0c;然后拷贝到内核缓冲区 (2) CPU把内核缓冲区的数据赋值到用户空间的缓冲区 (3) 在用户程序中调用write方法&#xff0c;把用户缓冲区的数据拷贝到内核下面…

【普通人维护windows的方法,不中毒,不弹窗,不卡顿】

前言 IT人也是普通人&#xff0c;我就说说普通人维护电脑的方法。 我的电脑配置 给大家看看&#xff0c;配置一般&#xff0c;运行软件和游戏&#xff0c;可以保持基本流程 日常维护措施 我不太喜欢设定一些非主流的配置&#xff0c;下了一个360卫士,360其他的套餐可以不用下…

Python开发环境Spyder介绍

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 Spyder简介 Spyder (前身是 Pydee) 是一个强大的交互式 Python 语言开发环境&#xff0c; 提供高级的代码编辑、交互测试、调试等特性&#xff0c;支持包括 Windows、Linux 和 OS X 系统。 &#x1f447; &#x1f44…

备忘录模式——撤销功能的实现

1、简介 1.1、概述 备忘录模式提供了一种状态恢复的实现机制&#xff0c;使得用户可以方便地回到一个特定的历史步骤。当新的状态无效或者存在问题时&#xff0c;可以使用暂时存储起来的备忘录将状态复原。当前很多软件都提供了撤销&#xff08;Undo&#xff09;操作&#xf…

Google Search Central (Google搜索支持的结构化数据标记)SEO开发设置

Google会根据结构化数据了解网页上的椰蓉&#xff0c;从而优化SEO排名。搜索引擎优化 (SEO) 是提高网站网页在搜索引擎上的曝光度以吸引更多相关流量的过程。 应用场景 海外独立站新闻网站所有需要SEO排名的网站基本都试用当然众多关于SEO的方法这只是其中一点&#xff0c;合理…

如何用断言帮助检测错误

Java中的断言通过测试我们认为是正确的代码来帮助检测错误。 使用assert关键字进行断言。 其语法为&#xff1a; assert condition; 这里condition是一个布尔表达式&#xff0c;我们假定在程序执行时为真。 启用断言 默认情况下&#xff0c;断言在运行时被禁用并被忽略。…

PHP语言基础知识(超详细)

文章目录 前言第一章 PHP语言学习介绍 1.1 PHP部署安装环境1.2 PHP代码工具选择 第二章 PHP代码基本语法 2.1 PHP函数知识介绍2.2 PHP常量变量介绍 2.2.1 PHP变量知识&#xff1a;2.2.2 PHP常量知识&#xff1a; 2.3 PHP注释信息介绍2.4 PHP数据类型介绍 2.4.1 整形数据类型2.4…

Vault数据备份恢复-MySQL

前言 Vault提供了可靠的功能来保护数据库和其他关键数据。 对于MySQL数据库,Vault提供了一个易于使用的解决方案,可以自动创建和管理定期备份,并支持从备份中快速恢复数据。本文将介绍Vault后端存储MySQL的备份恢复,包括如何设置Vault、如何进行数据备份和还原、如何保护…

day49-Springboot

Springboot 1. Springboot简介 1.1 简介&#xff1a;Springboot来简化Spring应用开发的一个框架&#xff0c;约定大于配置 1.2 优点&#xff1a; 可以快速的构建独立运行的Spring项目&#xff1b; 框架内有Servlet容器&#xff0c;无需依赖外部&#xff0c;所以不需要达成w…

二十三种设计模式第二十四篇--访问者模式(完结撒花)

在访问者模式&#xff08;Visitor Pattern&#xff09;中&#xff0c;我们使用了一个访问者类&#xff0c;它改变了元素类的执行算法。 通过这种方式&#xff0c;元素的执行算法可以随着访问者改变而改变。 这种类型的设计模式属于行为型模式。根据模式&#xff0c;元素对象已接…

如何监控制造业精密空调?看这技能就够了!

在半导体制造、电子元件生产、光学设备制造等领域&#xff0c;精密空调监控是关键的保障&#xff0c;因为微小的温度或湿度变化、微生物或颗粒物污染都可能对产品质量和性能造成巨大影响。 精密空调监控系统作为一种高度智能化的解决方案&#xff0c;能够实时监测和调节生产环境…

SQL注入之sqlmap

SQL注入之sqlmap 6.1 SQL注入之sqlmap安装 sqlmap简介&#xff1a; sqlmap是一个自动化的SQL注入工具&#xff0c;其主要功能是扫描&#xff0c;发现并利用给定的URL的SQL注入漏洞&#xff0c;目前支持的数据库是MS-SQL,MYSQL,ORACLE和POSTGRESQL。SQLMAP采用四种独特的SQL注…

新手入门Jenkins自动化部署入门详细教程

1. 背景 在实际开发中&#xff0c;我们经常要一边开发一边测试&#xff0c;当然这里说的测试并不是程序员对自己代码的单元测试&#xff0c;而是同组程序员将代码提交后&#xff0c;由测试人员测试&#xff1b; 或者前后端分离后&#xff0c;经常会修改接口&#xff0c;然后重新…

【Python】Python 实现猜单词游戏——挑战你的智力和运气!

文章目录 前言学到什么?导入 random 模块定义生命次数定义神秘单词并进行随机选择定义 clue&#xff08;猜测进度&#xff09; 列表&#xff0c;用问号 ? 初始化定义心形符号的 Unicode 编码初始化 guessed_word_correctly 变量定义更新猜测进度函数 update_clue主循环&#…

使用上 Spring 的事件机制

本文主要是简单的讲述了Spring的事件机制&#xff0c;基本概念&#xff0c;讲述了事件机制的三要素事件、事件发布、事件监听器。如何实现一个事件机制&#xff0c;应用的场景&#xff0c;搭配Async注解实现异步的操作等等。希望对大家有所帮助。 Spring的事件机制的基本概念 …

邪恶版ChatGPT来了!

「邪恶版」ChatGPT 出现&#xff1a;每月 60 欧元&#xff0c;毫无道德限制&#xff0c;专为“网络罪犯”而生。 WormGPT 并不是一个人工智能聊天机器人&#xff0c;它的开发目的不是为了有趣地提供无脊椎动物的人工智能帮助&#xff0c;就像专注于猫科动物的CatGPT一样。相反&…

Ansible —— playbook 剧本

Ansible —— playbook 剧本 一、playbook的概述1.playbook简介2.什么是Ansible playbook剧本&#xff1f;3.Ansible playbook剧本的特点4.如何使用Ansible playbook剧本&#xff1f;5.playbooks 本身由以下各部分组成 二、playbook示例1.运行playbook2.定义、引用变量3.指定远…

JAVA 反编译工具

Releases deathmarine/Luyten GitHub 安装exe 打开拖入文件即可

九耶|阁瑞钛伦特:产品经理面试题—产品经理在工作中是如何划分需求优先级的?

产品经理在工作中划分需求优先级是为了指导产品团队的开发和发布流程。以下是产品经理在划分需求优先级时通常考虑的因素&#xff1a; 业务目标&#xff1a;产品经理会与企业领导层或业务方合作&#xff0c;了解公司的战略目标和销售策略。然后&#xff0c;他们会根据这些目标评…

图像 检测 - YOLOv3: An Incremental Improvement (arXiv 2018)

YOLOv3: An Incremental Improvement - 增量改进&#xff08;arXiv 2018&#xff09; 摘要1. 引言2. 处理2.1 边界框预测2.2 类别预测2.3 跨规模预测2.4 特征提取器2.5 训练 3. 我们的做法4. 我们尝试过但没有成功的事情5. 这一切意味着什么References 声明&#xff1a;此翻译仅…