6月7日,地平线「你好,开发者」技术公开课在智东西公开课顺利完结直播。公开课由地平线TROS.A系统架构师傅亚涛主讲,主题为《基于TogetheROS.Auto的智能驾驶软件开发范式》。
本文是此次技术公开课主讲环节的实录整理。如果对直播回放以及Q&A有需求,可以点击阅读原文前去观看。
首先,我会简单介绍智驾开发中遇到的各种问题,然后会基于这些问题来看如何从设计角度将问题做简化;然后,我会把TROS.A基于这些设计方式和设计思路所做的相关设计及实践进行分享;最后,我会分享智驾软件开发的发展趋势,以及智驾中间件的发展方向。
一种是典型的V模型。做过智驾开发的应该都会比较熟悉。这个V模型,一般是从研发侧,基本上是从系统需求、系统架构,再到子系统的设计研发。相对于常见的V模型,从需求,到设计,到研发来说,智驾会复杂很多。
基于智驾的软件规模,基本上经常做的是一个大的系统需求,从顶层的架构,再分解到多个不同的模块或公司。这个公司本身会再去做顶层的系统需求的分解,然后再去做设计。这种层级可能有两到三层,导致的一个问题是:在需求设计上经过层层分解,而这个分解的过程和软件研发其实是分离的。需求设计可能更多停留在文档上,研发基本上就到了整个系统的设计,然后再到编码。这个过程其实是分离的,流程越长,分离的越开的话,会造成在真正开发过程中,越容易造成变形。有可能做着做着就做歪了,有一些东西可能会漏掉。
反过来做这种集成的时候,又会发现有这么多层这么多组在并行开发,反向去层层做集成的时候,集成的成本非常高。遇到一个小问题,可能都需要拉一大拨人去长时间的定位。一个问题当涉及到跨团队跨公司的时候,来回踢皮球的情况,其实非常常见。
另一种开发模式其实也很常见。我们一般会去做一个原型系统,其实是用来做算法验证快速迭代的。基于这个原型系统,并对效果做了一定迭代之后,再往量产的环境上迁移这时候会面临很多问题:
一是原型系统和量产环境的架构差异很大。在原型上,可能是怎么快怎么来,比如说基于ROS2,或者基于Python来写;但在量产上,比方说,可能需要一个功能安全的软件底座,为了性能的话,可能会基于C++,甚至写一些性能更高的定制化实现。这就导致迁移过程很重,软件的效果一致性以及算法的一致性很难保障。此外,在原型开发的时候,大家更多关注的是算法的效果,但很少关注软件的性能,这会导致在原型系统向量产系统迁移的时候,性能优化成本非常高,整个软件的质量收敛速度会较低。
另外一个问题刚才也提到过,就是我们现在的智驾开发,通常是多团队开发,很多时候还是多公司联合开发。那它带来了一个问题,就是大家都有自己的一套技术栈,然后底下的软件栈,包括中间件和基础库可能也不太一样,最终集成到一个系统会非常困难。若出了一个问题,其实很难定位,比如某个线程执行发现总是出现delay,这种时候去定位线程被哪些信息影响,是非常难定位的。因为大家对于任务划分的粒度,以及开发控制的界面都不同。
此外整个智驾涉及到的系统非常复杂,不同模块间的影响会非常大。比如感知输出的周期可能不是那么固定,或者我的Latency的方差会比较大,就会影响到后面,比如预测、规控、定位相关的计算效果。
另外,前面也说到,多团队的开发,由于底层的框架不统一,再来做性能优化的时候会非常难。我们和一些团队接触过,在某些情况下,整个软件的线程数可能会达到三到四千。这种情况下,想去优化某个具体任务的性能会非常难,不一定是这个任务算得慢,而是整个系统就调不过来。同时,在这种规模下,去做问题定位,会很困难。比如说运行的过程,若发现延迟不符合预期,或者整个过程block住了,要定位是哪个模块的问题,都非常困难。
最后,整个软件栈的话,从最上层的算法、工程、策略,再到中间的中间件,再到底层的BSP、Driver是非常复杂的,有时候面对一个简单的问题,可能会需要联合多个团队来进行联合定位。所有的这些都会造成一个问题,就是在自己模块开发的时候,可能已经开发好了,但一旦真正做集成量产的时候,会发现整个周期依旧拉得非常长。
第三点,前面也有讲到,现在做智驾这一块,涉及到的知识面,不管是横向还是纵向,都非常广。比方说在基础能力方面,你可能需要C++,然后也需要有些python或者shell能力,至少能看懂算法工程师写的算法策略;然后可能需要去了解一些基础的系统知识、基础的工具;做性能优化的时候,常规的优化手段,比方说线程池、协程池、对象池、内存池等会用上去;对于热点,可能会做一些定点化的优化,然后做一些OMP、neon、汇编优化都有可能;然后问题定位的时候,用GDB还有ftrace、地址消除器各种各样的工具来去定位,比方说热点的性能问题,或者一些内存问题。
虽然做工程开发的时候,可能大部分用到的是软件工程的能力。但做智驾的话,其实需要有一定的算法知识。最基础的,例如数据结构算法,是通用知识;另外基础的CV算法肯定要会,比如至少要去了解一个图怎么转成一个BEV的图,大概的原理和计算方式是什么;关于机器学习,可能相关的算法工程师会研究的更深入,但在做软件开发的时候,至少要了解对应模型是什么、大致的逻辑以及它的输入输出、相关的处理调用;做性能优化的时候,对于常用的调度算法,肯定要有了解;此外,还涉及到数据压缩、数据加密、标定算法等。
另外就是业务相关能力,各种传感器基础知识、硬件基础知识;然后AutoSAR、ROS、DDS这种常规的软件,各种数据、渲染工具,以及功能安全一类的等。
所以,做智驾方面的软件开发,对工程师的技术栈要求会非常高,也带来几个问题:一是很难招到合适的人;二是从整个团队来说,新人进来要真正地能开始动手干一些比较实际的活,可能需要几个月的培养;而他开始能做一些跨模块复杂的工作,可能需要一年左右。所有这些都会导致整个软件开发难度加大,整个开发的带宽会非常地受限。
我这里面只列了一些常见的问题,当然会有更多的问题。比如整个智驾,要去做数据的管理,从采集到传输分析,然后再到Software2.0这种数据驱动整个软件的迭代。
一个是port,是我们功能模块的一个输入输出的端点。一个module可以有多个输入,也可以有多个输出。
第二个概念proc,是最小的执行单元。在很多情况下,可以认为一个proc 其实就是一个task,它会由触发器来触发进行运行。这个触发器有可能是基于前面的消息触发,也有可能是基于一些时间触发。然后,实际触发之后的执行会由底层的调度器来执行。用户从开发界面其实不太会关注具体怎么调。怎么调其实是调度器部分的策略,它的配置更多是在graphlet这一层,我们来看这个子图应该是怎么去执行。
第三个概念filter或者是condition,其实是proc的触发条件。一般来说,一个proc可能会由多条消息或者多个条件,来进行触发,我们其实是内置了一些常用的。比方说A消息和B消息同时到达,再执行proc A;或者A消息或者B消息随便来一个,我都去执行。同时,这部分能力,也支持用户做扩展,比方说我们自己常用的一个扩展,会对消息进行筛选,来做消息的时间对齐。
单纯从用户的开发界面,主要了解这三层概念,就可以进行相关的功能模块的开发。
怎么样从TROS.Auto上做设计,前面其实有提到。TROS.Auto从概念上可以分三层:package,graphlet和module。这其实和设计是相呼应的。前面讲到V模型有多层的设计分解,体现在TROS.Auto里面,我们从设计上也做了一个层层分解的设计。
在顶层架构上,可能会有一个非常大的graphlet,里面的模块相对来说可能都是非常粗粒度的。比方说,感知就是一个大的module,或者是一个package;定位、预测、规控都是相关的这种粒度。基于这个确定这些大模块之间的交互是什么样的,约束是什么样的。
然后再往下,我们会做模块的分解。比方说感知,是由一个复杂的graphlet组成的感知。由于前面感知在顶层设计上,已经定义了它的输入输出的标准,以及对于感知的限制,比如执行资源或者其他的限制。这时展开做设计时,这些限制和输出,天然会在下一层设计上会被引入进来。这一层的设计和顶层的一样,对这一层做架构的分解。
再往后可能会有更进一层的架构分解,也是一样来做各种输入输出、限制的传递,来保证整个架构从顶层到底层,是基于同一套约束层层传递,不会造成架构多级分解的信息丢失或者变形。
整个设计,到最底下一层的时候,支持基于这个设计去做对应的代码框架生成。在生成的代码上,天然的里面定义的各种输入输出、各种限制,就会嵌在生成的代码框架里面。用户在这一套框架里面,去做自己的功能开发就可以。
这是TROS.Auto真正从设计到实际研发的一个大致过程。可以看到,最左侧,架构已经分解到最底层,可能在我这一层是一个比较小的功能模块。在这一层上,我们定义了一个graphlet,里面的模块与模块间的数据流会被定义出来。基于它,我们会去用工具生成整个应用的代码的框架,这个框架在这个时候实际上是属于已经可编译、可运行的框架,只是没有具体的业务逻辑。用户在开发的时候,基于生成的这个框架去做具体的功能模块的应用开发。因为输入输出已经定义好,基本上是把自己的业务逻辑加进去。
可以看到,部署、调度和开发是分离的。因为从我们的设计上来说,用户真正做这种应用的业务开发的时候,不应太关注应用如何配置以及如何调用。它实际上是配置运行的一个过程。会有少部分的同学做应用集成的时候,会更关注应用怎么配置,以及应用怎么做调度优化。他和实际开发同学有可能是同一个人,也有可能不是。所以,这两部分概念在设计里面应该是分离的。最终在部署配置、调度优化之后去上板运行。
整个开发过程是这样一个过程的循环迭代。部署运行之后,来看功能以及性能,效果是否符合预期;如果不符合预期,可能会返回到模块开发、部署配置、调度优化,来循环做这种持续的迭代,最终达到一个比较稳定,比较好的效果。
刚才有提到,我们将整个软件的应用逻辑的开发、部署以及调度做了隔离。这里可以看到,我们是如何做纵向封装来减轻用户在调度方面的投入,和降低调度的理解成本。
左侧是基于刚才说到graphlet在工具上通过拖拉拽的方式,生成的一个graphlet的实例。它会生成具体的一个框架代码。
可以看到,实际上它定义的是刚才的内容:input的一个port,output port以及里面不同的proc;input和output之间会去定义一些具体的执行触发条件。
整个代码框架生成之后,用户基于这个界面去做具体模块的开发。而实际在输入的时候,用户其实不会太关注具体每一个proc怎么配。因为整个支架其实里面任务数会非常多,可能几千个任务,或者上万个任务。如果对每个任务去配它的调度策略,比方说绑核、优先级以及任务之间的这种关联关系,其实会非常困难。都做这种配置,在某种程度上可能性其实很低。
所以,目前我们的做法,更多是在用户界面上基于graph来配。就是整个graphlet实际上会有一个子图的概念。前面有说过graphlet也支持嵌套。那我的配置可能更关注执行链路应该有一个什么样的执行效果。整个graphlet,我会划分成不同的子图,不同的子图有不同的调度预期。而实际的调度是由底下的scheduleGroup来进行调度和分配。scheduleGroup里面,我们现在有做大概4种不同的调度器:基于定时的(Timer Scheduler)、基于线程优先级的(Priority Scheduler)、基于公平调度的(Deteministic Scheduler),也提供了基于协程的调度的能力(Coroutine Scheduler)。当然,每一种调度器里面有很多种策略。
对于调度的确定性要求比较高的,我们也提供了基于任务链时间做编排的一些调度的逻辑。所以,整个来说,在上层用户的开发界面,可能更多看到的是,我希望graphlet达到一个什么样的调度效果;映射到底层的scheduleGroup会映射到不同的调度器里面去;这些调度器再基于它的调度策略来进行实际的调度。
右下角这个图,是我们在进行了调度配置之后,实际生成的一个调度配置文件。可以看到,不同的调度器可能会有不同的配置字段,但这一部分更多的是基于我们的工具来帮你生成。当然一些工程能力比较强的同学,可以直接基于这个配置文件去手动做修改。我们尽量简化整个应用在调度上的复杂度,希望通过框架来屏蔽整个调度的一个过程,做到应用开发和调度的分离。
前面也有提到,我们也做了应用开发和部署的分离。分离这部分是基于我们的通信框架来实现的,主要由两部分能力构成:
一部分是我们实现了一套IDL工具,目的主要是将消息定义和实际的序列化方式做解绑。做软件开发的同学可能会体会到,实际在做消息定义的时候,一般会绑定某一种序列化方式,比方说绑定protobuf,或者DDS的话,有可能是Fast Buffer或者其他的序列化方式。
这会导致一个问题,就是当我们一个消息发送给不同的序列化接收对象时,在代码里面可能需要定制开发。比方说我发给对端,对端是走DDS的,我可能要在发送的时候就给他绑Fast Buffer;如果对方是进程内,我可能什么都不绑。
我们IDL目前做的方式,实际上就是将消息和序列方式做解绑,从用户界面看到的消息实际上就是一个一个的struct,我们当成常用的结构体来进行使用。真正和对端通信走什么样的序列化方式的时候,实际上是IDL生成的library来做决定。我们会在里面做IDL 的扩展,比方说,现在默认其实已经做了protobuf、 Fast DDS 的序列化方式的扩展,也可以扩展第三方自定义的序列化方式。在这种情况下,整个消息通信走哪一种,更多是运行时看通道的配置。
另外一部分就是具体的通信和通信协议、通信链路的解绑。我们开发了一套通信框架,它对上提供了这种常用的Pub/Sub、CS和Action的通信接口。然后往下可以看到,会接入非常多的不同的通信协议,比方说DDS,ZMQ,PCIE或者一些其他的。我们当前的做法是一种插件化的接入,也就是说我实际使用了哪一种,我把对应的SO扔进来就可以支持。但是对上来说,用户使用界面是完全不感知。
具体使用哪一种通道或者协议去跑,更多决定于我运行的配置。可以在部署配置里面配,也可以基于类似于Hybrid的方式,让它自动去选择,这个更多取决于我们使用的时候的一个场景。通常来说,我们可能在调试的时候用一些Hybrid的方式,但真正量产的时候可能会把通信的配置给固化下来,直接走平台定制。
通过这两种方式,我们就做到了整个通信方式和实际的通信链路以及通信协议的解耦。这时候就可以做到多模块开发的时候,开发的接口完全一致,但把它部署在同一个进程,还是部署在不同的进程,甚至部署在不同的SoC上,这时候应用的代码是完全一致的,它只是一个运行期的配置,就达到了前面说到的软件研发和通信配置的解耦。这种能力在后期做功能调试的时候,会非常有用。
第三个方面,我们也做了基础服务简化。前面有聊到过,我们有参考AP来定义一套我们自己的基础服务,比方说EM、SM、PHM诊断时间同步。在这一部分,前面有讲到在Dataflow这一层,我们有DAG或者是graphlet这层概念。很多这种基础能力,我们可以在这一层界面上和它打通。
比方说EM去做应用生命周期管理,但应用生命周期某种程度来说,是应用的一个graphlet执行的管理。是把graphlet的运行起来,还是停掉或者暂停,都可以通过这个界面。
SM其实也类似,比方做functionGroup。functionGroup粗粒度的可能是进程级的进程组控制。它和前面的EM的逻辑有点像,就是我去做进程级的graphlet的启停。
基于graphlet,其实也可以做更细粒度的。前面有讲到过,graphlet支持嵌套,我们可以在这个概念上,去做更细粒度的进程内的一些子功能的控制。
PHM和诊断这一块,我们在框架内会有集成。因为框架本身也会有一些PHM的检查,比方说执行逻辑或者执行超时,也会有诊断信息的上报。用户也可以调这一块的接口去做执行检查和上报信息。这一块其实对用户来说是可见的一部分内容。
其他的,也有一些基础的库,比方说时间相关的timer,我们也做了封装。基于它可以屏蔽掉底层的时间变化,比方说基于系统时间、基于虚拟时间,还是基于外部时钟源。在应用开发界面,就不需要特别关注切换时间导致的代码适配变更。
另外,我们其他的一些基础模块也是类似的一些设计思路。比方说也做了一套log的前端,统一由这个前端按照固定的格式进行输入。那它的后端可以接各种各样的log后端的服务,比方说默认做这种文件传输,但它也可以接比方说安卓的Alog,也可以接AutoSAR的log service,或者一些其他的自定义的log服务,来做log后端log盘的管理。
整个基础服务,和AP很大层面上概念会比较接近。所以,在实际的项目里面,我们也遇到厂家已经买了某种AP。但对于我们来说,这种基础服务和AP的替换,从应用的开发界面来说,其实是无感的。
前面简单聊了一下,TROS.A从横向或者纵向是怎么样设计,来简化整个软件开发的界面,并降低智驾开发的难度。举一个简单的例子,刚才也讲过我们会做一些能力的屏蔽。实际开发的时候,我们可能的一个做法,在顶层上会有一些大的模块:感知、定位、预测、规控。这些模块内部本身是一个graphlet的组成,里面不同模块有可能是用户已有的一些模块,可以从某个其他项目直接给迁移过来。因为每个module都是可以单独进行引用的,也有可能是你自己去开发。
当然,从TROS.A来说,我们也做了很多标准的功能模块,比方说Sensor center、VechicleIO、Odom、tf,我们其实做了一些标准实现,可以直接用。这一整套架构会在DataFlow的开发界面上,进行框架的组成以及调度的配置划分。
做完开发之后,接下来就是去做调试。在很多时候,调试比开发更麻烦。前面有讲过,现在做软件开发,其实并不是我一组人聚在一起把整个软件开发就做完,很多时候涉及到跨团队甚至跨公司去并行开发。在这种时候,需要很完善的工具来进行问题的定位。某种程度上来说,很多时候我们需要快速分锅。
我们会提供一些基础的能力:
首先是在线调试。在整个软件的graph上,我们在不同层级提供了不同的能力。
在通信这一层,我们做了一些工具,用于查看整个通信拓扑以及通信节点的状态;同时,我们也做了通信相关的统计,比方说通信节点发送了多少数据,接收了多少数据,接收的延迟是多少;也会有工具去做模拟的数据发送,来进行问题的定位跟踪。
从调度的层面,前面其实有讲过,我们是基于上层Graph界面做调度。但在执行的时候,我们基于proc这个力度做了执行统计,包括执行时长、CPU占用情况。从右侧可以看到,这个图是studio上的一个工具,显示的是整个应用在不同的计算核上的计算分布情况。整个应用在不同计算核上,在某个时间段是哪个task在上面执行。基于这个,可以比较清晰分辨出具体的软件执行情况,来做各种性能问题、功能问题的定位;同时,我们也提供了一些msg trace能力来跟踪整个消息在整个graphlet里面是怎么运行的,可以有效地去做功能定位,比方说我跑着跑着block住了,或者在某些节点有大量的消息积压。
从控制的角度,基于graphlet这一层,我们提供了一些控制的能力,包括基于module/ proc的启停控制、基于graphlet的切换,还有一些配置相关的,这个在功能开发阶段会非常有用。一般不会在量产阶段去做控制,但在功能开发阶段,可能会为了调整功能,需要把整个图里面的某一部分给停掉,或者需要直接把图的执行逻辑改一下。
最后会有一些状态的数据。像前面说到通信的状态、module的节点的状态、整个系统的状态,包括各种资源的使用率、系统执行的基础情况。这是我们在线调试阶段提供的基础能力。
其次,我们有做各种数据分析的一些工具。首先,我们会提供基于pack的各种数据相关的工具。pack是地平线自定义的一套深度数据存储格式。基于pack,我们做了一系列的数据存储查看、查询分析的工具。比方说右侧第二个图,就是用来查看pack里面具体的数据内容。基于pack,我们也做了各种命令行的小工具,比方说基于topic做数据的录制、做数据的回放。在这个过程中做各种基础的控制以及做pack的数据转换。这个转换更多是和第三方做一些数据兼容.比方说,我们现在做了RosBag-to-pack的转换,可以和RosBag做一些简单的互转。
最后,我们也做了一些数据展示相关工具。比如文本的展示,像pack数据展示分析、log数据的展示分析和过滤;以及2D数据的展示,比方说统计数据、2D的image渲染;还有3D的数据展示。
基于这些工具,不管是在开发过程中进行功能调试,还是在出现问题之后,去确定问题是发生在哪个模块,进而进行问题的分解,会提供非常大的帮助,能有效提高开发效率。
前面简单介绍了我们基于TROS.A做软件设计、开发、调试的一些基础内容。接下来,想和大家分享和讨论一下,智驾的发展趋势对软件开发工作的影响。这也是地平线目前正在讨论和预研的,希望分享出来后可以引起更大范围的讨论。
首先,一个很明显的趋势,提出来也有很多年了。智驾相关的电子电气架构,从传统架构,往中央计算平台架构进行迭代,这一趋势已经非常明显了。可以看到,有很多家都提出了舱驾一体。
各种算力平台,特别是一些大算力平台,基本上也可以开始做计算任务的融合。这对于软件开发平台或者说中间件,影响会是什么?
虽然大家在一个平台上,但实际执行的时候需要做多域的隔离。最简单来说,虽然做舱驾一体,但座舱和智驾在很多地方要求会不一样,比方说功能安全等级。这种时候我们就需要做多域隔离。在底层,比如BSP这一层,要做资源隔离引擎;在更上一层,需要去做基于资源隔离引擎的应用框架,然后基于它来做各种调度相关的任务。
基于中央计算平台,整个数据的通信模式会发生比较大的变化。现在常见的多SOC,会有很大的数据量去做SOC之间的交互,比如通过网络、通过PCIE或者通过其他的一些通讯链路。中央计算平台下,数据通讯其实更多会往IPC的方式去发展。这就会要求整个软件平台对于内存管理、对于IPC零拷贝,会提出更高的要求。我们现在也支持零拷贝,但更多是在SoC内。但基于做多域隔离之后,怎么做内存管理,怎么做零拷贝,可能是后面需要去优化的一个方向。
由于多个不同应用都在一个计算平台上运行,但各种计算核实际上是同一套。CPU相对会比较好处理,比方说,有8核或者16核,做多域隔离的时候,可以分别给2个核、4个核。但其他的一些计算资源,比方说DSP,GPU,BPU,可能不会按照核来划分。这时候就需要有设备虚拟化的能力,对不同的应用来说都是一个完整的设备。这些设备可能会使用不同数量的计算资源。我们可能会基于设备虚拟化的技术,去做计算资源的管理。对于上层来说让他能无感地进行使用,而不需要考虑太多应用的计算核的抢占。
最后,基于同一个计算平台,调度其实要求会比较高。前面有讲到,我们现在看到已经有几千个线程,再往后这个数量只会更高。那在这种情况下就需要全局的调度能力。比方说你可能总共就8个核或16核,如果有4000或5000个线程,那花在线程切换上的代价会非常高。我们会真正的把上层的计算任务和底下的执行调度,去做分离和解耦。在全局上去做调度资源的分配,有效地把计算资源给利用起来。
以上是刚才提到的中央架构的演化对智能驾驶软件开发范式的影响。
另一个比较显著的趋势,就是整个智驾智能化的程度会越来越高。最开始我们做智驾的时候,相对来说AI占的比重会比较少。更多的是在感知部分,做各种物体的感知。但现在可以看到,AI模型的能力会越来越强,比方说BEV大模型或者Transformer。另外一部分,就是我们也会把越来越多的任务往AI核上放。比方说,规控有可能就直接在AI核上跑。所以,整个智驾的AI化程度显著的提高。然后和一些同学聊的时候,也得到一个观点,大家也在想后面整个智驾会不会就是一个AI大模型?前面数据结构,中间一个AI大模型,后面直接接对应的控制器。现在确实有这个趋势。
我们前面有提DAG或者graphlet,可以看到它更多是一个在CPU上的纯软的graphlet的概念。但再往后,我们在SoC上不同的计算核越来越多,能力越来越强,整个应用的graphlet可能越来越多,直接在硬件上跑,那实际上整个graphlet可能会硬件化。有可能一个大graphlet,中间有很大一部分都是直接在不同的专用计算核上跑,比方说在BPU或者在DSP上。这种时候,它的调度逻辑、执行逻辑,和在纯CPU上跑会非常不一样,比方说不需要来回去做CPU的中断,通信链路上也不需要在CPU上把数据来回倒腾。整个稳定性和性能其实会有非常显著地提高。
对于开发平台来说,对于这种趋势,我们可能需要设计合适的异构调度框架。然后和现有的调度框架融合起来,做无感地、平稳地过渡。
第三个点,刚才其实也有聊到,大家在说后面整个智驾会不会往大模型的方向去走,有可能智驾工程开发的内容会越来越少。现在,算法工程师和应用工程师其实工作分得还比较开:算法工程师去做算法的迭代、模型的效果,应用工程师来做整个应用的落地。后面这部分工作的区分,就不会那么明显。
对于整个开发平台来说,可能需要提供的一个能力,其实就是“原型即应用”。我们真正在做算法原型的时候,比方说我在x86上做算法原型,直接就可以在SoC上直接去跑,做到无感地切换。把里面大量的通信调度相关东西,屏蔽在底层,上层的工程师可能就不必太关注。
整个应用的开发界面,可能就不会像现在这样,基于C++,然后一个一个的coding,可能是基于一些DSL,甚至基于python的方式去做应用的开发。但底下执行可能是基于编译器,或者基于一些转换的工具,将它转化为可高速执行的二进制文件直接执行。
所以,整个智驾AI化程度越来越高,有可能算法和应用的分界会越来越不明显。对于应用开发平台来说,怎么样去做算法开发、往应用开发过渡以及直接运行,也是我们在探索和讨论的一个点,希望和更多业界的同学有更广泛地讨论。
关于发展趋势,我先和大家分享这两个点。当然,会有更多额外的内容,比方说GPT相关的内容,及Copilot相关的内容等等。这些对后面整个智驾开发的影响都会非常大,期待之后有机会和大家做更多的探讨。谢谢大家。