你对Linux下的实时性应该多点了解

2023-05-16

本文讲述一些有利于提高xenomai实时性的配置建议,部分针对X86架构,但它们的底层原理相通,同样适用于其他CPU架构和系统,希望对你有用。

一、前言

1. 什么是实时

“实时”一词在许多应用领域中使用,人们它有不同的解释,并不总是正确的。人们常说,如果控制系统能够对外部事件做出快速反应,那么它就是实时运行的。根据这种解释,如果系统速度快,则系统被认为是实时的。然而,“快”具有相对含义,并未涵盖表征这些类型系统的主要属性。

我们来看一下,在自然界中,生物在栖息地中的实时行为,这些行为与它们的速度无关。例如,乌龟对来自其栖息地的外部刺激的反应,与猫对其栖息地的外部反应一样有效。虽然乌龟比猫慢很多,但就绝对速度而言,它要处理的事件与它可以协调的动作成正比,这是任何动物在环境中生存的必要条件。

相反,如果生物系统所处的环境,引入了速度超过其处理能力的事件,其行为将不再有效,动物的生存也会受到损害。比如,一只苍蝇可以被苍蝇拍捕捉到,一只老鼠可以被陷阱捕捉到,或者一只猫可以被高速行驶的汽车撞倒。在这些例子中,苍蝇拍、陷阱和汽车代表了动物的异常和异常事件,超出了它们的实时能力范围,可能严重危及它们的生存。

前面的例子表明,实时并没有人们想象的那样快,而是与系统运行的环境严格相关。

实时系统是必须在设置的截止时间内对环境中的事件做出反应的系统,否则会产生严重的后果。

再比如,船舶的制导系统可能看起来是一个非实时系统,因为它的速度很低,而且通常有“足够”的时间(大约几分钟)来做出控制决定。尽管如此,根据我们的定义,它实际上是一个实时系统。

2. 实时分类

根据错过截止时间产生的后果,实时任务可以分为三类:

硬实时(Hard real time system)

如果在截止时间之后产生结果,可能对受控系统造成灾难性后果,则该任务是硬实时任务。

硬任务的例子可以在安全关键系统中找到,并且通常与传感、驱动和控制活动有关,例如:

  • 汽车安全气囊的检测与控制;

  • 反导弹系统要求硬实时。反导弹系统由一系列硬实时任务组成。反导系统必须首先探测所有来袭导弹,正确定位反导炮,然后在导弹来袭之前将其摧毁。所有这些任务本质上都是硬实时的,如果反导弹系统有任何一个任务失败都将无法成功拦截来袭导弹。

强实时(Firm real time system)

如果在截止日期之后产生结果对系统无用,但不会造成任何损害,则该任务是强实时任务。

在网络应用程序和多媒体系统中找到,在这些系统中,跳过一个数据包或一个视频帧比长时间延迟处理更重要。因此,它们包括以下内容:

  • 视频播放;

  • 音/视频编解码中,没有在设置的码率时序范围内执行完,产生结果都是无用的丢弃即可,继续下一轮读取;

  • 在线图像处理;

软实时(Soft real time system)

如果实时任务在截止日期之后产生结果仍然对系统有用,尽管会导致性能下降,则该任务是软实时任务。

软任务通常与系统-用户交互有关,有点延迟什么的并不影响,只是体验稍差点。因此,它们包括:

  • 用户界面的命令解释器;

  • 处理来自键盘的输入数据;

  • 在屏幕上显示消息;

  • 网页浏览等;

3.常见的RTOS

小型实时操作系统 UCOS、FreeRTOS、RT-Thread…

大型实时操作系统 RT linux、VxWorks、QNX、sylixOS…

4. latency和jitter

硬实时系统是必须在设置的截止时间内对环境中的事件做出反应的系统。硬实时操作系统应具备的最重要特性之一是确定性、可预期性。

操作系统的实时性能通常用latency或jitter来表示。事件预期发生与实际发生的时间之间的时间称为延迟(latency),实际发生的最大时间与最小时间之间的差值称为抖动(Jitter),两者均可表示实时性。根据实时性的定义,延迟必须是确定的,不能超过deadline,否则将会产生严重的后果。

当我们针对实时应用场景评估硬件和实时系统时,通常可以简化为对实时性能硬件资源的考量,即对于一个应用场景,实时性满足的情况下,硬件性能也满足。

在否决定使用一个实时系统时,需要结合具体应用场景来评估该实时系统是否符合,若不符合则需要考虑对现有系统优化或者更换方案。

二、实时性的影响因素

硬实时操作系统应具备的最重要特性之一是确定性、可预测性,系统应该保证满足所有关键时序约束。然而,这取决于一系列因素,这些因素涉及硬件的架构特征、内核中采用的机制和策略,以及用于实现应用程序的编程语言、软件设计等。

1.硬件

CPU架构

硬件方面,第一个影响调度可预测性的是处理器本身。处理器的内部特性是不确定性的第一个原因,例如指令预取、流水线操作、分支预测、高速缓存存储器和直接存储器访问(DMA)机制。这些特性虽然改善了处理器的平均性能,但它们引入了非确定性因素,这些因素阻止了对最坏情况执行时间WCET(Worst-caseExecutionTime)的精确估计。

高端CPU,如I5、I7实时性不一定有低端的赛扬、atom系列的好,芯片的设计本身定位就是高吞吐量而不是实时性。

Cache

  • CPU 里的 L1 Cache 或者 L2 Cache,访问延时是内存的 1/15 乃至 1/100,想要追求极限性能,需要尽可能地多从 CPU Cache 里面拿数据,减少cache miss,上面的分配CPU专门对实时任务服务就是对非共享的L1 、L2 Cache的充分优化。

  • 对于L3 Cache,多个cpu核与GPU共享,无法避免非实时任务及GUI争抢L3 Cache对实时任务的影响。

    为此intel 推出了资源调配技术(Intel RDT),提供了两种能力:监控和分配。Intel RDT提供了一系列分配(资源控制)能力,包括缓存分配技术(Cache Allocation Technology, CAT),代码和数据优先级(Code and Data Prioritization, CDP) 以及 内存带宽分配(Memory Bandwidth Allocation, MBA)。该技术旨在通过一系列的CPU指令从而允许用户直接对每个CPU核心(附加了HT技术后为每个逻辑核心)的L2缓存、L3缓存(LLC--Last Level Cache )以及内存带宽进行监控和分配。

RDT一开始是为解决云计算的问题,在云计算领域虚拟化环境中,宿主机的资源(包括CPU cache和内存带宽)都是共享的。这带来一个问题就是:如果有一个过度消耗cache的应用耗尽了L3缓存或者大量的内存带宽,将无法保障其他虚拟机应用的性能。这种问题称为 noisy neighbor。

同样对于我们的实时系统也是类似:由于L3 Cache多核共享,如果有一个过度消耗cache的非实时应用耗尽了L3缓存或者大量的内存带宽,将无法保障xenomai实时应用的性能。

以往虚拟化环境中解决方法是通过控制虚拟机逻辑资源(cgroup)但是调整粒度太粗,并且无法控制处理器缓存这样敏感而且稀缺的资源。为此Intel推出了RDT技术。在Intel中文网站的 通过英特尔® 资源调配技术优化资源利用视频形象介绍了RDT的作用。

Intel的Fenghua Yu在Linux Foundation上的演讲 Resource Allocation in Intel® Resource Director Technology 可以帮助我们快速了解这项技术。

总的来说,RDT让我们实现了控制处理器缓存这样敏感而且稀缺的资源,对我们对实时性能提升有很大帮助(不仅限于xenomai,RTAI、PREEMPT-RT均适用)。

  • CAT(缓存分配技术,Cache Alocation Technology),对最后一级缓存(L3 Cache)实现分区,用户可以通过限制每个核心能够向其中分配缓存行的LLC数量,将LLC的部分分配给特定核心,使用该技术可以提升实时任务Cahe命中率,减少MSI延迟和抖动,进而提升实时性能。(不是所有intel处理器具有该功能,一开始只有服务器CPU提供该支持,据笔者了解,6代以后的CPU基本支持CAT。关于CAT 见github),对于大多数Linux发行版,可直接安装使用该工具,具体的cache分配策略可根据后面的资源隔离情况进行。

sudo apt-get install  intel-cmt-cat

TLB

与cache性质一致。

分支预测

现代 CPU 的流水线级数非常长,一般都在10级以上,指令分支判断错误(Branch Mispredict)的时间代价昂贵。如果判断预测正确,可能只需要一个时钟周期;如果判断错误,就还是需要10-20 左右个时钟周期来重新提取指令。

如下为对同一随机组数,排序与未排序情况下for循环测试:

数据有规律和无规律两种情况下同一段代码执行时间相差巨大。

现代 CPU 的分支预测正确率已经可以在一般情况下维持在 95% 以上,所以当分支存在可预测的规律的时候,还是以性能测试的结果为最终的优化依据。

Hyper-Threading

人们对CPU的性能的追求是无止境的,在CPU性能不断优化提高过程中,对于单一流水线,最佳情况下,IPC 也只能到 1。无论做了哪些流水线层面的优化,即使做到了指令执行层面的乱序执行,CPU 仍然只能在一个时钟周期里面取一条指令。

为使IPC>1,诞生了多发射(Mulitple Issue)和超标量(Superscalar)技术,伴随的是每个CPU流水线上各种运算单元的增加。但是当处理器在运行一个线程,执行指令代码时,一方面很多时候处理器并不会使用到全部的计算能力,另一方面由于CPU在代码层面运行前后依赖关系的指令,会遇到各种冒险问题,这样CPU部分计算能力就会处于空闲状态。

为了进一步“压榨”处理器,那就找没有依赖关系的指令来运行好,即另一个程序。一个核可以分成几个逻辑核,来执行多个控制流程,这样可以进一步提高并行程度,这一技术就叫超线程,又称同时多线程(Simultaneous Multi-Threading,简称 SMT)。

由于超线程技术通过双份的 PC 寄存器、指令寄存器、条件码寄存器,在逻辑层面伪装为2个CPU,但指令译码器和ALU是公用的,这就造成实时任务运行时在CPU执行层面的不确定性,造成非实时线程与实时线程在同一物理核上对CPU执行单元的竞争,影响实时任务实时性。

电源管理与调频

我们知道CPU场效应晶体管FET构成,其简单示意图如下。

当输入高低电平时,CL被充放电,假设充放电a焦耳的能量。因为CL很小,这个a也十分的小,几乎可以忽略不计。为了提高CPU性能,不断提高处理器的时钟频率,但如果我们以1GHz频率翻转这个FET,则能量消耗就是a × 10^9,这就不能忽略了,再加上CPU中有几十亿个FET,消耗的能量变得相当可观。

详细的参考:https://zhuanlan.zhihu.com/p/56864499

为了省电,让操作系统随着工作量不同,动态调节CPU频率和电压。但是调频会导致CPU停顿(CPU停顿时间10us~500us不等),运行速度降低导致延迟增加,严重影响实时性能。

除了调频以外,另一个严重影响实时性的是,系统进入更深层次的省电睡眠状态,这时的唤醒延迟长达几十毫秒。

Multi-Core

接收 IRQ 的 CPU 可能不是响应者休眠的 CPU,在这种情况下,前者必须向后者发送重新调度请求,以便它恢复响应者。这通常是通过处理器间中断完成的,也就是IPI,IPI的发送和处理进一步增加了延迟。

中断周期及测试时长最小平均最大
100us 21h0.086us0.184us4.288us

此外,多核LLC共享,NUMA架构远端内存访问等,均会导致访问延迟不确定。

other

其他影响因素有内存、散热

提升内存频率可降低内存访问延时;使用双通道内存,这两个内存CPU可分别寻址、读取数据,从而使内存的带宽增加一倍,数据存取速度也相应增加一倍(理论上),内存访问延时得到缩短,进而提升系统的实时性能;

处理器散热设计不好,温度过高时会引发CPU降频保护,系统运行频率降低影响实时性,热设计应确保在高工作量时的温度不会引发降频。

对于X86 CPU,双通道内存性能是单通道内存的2. 5倍以上;正确的热设计可使实时性提升1.4倍以上。

2.BISO(X86平台)

BISO需要针对实时系统进行配置。优化的BIOS设置与使用默认BISO设置的实时性能差距高达9倍。

3.软件

  • 操作系统:调度算法,同步机制,信号量类型,内存管理策略,通信语义和中断处理等。

  • 资源的分配隔离:分配CPU专门对实时任务服务、将多余中断隔离到非实时任务CPU上,分配CPU专门对实时任务服务可使L1 、L2 Cache只为实时任务服务。

  • 实时任务的设计,良好的软件设计能更好的发挥实时性能。

  • 其他,虚拟化、GUI等 。

4. GPU

硬件上GPU与CPU共享L3 Cache ,因此GUI会影响实时任务的实时性。intel建议根据GUI任务的工作负载来固定GPU的运行频率,且频率尽可能低。减小GPU对实时任务实时性的影响。

三、优化措施

原则:降低不确定性,提高可预期性,在此基础上,再提高速度,降低延时。

比如,我们需要在确定的时间内从广州到深圳,如果驾车,途中会遇到多少个红绿灯,有无堵车 等等,有很多不确定性。但是如果我们换坐动车,就比驾车更具确定性,在此基础上我们提高速度,换坐高铁,广州到深圳的延时将变得更小。

1. BIOS[x86]

Disable FeaturesIntela Hyper-Threading Technology.
Intel SpeedStep.
Intel Speed Shift Technology
C-States: Gfx RC6.
GT PM Support.
PCH Cross Throttling.
PCI Express* Clock Gating.
Delay Enable DMI ASPM,DMI Link ASPM Control.
PCle *ASPM and SATA Aggressive LPM Support.
(For Skylake and Kaby Lake, also consider disabling Gfx Low Power Mode and USB Periodic SMl in BIOS.)
Enable FeaturesLegacy lO Low Latency
Gfx FrequencySet to fixed value as low as possible according to proper workload
Memory FrequencySA GV Fixed High

2. 硬件

除处理器外,内存方面,使用双通道内存,尽可能高的内存频率。

散热当面,针对处理器工作负载设计良好的散热结构, 否则芯片保护会强制降频,频率调整CPU会停顿几十上百us。

3. Linux

xenomai基于linux,xenomai作为一个小的实时核与linux共存,xenomai并未提供完整的硬件管理机制,许多硬件配置是linux 驱动掌管的,必须让linux配置好,给xenomai提供一个好的硬件环境,让xenomai充分发挥其RTOS的优势,主要宗旨:尽可能的不让linux非实时部分影响xenomai,无论是软件还是硬件

3.1 Kernel CMDLINE

cpu隔离

多核情况下,设置内核参数 isolcpus=[cpu列表],将列表中的CPU从linux内核SMP平衡和调度算法中剔除,将剔除的CPU用于RT应用。如4核CPU平台将第3、4核隔离来做RT应用。

CPU编号从"0"开始,列表的表示方法有三种:numA,numB,...,numN numA-numN 以及上述两种表示方法的组合:numA,...,numM-numN 例如:isolcpus=0,3,4-7表示隔离CPU0、3、4、5、6、7.

GRUB_CMDLINE_LINUX="isolcpus=2,3"

以上只是linux不会调度普通任务到CPU2和3上运行,这是基础,此时还需要设置xenomai方面的CPU隔离,方法一,任务通过函数 pthread_attr_setaffinity_np()设置xenomai任务只在CPU3和4上调度,隔离后的CPU的L1、L2缓存命中率相应的也会得到提高

cpu_set_t cpus;CPU_ZERO(&cpus);CPU_SET(2, &cpus);//将线程限制在指定的cpu2上运行CPU_SET(3, &cpus);//将线程限制在指定的cpu3上运行ret = pthread_attr_setaffinity_np(&tattr, sizeof(cpus), &cpus);

方法二,向xenomai设置内核参数 supported_cpus,指定xenomai支持的CPU,xenomai任务会自动放到cpu2、cpu3上运行。

xenomai 内核参数 supported_cpus与linux不同, supported_cpus是一个16进制数,每bit置位表示支持该CPU,要支持CPU2、CPU3,需要置置位bit2、bit3,即 supported_cpus=0x06(00000110b)。

GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x06"

注:linux内核参数 isolcpus=CPU编号列表是基础,否则若不隔离linux任务,后面的xenomai设置将没任何意义。

Full Dynamic Tick

将CPU2、CPU3作为xenomai使用后,由于xenomai调度是完全基于优先级的调度器,并且我们已将linux任务从这两个cpu上剔除,CPU上Tick也就没啥用了,避免多余的Tick中断影响实时任务的运行,需要将这两个cpu配置为Full Dynamic Tick模式,即关闭tick。通过添加linux内核参数 nohz_full=[cpu列表]配置。

nohz_full=[cpu列表]在使用 CONFIG_NO_HZ_FULL=y构建的内核中才生效。

GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x06 nohz_full=2,3"

为什么是linux内核参数呢?双核下时间子系统中分析过,每个CPU的时钟工作方式是linux初始化并配置工作模式的,xenomai最后只是接管而已,所以这里是通过linux内核参数配置。

注意:boot CPU(通常是0号CPU)会无条件的从列表中剔除。这是一个坑~

start_kerel() ->tick_init()   ->tick_nohz_init()void __init tick_nohz_init(void){ ....... cpu = smp_processor_id();    if (cpumask_test_cpu(cpu, tick_nohz_full_mask)) {    pr_warn("NO_HZ: Clearing %d from nohz_full range for timekeeping\n",      cpu);    cpumask_clear_cpu(cpu, tick_nohz_full_mask);  } ......}

Offload RCU callback

从引导选择的CPU上卸载RCU回调处理,使用内核线程 “rcuox / N”代替,通过linux内核参数 rcu_nocbs=[cpu列表]指定的CPU列表设置。这对于HPC和实时工作负载很有用,这样可以减少卸载RCU的CPU上操作系统抖动。

"rcuox / N",N表示CPU编号,‘x’:'b'是RCU-bh的b,'p'是RCU-preempt,‘s’是RCU-sched。

rcu_nocbs=[cpu列表]在使用 CONFIG_RCU_NOCB_CPU=y构建的内核中才生效。除此之外需要设置RCU内核线程 rcuc/nrcub/n线程的SCHEDFIFO优先级值RCUKTHREADPRIO,RCUKTHREADPRIO设置为高于最低优先级线程的优先级,也就是说至少要使该优先级低于xenomai实时应用的优先级,避免xenomai实时应用迁移到linux后,由于优先级低于RCUKTHREAD的优先级而实时性受到影响,如下配置RCUKTHREADPRIO=0。

General setup  --->    RCU Subsystem  --->        (0) Real-time priority to use for RCU worker threads        [*] Offload RCU callback processing from boot-selected CPUs             (X) No build_forced no-CBs CPUs            ( ) CPU 0 is a build_forced no-CBs CPU            ( ) All CPUs are build_forced no-CBs CPUsGRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x06 nohz_full=2,3 rcu_nocbs=2,3"

中断

  • 中断隔离

xenomai用户态实时应用运行时,中断优先级最高,CPU必须响应中断,虽然有ipipe会简单将非实时设备中断挂起,但是频繁的非实时设备中断产生可能引入无限延迟,也会影响实时任务的运行。

因此多,核情况下,通过内核参数 irqaffinity==[cpu列表],设置linux设备中断的亲和性,设置后,默认由这些cpu核来处理中断。避免了非实时linux中断影响cpu2、cpu3上的实时应用,将linux中断指定到cpu0、cpu1处理,添加参数:

GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x06 nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1"

以上只是设置linux中断的affinity,只能确保运行实时任务的CPU2、cpu3不会收到linux非实时设备的中断请求,保证实时性。

要指定cpu来处理xenomai实时设备中断,需要在实时驱动代码中通过函数 xnintr_affinity()设置,绑定实时驱动中断由CPU2、CPU3处理代码如下。

    cpumask_t irq_affinity;    ...    cpumask_clear(&irq_affinity);    cpumask_set_cpu(2, &irq_affinity);    cpumask_set_cpu(3, &irq_affinity);    ...    if (!cpumask_empty(&irq_affinity)){      xnintr_affinity(&pIp->irq_handle,irq_affinity);  /*设置实时设备中断的affinity*/    }

虽然ipipe会保证xenomai 实时中断在任何CPU都会优先处理,在实时设备中断比较少的场合,我觉得把linux中断与实时中断分开比较好;如果实时设备中断数量较多,如果隔离就会造成实时中断间相互影响中断处理的实时性,这时候不指定实时中断处理CPU比较好。

  • 编写xenomai实时设备驱动程序时,中断处理程序需要尽可能的短。

禁用irqbanlance

linux irqbalance 用于优化中断分配,它会自动收集系统数据以分析使用模式,并依据系统负载状况将工作状态置于 Performance mode 或 Power-save mode。简单来说irqbalance 会将硬件中断分配到各个CPU核心上处理。

  • 处于 Performance mode 时,irqbalance 会将中断尽可能均匀地分发给各个 CPU core,以充分利用 CPU 多核,提升性能。

  • 处于 Power-save mode 时,irqbalance 会将中断集中分配给第一个 CPU,以保证其它空闲 CPU 的睡眠时间,降低能耗。

禁用irqbanlance,避免不相干中断发生在RT任务核。发行版不同,配置方式不同,以Ubuntu为例,停止/关闭开机启动如下。

systemctl stop irqbalance.servicesystemctl disable irqbalance.service

必要的话直接卸载irqbalance。

apt-get remove irqbalance

x86平台还可添加参数acpi_irq_nobalance禁用ACPI irqbalance.

GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x06 nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1 acpi_irq_nobalance noirqbalance"

intel 核显配置[x86]

主要针对intel CPU的核显,配置intel核显驱动模块i915,内核参数如下。

GRUB_CMDLINE_LINUX="i915.enable_rc6=0 i915.enable_dc=0 i915.disable_power_well=0  i915.enable_execlists=0 i915.powersave=0"

nmi_watchdog[x86]

NMI watchdog是Linux的开发者为了debugging而添加的特性,但也能用来检测和恢复Linux kernel hang,现代多核x86体系都能支持NMI watchdog。

NMI(Non Maskable Interrupt)即不可屏蔽中断,之所以要使用NMI,是因为NMI watchdog的监视目标是整个内核,而内核可能发生在关中断同时陷入死循环的错误,此时只有NMI能拯救它。

Linux中有两种NMI watchdog,分别是I/O APIC watchdog(nmiwatchdog=1)和Local APIC watchdog(nmiwatchdog=2)。它们的触发机制不同,但触发NMI之后的操作是几乎一样的。一旦开启了I/O APIC watchdog(nmi_watchdog=1),那么每个CPU对应的Local APIC的LINT0线都关联到NMI,这样每个CPU将周期性地接到NMI,接到中断的CPU立即处理NMI,用来悄悄监视系统的运行。如果系统正常,它啥事都不做,仅仅是更改 一些时间计数;如果系统不正常(默认5秒没有任何普通外部中断),那它就闲不住了,会立马跳出来,且中止之前程序的运行。该出手时就出手。

避免周期中断的NMI watchdog影响xenomai实时性需要关闭NMI watchdog,传递内核参数 nmi_watchdog=0.

GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x06 nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1 acpi_irq_nobalance noirqbalance i915.enable_rc6=0 i915.enable_dc=0 i915.disable_power_well=0  i915.enable_execlists=0 i915.powersave=0 nmi_watchdog=0"

nosoftlockup

linux内核参数,禁用 soft-lockup检测器。

GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x06 nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1 acpi_irq_nobalance noirqbalance i915.enable_rc6=0 i915.enable_dc=0 i915.disable_power_well=0  i915.enable_execlists=0 i915.powersave=0 nmi_watchdog=0 nosoftlockup"

CPU特性[x86]

intel处理器相关内核参数:

  • nosmap

  • nohalt。告诉内核在空闲时,不要使用省电功能PALHALTLIGHT。这增加了功耗。但它减少了中断唤醒延迟,这可以提高某些环境下的性能,例如联网服务器或实时系统。

  • mce=ignore_ce,忽略machine checkerrors (MCE).

  • idle=poll,不要使用HLT在空闲循环中进行节电,而是轮询以重新安排事件。这将使CPU消耗更多的功率,但对于在多处理器基准测试中获得稍微更好的性能可能很有用。它还使使用性能计数器的某些性能分析更加准确。

  • clocksource=tsc tsc=reliable,指定tsc作为系统clocksource.

  • intel_idle.max_cstate=0 禁用intelidle并回退到acpiidle.

  • processor.max_cstate=0intel.max_cstate=0processor_idle.max_cstate=0 限制睡眠状态c-state。

GRUB_CMDLINE_LINUX="isolcpus=2,3 xenomai.supported_cpus=0x06 nohz_full=2,3 rcu_nocbs=2,3 irqaffinity=0,1 acpi_irq_nobalance noirqbalance i915.enable_rc6=0 i915.enable_dc=0 i915.disable_power_well=0  i915.enable_execlists=0  nmi_watchdog=0 nosoftlockup processor.max_cstate=0 intel.max_cstate=0 processor_idle.max_cstate=0     intel_idle.max_cstate=0 clocksource=tsc tsc=reliable nmi_watchdog=0 nosoftlockup intel_pstate=disable idle=poll nohalt nosmap  mce=ignore_ce"

3.2 内核构建配置

系统构建时,除以上提到的配置外(CONFIGNOHZFULL = y、CONFIGRCUNOCBCPU=y、RCUKTHREADPRIO=0),其他实时性相关配置如下:

CONFIGMIGRATION=n、CONFIGMCORE2=y[x86]、CONFIGPREEMPT=y、ACPIPROCESSOR =n[x86]、CONFIGCPUFREQ =n、CONFIGCPUIDLE =n;

经过以上配置后可以使用latency测试,观察配置前后的变化。关于latency,需要注意的是,测试timer-IRQ的latency时,即用 latency-t2命令来测试时,xenomai默认使用cpu0的timer,上面提到boot CPU(通常是0号CPU)会无条件的从 nohz_full=[cpu列表]列表中剔除,所以 latency-t2测试时你会发现没什么变化,还可能会变差了(最坏情况差不多一致,平均值变大了),另外我们将linux中断affinity全都设置为CPU0处理,这些中断或多或少也会影响timer-IRQ的latency。

2021.5添加-- 最近发现xenomai内核定时器affinity为cpu0的问题已被社区修复。

四、软件方面

  • 使用静态编译语言

  • 编写高性能的代码

  • 尽量让分支有规律性,使用likely()/unlikely()或编写无分支代码

  • 利用cache局部性原理,防止伪共享

  • 合理分配任务优先级等待

  • 驱动程序中断处理尽可能短等等

五、优化结果对比

笔者对以上各个条件配置前后对比过实时性改善效果,均有不同程度的优化效果,大家有兴趣也可自行测试。

以下结果基于 i5-7200U 8GB单通道DDR4,64GB emmc5.0,未使用RDT技术。

1-3 在已裁剪桌面下,压力加了内存。

1. 原始性能测试。

只使用了xenomai,CONFIGMIGRATION=n、CONFIGMCORE2=y[x86]、CONFIGPREEMPT=y、ACPIPROCESSOR =n[x86]、CONFIGCPUFREQ =n、CONFIGCPUIDLE =n。

优化项配置与否
BISONO
LinuxNO
Full Dynamic TickNO
Offload RCU callbackNO
Full desktopNO
stress-c 10 -m 4

2. 优化BIOS设置。

优化项配置与否
BISOYES
LinuxNO
Full Dynamic TickNO
Offload RCU callbackNO
Full desktopNO
stress-c 10 -m 4

3. Linux配置优化。

优化项配置与否
BISOYES
LinuxYES
Full Dynamic TickYES
Offload RCU callbackYES
Full desktopNO
stress-c 10 -m 4


4-6 未添加内存压力

4. 裁剪桌面。

保留完整Ubuntu桌面前,且经所有配置

优化项配置与否
BISOYES
LinuxYES
Full Dynamic TickYES
Offload RCU callbackYES
Full desktopNO—>YES
stress-c 10

裁剪桌面后:

裁剪前后对比:

5. Full Dynamic Tick启用前后对比

裁剪桌面后,配置cpu0未启用Full Dynamic Tick,cpu1启用Full Dynamic Tick,加压与未加压对比。

优化项配置与否
BISOYES
LinuxYES
Full Dynamic TickCPU0:NO
;CPU1:YES
Offload RCU callbackCPU0==NO;CPU1:
NO==
Full desktopNO
stress-c 10

对比cpu0与cpu1,最坏情况没有改善,但4us以上的latency改善明显。

6.桌面、rcu、tick前后比对

带桌面、未启用rcunocb、未启用Full Dynamic Tick-------->裁桌面、启用rcunocb、启用Full Dynamic Tick;

优化项配置与否
BISOYES            -->       YES
LinuxYES            -->       YES
Full Dynamic TickNO --> YES
Offload RCU callbackNO-->YES
Full desktopYES - >NO
stress-c 10

7.总对比

优化项配置与否
BISONO            -->       YES
LinuxNO            -->       YES
Full Dynamic TickNO            -->       YES
Offload RCU callbackNO             -->       YES
Full desktopYES             -->       NO
stress-c 10 -m 4

六、实时性能测试

下面直接给出最终的应用空间任务Jitter测试结果,使用的环境如下:

CPUintel 赛扬 3865U@1.8GHZ
KernelLinux 4.4.200
操作系统Ubuntu 16.04
内存8GB DDR3-1600 双通道
存储64GB EMMC

测试条件:在stress压力下测试,同时一个QT应用程序绘制2维曲线图,QT CPU占用率99%。

stress -c 10 -m 4

测试时间:211:04:55 测试命令:

latency -t0 -p 100 -P 99 -h -g result.txt 

测试应用空间程序,优先级99,任务周期100us,测试结果输出到文件result.txt。经过接近10天的测试后,文件result.txt中latency分布结果如下:

# 211:04:55 (periodic user-mode task, 100 us period, priority 99)# ----lat min|----lat avg|----lat max|-overrun|---msw|#       0.343|      1.078|     23.110|       0|     0|# Xenomai version: Xenomai/cobalt v3.1# Linux 4.4.200-xeno ......# I-pipe releagese #20 detected# Cobalt core 3.1 detected# Compiler: gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.12) # Build args: --enable-smp --enable-pshared --enable-tls PKG_CONFIG_PATH=:/usr/xenomai/lib/pkgconfig:/usr/xenomai/lib/pkgconfig0 10.5 15993570371.5 16211301062.5 566187533.5 43869854.5 38485315.5 35567046.5 33536497.5 30332188.5 25601339.5 203507510.5 151686611.5 103898912.5 68081513.5 41712414.5 22429615.5 11516516.5 5807517.5 2766918.5 1164819.5 464820.5 164621.5 46722.5 3823.5 1

其中第一列数据表示latency的值,第二列表示该值与上一个值之间这个范围的latency出现的次数,最小0.343us,平均latency 1.078us,最大23.110us。可见xenomai的实时性还是挺不错的。以上只是xenomai应用空间任务的实时性表现,如果使用内核空间任务会更好。当然这只能说明操作系统能提供的实时性能,具体的还要看应用程序的设计等。

此外,该测试基于X86平台,X86处理器的实时性与BIOS有很大关系,通常BIOS配置CPU具有更高的吞吐量,例如超线程、电源管理、CPU频率等,毕竟BIOS不是普通开发者能接触到的,如果能让BIOS对CPU针对实时系统配置的话,实时性会更好。如下图所示,平均抖动几乎在100纳秒以内。

相关链接

https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/cache-allocation-technology-white-paper.pdf

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

你对Linux下的实时性应该多点了解 的相关文章

  • 如何更改 Apache 服务器的根目录? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如何更改 Apache 服务器的文档根目录 我基本上想要localhost从 来 users spencer projects目录而不是
  • CoAP数据包的大小是多少?

    我是这项技术的新手 有人可以帮助我了解一些疑问吗 Q 1 CoAP数据包的大小是多少 我知道有 4 字节固定标头 但是包括标头 选项和负载在内的最大大小限制是多少 Q 2 有像MQTT那样的Keep Alive的概念吗 它在UDP上工作 它
  • 是否可以创建一个脚本来保存和恢复权限?

    我正在使用 Linux 系统 需要对一组嵌套文件和目录进行一些权限实验 我想知道是否没有某种方法可以保存文件和目录的权限 而不保存文件本身 换句话说 我想保存权限 编辑一些文件 调整一些权限 然后将权限恢复到目录结构中 将更改的文件保留在适
  • 删除 Git 存储库,但保留所有文件

    在我使用 Linux 的过程中的某个时刻 我决定将我的主目录中的所有内容都放入源代码管理中是个好主意 我不是在问这是否是一个好主意 我是在问如何撤销它 删除存储库的原因是我最近安装了 Oh My Zsh 而且我非常喜欢它 问题是我的主目录有
  • 如何在基于 Linux 的系统上的 C 程序中使用 mqueue?

    如何在基于 Linux 的系统上的 C 程序中使用 mqueue 消息队列 我正在寻找一些好的代码示例 可以展示如何以正确且正确的方式完成此操作 也许是一个操作指南 下面是一个服务器的简单示例 该服务器接收来自客户端的消息 直到收到告诉其停
  • Linux:如何设置进程的时区?

    我需要设置在 Linux 机器上启动的各个进程的时区 我尝试设置TZ变量 在本地上下文中 但它不起作用 有没有一种方法可以使用与系统日期不同的系统日期从命令行运行应用程序 这可能听起来很愚蠢 但我需要一种sandbox系统日期将被更改的地方
  • 监视目录的更改

    很像一个类似的问题 https stackoverflow com questions 112276 directory modification monitoring 我正在尝试监视 Linux 机器上的目录以添加新文件 并希望在这些新文
  • 如果在等待“read -s”时中断,在子进程中运行 bash 会破坏 tty 的标准输出吗?

    正如 Bakuriu 在评论中指出的那样 这基本上与BASH 输入期间按 Ctrl C 会中断当前终端 https stackoverflow com questions 31808863 bash ctrlc during input b
  • 子目录中的头文件(例如 gtk/gtk.h 与 gtk-2.0/gtk/gtk.h)

    我正在尝试使用 GTK 构建一个 hello world 其中包括以下行 include
  • Windows CE 与嵌入式 Linux [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 现在我确信我们都清楚 Linux 与 Windows 桌面的相对优点 然而 我对嵌入式开发世界的了解却少得多 我主要对行业解决方案感兴
  • 捕获实时流量时如何开启纳秒精度?

    如何告诉 libpcap v1 6 2 将纳秒值存储在struct pcap pkthdr ts tv usec 而不是微秒值 捕获实时数据包时 Note This question is similar to How to enable
  • 为什么C Clock()返回0

    我有这样的事情 clock t start end start clock something else end clock printf nClock cycles are d d n start end 我总是得到输出 时钟周期是 0
  • Mcrt1.o和Scrt1.o有什么用?

    我坚持使用以下两个文件 即 Mcrt1 o 和 Scrt1 o 谁能帮我知道这两个文件的用途 如何使用它 我们以 gcrt1 o 为例 在使用 pg 选项编译进行性能测试时非常有用 谢谢 表格的文件 crt o总是 C 运行时启动代码 大部
  • 从 systemd bash 内联脚本创建 filename_$(date %Y-%m-%d)

    我正在尝试执行systemd计时器并希望将执行脚本的输出保存在每个日期的文件中 这是我的ExecStart脚本中的 service file ExecStart bin bash c echo date Y m d gt gt home u
  • 如何在 GNU/Linux 上设置 Subversion (SVN) 服务器 - Ubuntu [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一台运行 Ubuntu 的笔记本电脑 我想将其用作 Subversion 服务器 既让我自己在本地承诺 也让其他人远程承诺 要使其
  • 后台分叉无法正常工作[重复]

    这个问题在这里已经有答案了 我运行这个程序 在前景和背景中 int main int pid printf App Start pid d n getpid while 1 pid fork if pid 0 printf Child n
  • Linux 上的 RTLD_LOCAL 和dynamic_cast

    我们有一个由应用程序中的一些共享库构成的插件 我们需要在应用程序运行时更新它 出于性能原因 我们在卸载旧插件之前加载并开始使用新插件 并且只有当所有线程都使用旧插件完成后 我们才卸载它 由于新插件和旧插件的库具有相同的符号 我们dlopen
  • 在 Linux 上访问 main 之外的主要参数

    是否可以访问参数main在外面main 即在共享库构造函数中 在 Linux 上除了通过解析之外 proc self cmdline 您可以通过将构造函数放入 init array部分 功能在 init array 不像 init 使用相同
  • 如何访问 mmaped /dev/mem 而不导致 Linux 内核崩溃?

    我有一个简单的程序 尝试访问用户空间中的物理内存 其中内核存储第一个结构页 在 64 位机器上 该地址是 内核虚拟地址 ffffea0000000000 物理地址 0000620000000000 我正在尝试通过用户空间中的 mmap 访问
  • 这种 bash 文件名提取技术有何用途?

    我有一部分 bash 脚本正在获取不带扩展名的文件名 但我试图了解这里到底发生了什么 是做什么用的 有人可以详细说明 bash 在幕后做了什么吗 如何在一般基础上使用该技术 bin bash for src in tif do txt sr

随机推荐

  • [C++][原创]ubuntu上C++发送http请求get和post

    找到一个开源项目 xff1a GitHub elnormous HTTPRequest Single header C 43 43 HTTP request class 使用项目都有介绍 xff0c 很简单 xff0c 这里我在ubuntu
  • 网络通信编程(UDP和TCP协议的实现)

    网络通信 1 网络编程入门1 1网络编程概述1 2网络编程三要素第一要素第二要素第三要素 1 3IP地址 xff08 网络中设备的唯一标识 xff09 常用命令特殊IP地址 1 4InetAddress类的使用 xff08 为了方便对IP地
  • STM32F0 HAL库的串口中断调用顺序

    首先在主函数里执行发送中断或者接收中断函数 xff1a HAL UART Receive IT amp UartHandle uint8 t RxBuf 1 HAL UART Transmit IT amp UartHandle uint8
  • 最全综述 | 图像分割算法

    点击上方 AI算法与图像处理 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 图像分割是计算机视觉研究中的一个经典难题 xff0c 已经成为图像理解领域关注的一个热点 xff0c 图像分割是图像分析的第一
  • CNN的Flatten操作 | Pytorch系列(七)

    点击上方 AI算法与图像处理 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 文 AI study 欢迎回到这个关于神经网络编程的系列 在这篇文章中 xff0c 我们将可视化一个单一灰度图像的张量flat
  • PyTorch中Linear层的原理 | PyTorch系列(十六)

    点击上方 AI算法与图像处理 xff0c 选择加 34 星标 34 或 置顶 重磅干货 xff0c 第一时间送达 文 AI study 原标题 xff1a PyTorch Callable Neural Networks Deep earn
  • python-opencv报错:QObject::moveToThread: Current thread

    报错 xff1a QObject moveToThread Current thread 0x55ab2a343120 is not the object s thread 0x55ab2a4f8820 Cannot move to tar
  • 谷歌又放大招 Disco Diffusion!AI生成超高质量绘画!

    En点击下方 AI算法与图像处理 xff0c 一起进步 xff01 重磅干货 xff0c 第一时间送达 大家好 xff0c 我是 阿潘 xff5e 我在b站刷到了一个博主分享最新的算法 xff0c 用AI生成高质量的插画 本文主要是分享现在
  • ikun必学!python 画一个简单的只因

    大家好呀 xff0c 我是阿潘 现在有很多虚假的ikun 1 看似维护鸡哥 xff0c 实则想吃鸡哥下的蛋 每次看到这种网络攻击 xff0c 鼻子一酸 xff0c 泪流不止 这个世界太不友善了 xff0c 真的不知道面对那么多无端的谩骂他是
  • CVPR2023论文速递(2023.3.23)!已接入ChatGPT总结!共26篇!

    整理 xff1a AI算法与图像处理 CVPR2023论文和代码整理 xff1a https github com DWCTOD CVPR2023 Papers with Code Demo 欢迎关注公众号 AI算法与图像处理 xff0c
  • 5个python常用的装饰器!

    大家好呀 xff0c 我是阿潘 首先 xff0c 每个开发人员的目标都是让事情正常进行 慢慢地 xff0c 我们担心可读性和可扩展性 这是我们第一次开始考虑装饰器的时候 装饰器是为函数提供额外行为的绝佳方式 使用装饰器 xff0c 你会惊讶
  • PerSAM!单图即可定制专属SAM模型!支持微调,甚至可增强DreamBooth

    大家好呀 xff0c 我是阿潘 Meta 的 Segment Anything Model 着实火了一把 xff0c 今天来和大家分享一篇相关的研究成果 xff0c 论文和代码都已开源 xff1a 从标题的字面意思应该就是指仅需一个样本即可
  • Python绘制可爱的卡通人物 | 【turtle使用】

    Turtle库 简介 什么是Turtle 首先 xff0c turtle库是一个点线面的简单图像库 xff0c 能够完成一些比较简单的几何图像可视化 它就像一个小乌龟 xff0c 在一个横轴为x 纵轴为y的坐标系原点 xff0c 0 0 位
  • STM32 Keil5 Bug记录 汇总和解决办法

    STM32 Keil5 Bug记录 汇总和解决办法 文章目录 STM32 Keil5 Bug记录 汇总和解决办法前言一 Warning1 warning no newline at end of file2 warning function
  • STM32重要源文件和头文件说明

    对于STM32F4xx StdPeriph Driver xff0c 其重要源文件为 xff1a stm32f4xx ppp h xff1a 外设头文件 这里的ppp只是一个代码 xff0c 在实际上是具体的外设名字 xff0c 如ADC
  • 带参宏定义和带参函数的区别

    在带参宏定义中 xff0c 不会为形式参数分配内存 xff0c 因此不必指明数据类型 而在宏调用中 xff0c 实参包含了具体的数据 xff0c 要用它们去代换形参 xff0c 因此必须指明数据类型 这一点和函数是不同的 xff1a 在函数
  • “段寄存器”的故事

    一 段寄存器的产生 段寄存器的产生源于Intel 8086 CPU体系结构中数据总线与地址总线的宽度不一致 数据总线的宽度 xff0c 也即是ALU 算数逻辑单元 的宽度 xff0c 平常说一个CPU是 16位 或者 32位 指的就是这个
  • 阿里面试官:为什么MySQL数据库索引选择使用B+树而不是跳表?

    来源 xff1a https www cnblogs com andydao p 12891690 html 作者 xff1a andydaopeng 在进一步分析为什么MySQL数据库索引选择使用B 43 树之前 xff0c 我相信很多小
  • AD生成bom表

    1 Report Bill of material 2 可通过点击右侧的Columns xff0c 更改导出属性 3 点击Preview 查看生成的excel文件 4 生成的 excel文件 注 xff1a 出bom表的原理图需要在工程里
  • 你对Linux下的实时性应该多点了解

    本文讲述一些有利于提高xenomai实时性的配置建议 xff0c 部分针对X86架构 xff0c 但它们的底层原理相通 xff0c 同样适用于其他CPU架构和系统 xff0c 希望对你有用 一 前言 1 什么是实时 实时 一词在许多应用领域