本文来源:智车科技
确定性执行是目前汽车电子市场的技术热点,但是笔者仍觉得此项技术需更多的验证,因为这项技术是有难度的,对系统的稳定性、鲁棒性都有要求。此外,确定性执行是否适合所有的域控制器仍然是一个未知数。
1、确定性执行的概念
确定性执行是指在给定输入的情况下,在有限的时间内产生一致的输出,也就是输入到输出的运行过程是确定的,输入与输出有如下关系:
输出 = f(输入)
这个概念不是很像可重入函数嘛,输入确定的情况下,输出也是确定的,不管怎么运行,什么时候运行,有多少调用者,输出就是确定的,输出只依赖输入。
相比较于可重入的概念,确定性多了一个对运行时间的限制。实际应用过程中,我们对确定性还有一个隐式的需求,要求在确定的时间点执行,并且在确定的时间点之前结束。那么确定性执行就产生如图所示的几个因素。
实际操作中,输出依赖输入不现实,总会有状态切换,其他依赖项的失效或者硬件失效等等原因导致同一个输入产生多个输出。但是,可以尽可能做到在不同的工况下,输出依赖于输入。
因此,对于确定性执行,就产生了如下需求:
1.要求函数或者任务是单例或者可重入,正常工况下的,这就保证了输出和输出基本处于一一对应的状态,保证了输出的可控。
2.运行时长受限,就需要尽量不存在运行时间不可控的代码。例如,阻塞型代码,带有自旋锁的代码。
3.运行时长受限,隐式的指明,任务的截止时间是确定的。
4.运行时间点要求时间同步是系统必备的需求。
5.运行时间点要求确定性执行的任务应在需求指定的时间点运行。
6.确定性执行的任务应明确任务激活源。
对于确定性执行,并没有很明确的需求或者在实践中需要关中断,或者任务保持原子执行。也就是说,确定性执行的过程中,任务可能会被打断,暂停,抢占。
2、确定性执行的过程分析
确定性执行是有它自身应用的场景的,它需要整个系统处于稳定并且存在一定的运行规律。在自动驾驶领域,对确定性执行有着极高的需求,它需要传感器数据,特殊的任务在规定的时间点执行,并在规定的时间内结束。此外,确定性执行对数据处理的延迟性有很好的抑制作用,可以满足自动驾驶对实时性的需求。
确定性执行经常和确定性通信绑定在一起使用,正常的带有数据转发的确定性执行流程如下图所示:
2.中间件任务在3000us时间点执行并发送数据
3.经过协议栈处理,并物理传输,在3300us时到达对方的协议栈
4.对端中间件任务在3500us时间点运行接收数据,并转发给应用
5.应用在5000us时间点运行并处理
当然,此处还有一个优化点,将中间件的数据接收或者发送 与 应用绑定到同一个确定性执行的任务中。
我们假定底层的协议栈,硬件配置,参数配置均保持一致,也就是假定了硬件平台的传输范畴的运行时间是稳定的,波动较小的。其实这边抛开了TSN、传输负载等相关因素的影响。我们假定关键数据帧的传输最大时间,从请求协议栈发送接口调用开始计算,到达对端协议栈并且协议栈把数据准备好给中间件处理为计算的终点,整个的传输最大时间为500us。
非确定性执行关键点在于执行时间点一直在波动,可能在应用运行之前,也可能会在应用执行之后准备好数据。这就导致了应用层获取的数据一直在抖动,可能某些时刻数据已经失去了时效性。
而确定性执行恰恰相反,数据总是在应用执行之前就会准备好,应用层每次运行都不会空跑一轮代码然后让渡CPU的运行时间。
对于CPU负载而言,非确定性执行的CPU负载是杂乱无章的,但是确定性执行的CPU负载就是波浪形的。
简单说来,确定性执行的负载是均匀的分布在该有的时间点范围内,而非确定性执行的时间点和截止点都是未知的,有可能非确定性执行的任务在本次时间片内处理了三个数据,下一个时间片处理1个数据。确定性执行的任务每一个时间片都处理2个数据,运行时长也是比较稳定的。
3、确定性执行的优点
确定性执行对于运行截止时间,降低延时是非常有效的。此外,设计得当的话,确定性执行可以降低内存消耗。如下表格所示,非确定性执行因为数据申请和数据释放的速度不一致,为了保证数据不丢失,必然需要缓存多次数据。而确定性执行在一个任务周期内,可以完成数据申请和数据释放,因此只需要缓存一个数据。这个作用对MCU这种资源紧缺型的芯片而言,真是天大的福音。
实践过程中,意外的发现,确定性执行对我们的软件设计比较友好。以下是几个可以快速提高效率的点,不需要考虑太多其他副作用。
第一点:无锁的中间件设计。第二点:零拷贝的内存模型软件设计。这两点本质上是一点,但此处还是拆开来讲,因为这里面的侧重点不一样。
第一点,无锁的中间件设计。
首先,有一点需要澄清,当我们谈到中间件,第一印象就是Linux,QNX,域控制器,但是MCU侧也就是CP侧也需要中间件设计。其次,对于无锁我们第一印象是Lock-Free,但它真的是Free并且没有代价的吗?这种无锁需要代价,各种编译器提供的各种原子操作以及内存序的需求对程序的运行是有影响的。此处讲的无锁是指不用原子操作,也不用锁!当然,cache同步的问题还是需要解决的。我们将其抽象成一个单读单写问题,以便于举例说明。
读和写都在同一款芯片内,如果不用原子操作,当核0写数据之后,核1读数据需要在硬件MESI机制起作用并完全核间同步之后读取数据,那么此时数据就不是Dirty Data。确定性执行可以保证核0写内存和核1读内存的时间差大于MESI的同步耗时,那么,我们写内存完全不需要考虑各种锁,以及内存同步的机制对运行效率的影响,因此局部运行效率将大大提高。
对于MCU而言,一般不存在cache同步的问题,但是核间数据访问需要做互斥,确定性执行保证两个任务不在同一个时间点执行,那么就不存在互斥(锁)的问题。
第二点,零拷贝的内存模型软件设计。
我们经常碰到一个很苦恼的问题,同一块内存如何给其他程序访问。我们将这个问题简化成一个单写2读的模型,这其实在汽车电子中很常见,同一个topic的数据,其实也就那么两个或者3个程序需要用。我们再明确一下场景,假设一个温度传感器的数据需要被2个程序获取,为了软硬解耦,我们在设计时可能会有一个任务周期性的获取温度数据,然后传递给其他2个程序。整个流程如下图所示,读取数据时,如果是Linux系统,直接将温度数据内存首地址传递给内核,内核直接将数据拷贝到此内存中,不需要借助临时变量,然后再拷贝到温度数据内存中。不同的程序在不同的时间点读取使用数据,也就是说,不同程序只是拿到这个内存地址,然后用这个数据,不需要任何拷贝。当然,这边有个前提,最后一个需要使用数据的程序必须在温度数据下一次获取之前结束使用。
4、确定性执行面对的现实
然而,确定性执行并没有那么美好,很多因素制约着确定性执行的发挥,确定性执行的稳定性和可靠性也有待考量。
就整车层级而言,确定性面临的现实:
1.确定性执行在整车层级实现是有一定的困难的,并不是所有控制器均可以实现确定性执行的。
2.面临的第一个挑战是时间同步!确定性执行的基础是时间同步必须要精准,抖动要小。不是所有的控制器能做到。尤其是某些同步时刻,时间会有一些奇奇怪怪的跳变或者抖动。当然,时间回滚是必须要避免的。
3.小周期运行的任务,比如说2.5毫秒周期运行的任务,确定性执行实施起来非常困难。
4.由于时间同步需要时间,这就影响车辆启动了。确定性执行的任务启动可能会存在启动延迟,过大的延迟对于整车来说可能无法接受。
从单个域控制器的角度来说,面临的现实挑战更大:
1.必须要正视操作系统的实时性,Linux打个实时patch真不算什么真实时性,确定性执行对触发到程序响应是有要求的,响应太慢或者响应的时间忽长忽短,必然影响确定性执行的配合。
2.就同样的操作系统而言,不是所有任务都可以上确定性执行,必然面对确定性执行任务和非确定性执行任务混合运行的情况。绑核可以解决一部分问题,让所有确定性任务都运行在同一个核上,非确定性任务运行在其他核上,解决部分问题。然而,确定性任务和非确定性任务之间的数据交互,仍然需要去解决。
3.就不同的操作系统而言,确定性任务和非确定性任务的配合也十分困难。不同的操作系统必然面对着以太网,CAN,SPI或者异构核间的mailbox等类似硬件机制主导的数据传输机制。考虑跨芯片,跨操作系统,数据传输延时等各方面因素。众多因素考量下,需要合理排布好确定性执行任务,保证确定性执行任务间的低延时。
4.系统的卡滞,偶发的系统卡滞。直接导致确定性执行的任务执行错乱。是否会引发级联失效,仍待更多的验证。
5.系统调用的风险。有些系统调度会阻塞,有些系统调用有自旋锁,这些系统调用又不可能不用,但是用了,确定性执行还确定吗?
6.软件模块设计的挑战,确定性执行必然要求软件接口必须是非阻塞的,很多第三方库或者其他软件库存在阻塞行为,确定性执行与其配合,必然需要一番思考。
7.硬件的品控的挑战。最简单的体现是EOL下线时各种测试没问题,一跑量产代码就会有问题。有时候,由于各种原因,某次硬件操作耗时不一样,这可能会直接或者间隔影响确定性执行的时间。
8.确定性执行的效率相对来说是比较低的,对于Linux系统而言,需要自己设计适配调度器。
9.高负载尤其是偶发高负载下的确定性执行的抢占与稳定性保证。
10.确定性执行偶发运行耗时过长。某些情况下,由于确定性程序也会被内核任务抢占,如何保证确定性执行的截止时间仍在设计的范围内,或者在超时时间之后,确定性执行仍然可靠,也是需要特殊考虑的。
11.功能安全对确定性执行的影响。确定性执行可能会失效,那么它的失效模式是什么?失效之后后处理的策略是什么?ASIL-B控制器的确定性执行失效是否会引发ASIL-D控制器的确定性执行?
12.功能安全岛无法完全保证确定性执行的功能安全。
13.以上都考虑之后,开始调度器的特殊设计挑战! 跨核,跨进程,跨芯片,跨操作系统的考量设计。如果还要其他公司配合,那么恭喜你,加倍难度。
5、总结
确定性执行仍面临着很多挑战,需要操作系统的配合,各个控制器供应商的配合。功能安全也挑战着确定性执行的实现。目前确定性执行方案还存在着各种各样的问题,但是历史总是螺旋式的上升前进。技术发展的大浪淘沙,确定性执行总将在汽车电子行业占据一席。