自动驾驶统一云平台
为每个自动驾驶应用定制云支持将需要维护多个基础设施,可能导致资源利用率低、性能低下以及管理开销高。为解决此问题,作者提出了一种统一云基础设施,采用Spark进行分布式计算,Alluxio进行分布式存储,以及OpenCL来利用异构计算资源,以提升性能和能效。
Clouds 为自动驾驶提供基础架构支持
Clouds 为自动驾驶提供基础架构支持,包括分布式计算、分布式存储和异构计算。在此基础设施之上实现了数据存储、新算法开发的仿真测试、高精度地图生成以及离线深度学习模型训练等关键应用。需要高效的云平台来存储和处理自动驾驶车辆产生的大量原始应用数据,其数据速率可超过每秒2吉字节。
为单个应用程序定制云平台会带来若干问题:
-
缺乏动态资源共享
:为某一应用设计的云平台无法被其他应用使用,即使一个平台空闲而另一个平台已满载。
-
性能下降
:跨应用共享的数据——例如在驾驶仿真工作负载中使用的新生成地图——必须频繁地从一个分布式存储系统复制到另一个,导致在不同系统元素之间性能急剧下降。
-
管理开销
:每个专用平台可能都需要自己的工程师团队来维护。
为了解决这些问题,我们开发了一个统一的云基础设施,为自动驾驶提供分布式计算和存储能力(见图1)。我们还构建了一个异构计算层,以在图形处理器(GPU)或现场可编程门阵列(FPGAs)上加速不同的内核,从而提升性能和能效。我们使用Apache Spark进行分布式计算,Alluxio进行内存存储,以及OpenCL实现异构计算加速。通过结合这三项技术的优势,我们能够提供一个可靠、低延迟且高吞吐量的自动驾驶云。
分布式计算
在构建自动驾驶的分布式计算框架时,我们有两种选择:具有可靠应用记录的Hadoop MapReduce引擎,或提供低延迟和高吞吐量的内存式分布式计算框架Spark。
具体来说,Spark为程序员提供了一个以名为弹性分布式数据集(RDD)的数据结构为核心的API,RDD是一种分布在机器集群上的只读多重集合,以容错的方式维护。Spark是针对MapReduce集群计算范式局限性而提出的解决方案,该范式强制分布式程序采用特定的线性数据流结构:MapReduce程序从磁盘读取输入数据,对数据映射一个函数,归约映射结果,并将归约结果存储到磁盘上。
相比之下,Spark的RDD充当分布式程序的工作集,提供了一种受限形式的分布式共享内存。通过使用内存中的RDD,Spark可以将迭代计算的延迟降低数个数量级。
为了确定Spark是否可以作为自动驾驶的可行解决方案,我们评估了其提供所需性能提升的能力。首先,为了验证其可靠性,我们部署了一个由1000台机器组成的Spark集群,并对其进行了为期三个月的压力测试。这帮助我们发现了系统中的一些漏洞,主要集中在内存管理方面,这些漏洞会导致Spark节点崩溃。在修复这些漏洞后,系统连续数周运行平稳,极少发生崩溃。其次,为了量化性能表现,我们在MapReduce和Spark集群上运行了大量的SQL查询。在相同的计算资源下,Spark的性能平均超过MapReduce 5×。
在百度每天执行的一次内部查询中,MapReduce耗时超过1000秒,而Spark仅用150秒就完成了任务。
分布式存储
在选择分布式计算框架后,我们需要确定分布式存储引擎。同样,我们面临两个选择:Hadoop分布式文件系统(HDFS),它提供可靠的持久化存储,或Alluxio,一种以内存为中心的分布式存储系统,能够在集群框架之间以内存速度实现可靠的数据共享。
具体而言,Alluxio使用内存作为默认存储介质,并提供内存速度的读取和写入性能。然而,内存是一种稀缺资源,因此我们必须确定Alluxio是否能够提供足够的存储空间来保存所有数据。幸运的是,Alluxio具有分层存储功能,可以管理包括内存、固态硬盘和机械硬盘在内的多层存储。通过使用分层存储,即使在内存容量有限的部署环境中,Alluxio也能同时在系统中存储更多的数据。Alluxio会自动管理所有已配置层级之间的数据块,因此用户和管理员无需手动管理数据位置。本质上,内存作为一级缓存,固态硬盘作为二级缓存,机械硬盘作为三级缓存,持久化存储则作为最后一级。
在我们的云平台中,Alluxio与计算节点共同部署,并作为缓存层以利用空间局部性。因此,计算节点可以读取和写入Alluxio;Alluxio随后异步地将数据持久化到远程存储节点中。使用该技术,我们相比仅使用HDFS实现了30×倍的加速。
异构计算
默认情况下,Spark使用通用中央处理器作为其计算载体。然而,这可能并非所有类型工作负载的最佳选择。例如,图形处理器天生具有巨大的数据并行性,非常适合图像卷积等高密度计算任务。
我们在基于卷积神经网络(CNN)的目标识别任务上比较了图形处理器与中央处理器的性能,发现图形处理器的性能轻松超过中央处理器10到20倍。另一方面,现场可编程门阵列是向量计算的低功耗解决方案,而向量计算是大多数计算机视觉和深度学习任务的核心。利用异构计算载体显著提升了性能和能效。
我们在集成这些异构计算时面临两个关键挑战:
1. 如何为不同的工作负载动态分配不同的计算资源;
2. 如何将工作负载无缝调度到计算底层。
为了解决第一个问题,我们使用Apache Hadoop YARN和Linux容器(LXC)进行作业调度与分发(见图2)。YARN为分布式计算系统提供资源管理和调度功能,使多个作业能够高效地共享一个集群。LXC是一种操作系统级虚拟化工具,可在同一主机上运行多个相互隔离的Linux系统(容器)。它能够对中央处理器、内存、块输入/输出、网络及其他资源进行隔离、限制和优先级划分。LXC使得在同一主机上以极低开销有效地共置多个虚拟机(VM)成为可能。例如,我们的实验表明,中央处理器托管Linux容器的开销比原生运行应用程序低5%。
当启动Spark应用程序时,它可以通过YARN请求异构计算资源,然后YARN会分配Linux容器以满足该请求。Spark工作节点可以托管多个容器,每个容器可能包含中央处理器、图形处理器或现场可编程门阵列。在这种情况下,容器提供资源隔离,以实现高资源利用率以及任务管理。
为了解决第二个问题,我们需要一种机制来无缝连接Spark与这些异构计算资源。由于Spark默认使用Java虚拟机,首要挑战是将工作负载部署到本地空间。鉴于Spark以RDD为中心的编程接口,我们开发了一种异构计算RDD,它可以通过Java本地接口将计算任务从托管空间调度到本地空间。
我们还需要一种机制,将工作负载分派到GPU或FPGA上执行。为此,我们选择了在不同异构计算平台上均可用的OpenCL。在OpenCL设备上执行的函数称为内核。OpenCL定义了一个应用程序编程接口,允许在主机上运行的程序在异构设备上启动内核,并管理设备内存。
仿真测试
我们提出的用于自动驾驶的统一云平台支持多种应用。其中,包括用于新算法部署的分布式仿真测试。
在新算法有资格部署到实际车辆上进行道路测试之前,必须进行彻底的测试。一种仿真方法是通过机器人操作系统(ROS;www.ros.org)重放数据以识别问题。在单台机器上测试新算法要么耗时过长,要么无法提供足够的测试覆盖。因此,我们利用Spark构建了一个分布式仿真平台,使我们能够在多个计算节点上部署新算法,为每个节点提供不同的数据片段,并汇总测试结果。
BinPipeRDD
Spark的原始设计假设输入为文本格式,例如通过空格/制表符分隔键和值的记录,或通过回车字符分隔的记录。然而,在二进制数据流中,键/值字段中的每个数据元素可以是任意值。
为了解决这个问题,我们设计并实现了BinPipeRDD。图3展示了BinPipeRDD在Spark执行器中的工作方式。首先,经过分区的多媒体二进制文件通过编码和序列化形成二进制字节流。所有支持的输入格式(包括字符串(例如,文件名)和整数(例如,二进制内容大小))都被编码为基于字节数组的统一格式。序列化将所有字节数组(每个可能对应到一个输入二进制文件)合并为单个流。
用户程序接收到该流后,对其进行反序列化并解码为可理解的格式。然后,用户程序执行目标计算(图中的“用户逻辑”),范围从简单的任务(如将JPEG文件旋转90度)到相对复杂的任务(如根据激光雷达(光检测与测距)传感器读数检测行人)。输出结果随后被编码并序列化,再以RDD[Bytes] partitions的形式传递。在最后阶段,这些分区通过收集操作返回给Spark驱动器,或作为二进制文件存储在HDFS中。
通过此过程,二进制数据可以被转换为用户定义格式,并且Spark计算的输出被转换为用于收集操作的字节流。根据应用需求和逻辑,该字节流又可以在HDFS中被转换为文本或通用二进制文件。
将Spark连接到ROS
通过BinPipeRDD,Spark能够消费ROS bag数据,但我们还需要一种在Spark中启动ROS节点的方法,以及实现ROS节点与Spark之间通信的机制。
一种选择是设计一种新的RDD形式来集成ROS节点和Spark执行器,但这需要修改ROS和Spark的接口。为了避免不得不维护不同版本的ROS,我们选择独立地启动ROS和Spark,同时将ROS节点和Spark执行器共置于同一位置,并为它们提供Linux管道以进行通信。Linux管道创建了一个单向数据通道,用于进程间通信,其中内核会缓冲写入管道写端的数据,直到从管道的读端读取这些数据。
系统性能
在开发系统的过程中,我们持续评估了其性能。首先,我们在一百万张图像上执行了基础的特征提取任务(总数据集大小为> 12 TB)。当我们将CPU核心数量从2,000扩展到10,000时,执行时间从130秒减少到约32秒,展现了极具前景的线性可扩展性。接下来,我们运行了一个内部回放缓冲示范测试集。耗时在单个Spark节点上完成仿真大约需要3小时,而在8个节点上仅需约25分钟,再次展示了出色的可扩展性潜力。
模型训练
我们统一云基础设施支持的另一个应用是离线模型训练。为了实现高性能,它为参数服务器提供了无缝的GPU加速以及内存存储。
由于自动驾驶依赖于不同的深度学习模型,因此必须提供持续更新,以不断提高模型的有效性和效率。鉴于生成的原始数据量巨大,使用单个服务器无法实现快速模型训练。为了解决这一问题,我们开发了一个高度可扩展的分布式深度学习系统,使用Spark和百度并行分布式深度学习(Paddle)平台(www.paddlepaddle.org)。在Spark驱动器中,我们可以管理一个Spark上下文和一个Paddle上下文,而在每个节点上,Spark执行器托管一个Paddle训练器实例。在此基础上,我们使用Alluxio作为参数服务器。通过该系统,即使增加更多资源,我们也实现了线性的性能扩展,证明了该系统具有高度可扩展性。
为什么选择Spark?
有人可能会疑惑,既然现有的深度学习框架都具备分布式训练能力,为何我们仍选择Spark作为离线模型训练的分布式计算框架。主要原因在于数据预处理可能包含多个阶段,例如ETL(提取、转换、加载)操作,而不仅仅是简单的特征提取。若将每个阶段视为独立流程,会导致对底层存储(如HDFS)产生大量的输入/输出,我们的测试表明,这常常成为处理流水线中的瓶颈。
Spark以RDD的形式将中间数据缓存在内存中。处理阶段自然形成一个流水线,在各阶段之间无需频繁访问底层存储的远程输入/输出。通过这种方式,系统在流水线开始时从HDFS读取原始数据,然后以RDD的形式将处理后的数据传递到下一阶段,最后将数据写回HDFS。该方法使系统吞吐量平均提升了一倍。
训练平台架构
图4显示了训练平台架构。一个Spark驱动器管理所有Spark节点,每个节点上运行着一个Spark执行器和一个Paddle训练器。该架构通过将所有训练数据划分为分片来利用数据并行性,使得每个节点独立处理一个或多个分片。
为了同步Spark节点,在每次训练迭代结束时,系统必须汇总每个节点的参数更新,进行计算以得出一组新参数,然后将这组新参数广播到每个节点,以便它们可以开始下一次训练迭代。如果我们把这些参数存储在HDFS中,输入/输出将成为性能瓶颈。为缓解此问题,我们使用Alluxio作为参数服务器。如前所述,Alluxio利用内存存储来优化输入/输出性能。使用Alluxio后,我们观察到相比HDFS的I/O性能提升达到了5×。
异构计算
接下来,我们探讨了异构计算如何提高离线模型训练的效率。第一步,我们比较了卷积神经网络中图形处理器和中央处理器的性能。使用内部目标识别模型和OpenCL架构,我们观察到使用GPU可实现15×倍的加速。第二步是确定该架构的可扩展性。在我们的机器上,每个节点配备一张GPU卡。随着GPU数量的增加,每轮训练延迟几乎呈线性下降(见图5)。这一结果表明,在拥有更多训练数据的情况下,增加计算资源可以显著缩短训练时间。
高精度地图生成
我们统一云基础设施支持的第三种应用是高清(HD)地图生成。这是一个涉及多个阶段的复杂过程,包括原始数据读取、过滤与预处理、位姿恢复与优化、点云配准、二维反射图生成、高精地图标注以及最终地图的输出。Spark的内存计算机制消除了将中间数据存储到硬盘的需求,从而使得将所有这些阶段连接为一个作业成为可能。通过使用Spark和异构计算,我们减少了流水线阶段之间的输入/输出,大大加速了地图生产流程。
高精地图
自动驾驶的高精地图包含多个信息层。最底层是关于环境的原始激光雷达生成的高程和反射数据的网格地图,粒度约为5厘米× 5厘米。当车辆移动时,它们会将新采集的激光雷达数据与该网格地图进行实时比对,初始位置估计由全球定位系统(GPS)和/或惯性测量单元(IMU)提供,以辅助实现精确自定位。
在网格图层之上是多个语义信息层。例如,车道标签使自动驾驶车辆能够判断自身是否处于正确车道,并与相邻车道保持安全距离。此外,车辆使用交通标志标签来确定当前限速以及附近交通标志的位置,以防车载传感器未能检测到这些标志。
云中的地图生成
为了获得精确的车辆位置信息,高精度地图生成过程会融合来自多个传感器的原始数据。例如,轮速里程计和惯性测量单元数据可用于进行传播——即,在固定时间内推导车辆的位移。然后可以使用全球定位系统和激光雷达数据来校正传播结果以最小化误差。
地图生成的计算可以分为三个阶段。首先,对车辆的原始惯性测量单元、轮速里程计、全球定位系统和激光雷达数据进行即时定位与地图构建(SLAM),以确定每次激光雷达扫描的位置。其次,进行点云配准,将独立的激光雷达扫描拼接在一起,形成连续的地图。第三,在网格地图上添加标签和其他语义信息。
与离线模型训练类似,我们使用Spark将这些阶段连接在一起,并将中间数据缓存在内存。与每个阶段使用单独作业相比,该方法实现了5×倍的加速。通过利用我们的异构计算基础设施,还将最耗时的地图生成操作——迭代最近点(ICP)点云对齐的核心操作卸载到图形处理器,从而实现了30×的加速。
Distributed 计算、分布式存储以及通过异构计算能力实现的硬件加速,都是支持不同自动驾驶应用所必需的。
为自动驾驶应用定制云支持每个应用程序都需要维护多个基础设施,可能导致资源利用率低、性能低下以及管理开销高。我们通过构建统一云基础设施解决了这一问题,该基础设施采用Spark进行分布式计算,Alluxio用于分布式存储,OpenCL用于利用异构计算资源,从而提升性能和能效。目前,我们的基础设施支持新算法部署的仿真测试、离线深度学习模型训练以及高精度地图生成,并具备可扩展性,能够满足这一快速发展的领域中新出现应用的需求。
1250

被折叠的 条评论
为什么被折叠?



