分享嘉宾
杨林三-辉羲智能
关于辉羲智能
辉羲智能是一家做自动驾驶芯片的初创公司,成立于2022年。致力打造创新车载智能计算平台,提供高阶智能驾驶芯片、易用开放工具链及全栈自动驾驶解决方案,助力车企实现优质高效的自动驾驶量产交付,构建低成本、大规模和自动化迭代能力,引领数据驱动时代的高阶智慧出行。
分享提纲
- 创业公司中,如何使用 Alluxio ?
- 从0-1使用 Alluxio 的过程(调研-部署-上生产)。
- 实践经验分享。
分享主题
《 Alluxio 在自动驾驶模型训练中的应用与部署》
下文为完整文字版分享内容
自动驾驶数据闭环
首先分享一下自动驾驶中怎么样构建数据闭环,这个业务过程可能大家都有所了解。自动驾驶会包含多种车辆类型,比如数采车辆、带着算法在路上跑的车。数据采集就是在跑的过程中采自动驾驶车上的各种数据:比如说 camera 的数据就是图片,激光雷达的数据是点云。
传感器数据采回来,可能一辆车每天跑下来就有几T的数据。这种数据通过基盘的方式或者其他上传方式把它们整体存储起来,传到对象存储里面。原始数据存储之后会有一个 pipeline 做数据的解析预处理,比如把它切成一帧一帧的数据帧,每帧的不同传感器数据之间可能还要做同步对齐的操作。
完成数据解析之后,就要在上面做更多的挖掘。构建一个一个的数据集。因为不管是在算法、仿真或者测试里面,都要构建数据集。比如说我们想要雨天的某一个晚上,某一个路口,或者一些密集形成区域的数据,那我们就会在整个系统里面有大量的这种数据需求,要做数据的打标,打上一些标签。比如说在清华东门这个地方,需要去拿这个位置的经纬度,解析周围的 POI。之后再对挖掘出来的数据做标注。常见的标注有:对象、行人、对象的类型等。
这种做了标注的数据,会被拿去做训练。典型的一些任务,比如目标的检测、车道线的检测、或者更大的端到端的模型。模型训练好了之后,还要做一些仿真验证。验证完再把它部署到车上面,再去跑数据,在这个基础上再去采更多的数据。就是这样的一个循环,不断的去丰富数据,不断的去构建性能更好的模型。这是整个训练,数据闭环要做的事情,也是现在自动驾驶研发里面较核心的事情。
算法训练:NAS
我们聚焦到模型训练来讲:模型训练主要是通过数据挖掘拿到数据,从而生成一个数据集。数据集在内部是一个 pkl 文件,包含数据、channel、存储位置,最后数据算法训练的同学会自己写下载脚本,把数据从对象存储拉到本地。
我们在选用 Alluxio 之前,是通过NAS 系统充当缓存的作用,把对象存储的数据拉到 NAS 上面,最后再用不同的模型,把数据 load 进来进行训练。这是使用 Alluxio 之前,大概的训练流程。
其中最大的问题在 NAS :
- 并发性能比较差——NAS我们可以理解成它就是一块大的硬盘,当只有几个任务一起跑的时候,还是比较够用的。但是当有几十个训练任务同时进行、很多模型在训练的时候,往往就会出现卡死。我们曾经有一段时间卡死非常严重,研发每天都叫苦不迭。卡得严重以至于可用性非常差、并发性能很差。
- 管理困难——每一个人都用自己下载的脚本,然后把想要的数据下载到自己的目录下面。另一个人可能又自己去下另外一堆数据,放到NAS的另外一个目录下面,这样就会造成NAS空间满时很难做清理。当时我们基本都是当面或者微信群沟通。一方面是效率特别低,依靠群消息管理会滞后。另外一方面,也会因为手动remove,导致一些风险。我们曾经出现过remove 数据时,把别人的数据集给删掉的情况。这也会造成线上任务区域的报错,这是另外一个痛点。
- 空间浪费——不同人下载的数据放在不同目录下,有可能同样一帧数据会出现在好几个数据集,存在比较严重的空间浪费。
- 使用很复杂——因为 pkl 里面的文件格式不相同,使得下载逻辑也不一样,每个人都要单独去写下载程序。
这是我们之前用NAS会面临的一些困难和问题,为了解决这些问题,我们做了调研。调研后聚焦到Alluxio上来。发现Alluxio它可以提供一个比较统一的缓存,缓存可以提升我们的训练速度,同时也可以减少管理成本。我们还会用Alluxio的系统,处理双机房的问题。通过统一的命名空间和访问方式,一方面可以简化我们的系统设计,另外在代码实现上也会变得很简单。
算法训练引入Alluxio
当我们把 NAS 换成Alluxio之后,Alluxio能够针对性的解决刚才提到的一些问题:
- 在并发性方面:NAS本身不是一个完全分布式的系统,而Alluxio是。NAS它访问的 IO 达到一定的速度时会出现卡顿,可能达到几个 G/s的时候就会开始卡。而Alluxio的上限非常高,我们下面还有专门的测试来说明这一点。
- 通过手动清理或者管理会非常麻烦:Alluixo会配置缓存的逐出策略。一般是通过LRU,当到一个threshold的时候(比如90%)它会自动做缓存的驱逐和清理。这样做的效果:
- 效率大大得提升;
- 可以避免因为误删导致的安全性问题;
- 解决了重复数据的问题。
在Alluxio里面,一个 UFS 里面文件,对应到Alluxio就是一个路径,当所有人都去访问这个路径时,就可以拿到对应的数据,这样就不会存在重复数据的问题。另外使用上面也比较简单,我们只需要通过 FUSE 的接口方式访问,不再需要下载文件。
以上是从逻辑层面解决了我们刚才讲的各种各样问题。下面讲一讲,我们整个落地的历程,怎么从 0 到 1 实现Alluxio从开始的 POC 测试,到各种性能的验证,再到最后怎么样部署、运维。我们的一些实践经验。
Alluxio部署:单机房
首先,我们可能会在单机房里部署,就是一定要临近GPU,部署到GPU节点上。同时利用之前GPU 上很少用的SSD,把每个节点都利用起来,然后把 FUSE 和 worker 部署在一起。FUSE就相当于客户端,worker 就相当于一个具有内网通信的缓存小集群,做FUSE 的服务。最后对应的通过 worker 自己对底层的对象存储做通信。
Alluxio部署:跨机房
但是由于各种各样的原因,我们还会有跨机房的存在。现在有两个机房,每一个机房里都会有对应的 S3 服务,也会有相应的 GPU 计算节点。基本上每一个机房我们都会部署一个Alluxio。同时在这个过程中也要注意,一个机房里可能是两个Alluxio的对象存储,另外一个机房如果也要做 S3 挂载,尽量做好 bucket 名字的统一规划,不能把两个搞重了。比如这里有个bucket 1,那里又有一个bucket 1,会导致Alluxio挂载时的一些问题。
还要注意,不同的 endpoint 要注意内网和外网的区分,比如集群1的Alluxio,挂载集群1的endpoint内网,在另一边就是外网,反之性能就会大打折扣。挂载之后我们可以通过同样的路径去访问不同集群上面不同 bucket 的数据,这样其实整个架构就会变得非常简单,这是跨机房部署方面。
Alluxio测试:功能
想要真正把NAS换成Alluxio,在部署之前要做很多功能测试。这种功能测试,目的是让现有的算法流程通过最小程度的改造,让算法同学也能用起来。这里可能要根据各位实际情况去操作。我们当时和Alluxio做过接近2-3周的 POC验证,其中会涉及到,比如说:
- K8S 上访问 PVC 的配置;
- 数据集的组织方式;
- 作业提交的配置;
- 访问路径的替换;
- 最终访问的脚本接口。
以上遇到的诸多问题可能都要做验证,至少我们要通过它选一个典型任务,然后做一些改造,最后才能把 NAS 比较平稳的换成Alluxio。
Alluxio测试:性能
接下来在这个基础上,还要做一些性能测验。在这个过程中,不管是单机还是多机,我们都做了比较充分的测试。在单机上,Alluxio和原来的 NAS 基本上性能是打平的。
其实真正体现Alluxio优势的是多主机上、分布式的能力。可以看到 NAS 或者我们举例的QTS,它有一个非常明显的点:不稳定。测试3G 到 10G 间波动会比较大,同时它有一个明显的瓶颈,达到 7/8G 左右,就基本上稳定了。
而Alluxio这边,整个测试过程,节点随着运行实例的增加,可以达到一个非常高的上限,我们当时设到 20GB/s时,它都还是呈现出一直向上的趋势。这说明Alluxio整个并发的、分布式的性能非常好。
Alluxio落地:调参适配环境
做完功能验证和性能测试之后,就真正的要实际部署Alluxio集群,部署好之后,需要一个参数调参适配的过程。因为测试时,只采用了一些典型的任务,真的上Alluxio环境之后,会发现随着任务增多,会有一个参数调参适配的过程。需要把Alluxio 上面相应的参数跟实际运行环境做匹配,然后才能够把它性能给发挥好。所以会有边运行、边运维、边调参的过程。
我们经历了一些典型的调参过程,比如说:
- 这里列的 ETCD 的节点。一开始是 1 ,后面变成 3 ,这样就可以保证它是一个ETCD被挂了,不至于整个集群就都给挂了。
- 还有与 S3 相关的。比如说Alluxio在实现的时候,他会让S3生成一个访问比较长的路径,会在中间的路径节点,默认写一些空白,以至于让它具有更好的性能。但是这种情况下,我们训练任务下面的 S3 ,是做了权限管控的,不允许他们去写这种数据。面对这种冲突,也需要调参。
- 还有像 FUSE 节点本身能忍受的并发强度的能力。包括它要使用的Direct Memory的大小,实际上也和整个业务实际运行并发的强度多少有很大关系。和能够一次性访问的数据量其实是有很大关系的,这也有一个调参的过程,不一而足。可能会在不同环境下遇到不同的问题。这也是选择Alluxio企业版的原因。因为在企业版的过程中Alluxio会有非常强的支持, 7* 24h 都可以做到遇到问题去调整、去配合。有了相互配合的周期,才能够让整个集群比较顺畅地运行起来。
Alluxio落地:运维
我们这个团队最早运维的同学只有一个人,他负责很多底层Infra 的维护和相关工作,当我要把Alluxio部署上来的时候,其实运维那边的资源是不够的,所以相当于我也兼半个运维。从自己要去运维一个东西的角度来说,要做好很多运维方面的记录和知识沉淀,特别是对一个新手来讲很重要。比如下一次出现问题怎样更好地解决,是不是之前已经有过这样的经验。
针对我们当时的环境,会维护好三份文档。
- 运维的历史记录文档:比如说哪一天出现了什么问题,这些问题我找到它根因是什么,它的解决方案是什么?具体操作是什么?
- 操作文档:比如我们在 K8S 上面去运维,它的重启是哪几步、操作是什么、出现问题怎样去看日志、怎样去排查、去看FUSE对应的数据是哪个任务、哪个 work 上面去运行、监控等等。都是常用的一些操作。
- 配置的变更:因为Alluxio具体在调参的过程中。不同的时候,可能遇到的配置文件、yaml 文件是不一样的,可能还要做一些备份。可以用 Git 管理,也可以简单地采用文档管理。通过这种方式可以追溯到当前配置和历史配置版本。
在此基础上,我们还会有一些相关的配套建设,就是为了更好地使用 Alluxio。研发同学使用下来认为Alluxio蛮好用的。但多任务的时候,就暴露出来一些配套建设的需求。比如我们要去做图片的resize,把图片从一开始高清4K ,降到 720P ,以便支持更多的任务缓存。
训练数据集做跨集群同步,以便更好的做数据预加载。这些都是围绕着Alluxio要做的系统化建设。
Alluxio落地:共同进步
在我们不断使用Alluxio的过程中,也会发现一些值得改进的地方,我们通过给Alluxio反馈,促进了整个产品的迭代,这里特别提到几点,
从研发算法同学那边,他们care的是:
- 稳定性:一定要在运行过程中稳定,不能因为Alluxio,一些东西 crash 了,让整个系统训练受阻。这里面可能有一些运维的小技巧,比如说尽可能不要让 FUSE 重启。刚才也提到了 FUSE 重启就意味着它的访问路径,读数据文件的时候,会失败、出现 IO 的error。
- 确定性:比如Alluxio之前建议数据不需要做预加载,即不需要在预训练之前读一遍,只需要在第一个 epoch 过程中读一遍。但是因为研发有发版周期,他要明确的知道预加载要多长的时间,如果通过第一个 epoch去读,很难预估整个训练时间。这里面其实也会引申出来,怎样通过一个 file list做缓存这件事情,这个也给Alluxio提了一些需求。
- 可控性:虽然Alluxio是可以提供自动化的基于 LRU 的缓存驱逐清理缓存。但是实际上研发还是希望,一些已经缓存过的数据,能够主动做一些清理。那么能不能也通过提供 file list,让Alluxio把这块数据给 free 掉。这也是我们除了间接的用Alluxio,还要直接的、非常可控的用Alluxio的需求。
从运维的这一端,也会提一些需求:
- 配置中心:Alluxio自己可以提供一个配置中心,把配置的历史给保存下来。增加一个功能以便实现配置项更改时,提前预算到这个改动到底影响的是什么;
- Trace跟踪一个命令的运行过程:另外一个比较现实一点的需求,比如现在发现一个问题:访问底层的一个 UFS 文件时延时比较高,到底是什么原因?我们看 FUSE 的日志可能看不出原因,得需要再去看 location 对应的worker日志。这其实是一个非常耗时、麻烦的过程,而且往往排查不了问题,还需要Alluxio的线上客服支持。Alluxio能不能加一个 Trace 命令,在要做访问的时候,把 FUSE 耗时、work 耗时、以及从 UFS 里面读它的耗时,一个全链路的耗时问题给 Trace 出来。这样其实对整个运维过程或者排查过程会有比较大的帮助。
- 智能监控:有时候监控的东西是我们已经知道的东西。比如说Direct Memory 有问题了,我们去配一个监控项。但是如果下一次一个新问题在我的日志里面出来了,它可能是一个隐藏的问题,在人不知道的情况下悄悄地发生。这种情况我们希望可以自动的监控出来。
我们通过工单反馈的方式,给Alluxio提了各种各样的建议。希望Alluxio能够在产品迭代过程中,提供更强大的功能。把整个研发、运维 care的事项,做到更好的满足。
小结
第一,从Alluxio在整个自动驾驶模型训练的缓存加速方面,对比 NAS它提供了很好的可用性。对我们来说它也会有10倍左右的提升。成本的降低来源于两部分:
- 产品采购成本低;
- NAS可能会有20%-30%的冗余存储,Alluxio都可以解决掉。
从可维护性的角度来讲,它可以自动清理数据,更加及时,也更加安全。易用性方面,它通过 FUSE 可以更便捷的访问数据。
第二,我也分享了辉羲是怎么样去从 0 到 1 部署Alluxio,运维一个系统。
以上就是我的分享,谢谢大家。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。