介绍Neuropod,Uber ATG的开源深度学习推理引擎

0.
介绍Neuropod,Uber ATG的开源深度学习推理引擎

优步高级技术组(ATG)在美国,我们利用深度学习提供安全可靠的自动驾驶技术。使用深度学习,我们可以建立和训练模型来处理诸如处理传感器输入、识别物体以及预测这些物体可能会去哪里等任务。

随着自动驾驶软件的发展,我们一直在寻找新的方法来改进我们的模型,有时,这意味着尝试不同的深度学习(DL)框架。随着新的DL框架的发布,现有的框架,比如纹orflow.Pytorch.推进,我们希望确保我们的工程师和科学家能够灵活地利用最适合他们正在努力的问题的工具。

不幸的是,在整个整个中增加了对新的深度学习框架的支持机器学习堆栈资源和时间密集。在ATG,我们花了很多时间努力让这个过程更容易。今天,我们通过介绍来开放这些努力神经。neuropod是一个抽象层,位于现有的深度学习框架之上,提供了运行DL模型的统一接口。Neuropod使研究人员能够轻松构建其选择的框架中的雷竞技是骗人的模型,同时也简化了这些模型的制造。

使用多个深度学习框架

深度学习(DL)发展非常迅速,不同的DL框架在不同的任务中有效。因此,在过去几年里,我们在Uber ATG使用了几个DL框架。2016年,咖啡因2是我们主要的深度学习框架,2017年初,我们投入了大量的工作来整合纹orflow.。这涉及与CUDA和CUDNN的主要一体化障碍,Caffe2和Tensorflow的依赖关系之间的冲突,图书馆加载问题等等。在2017年底,我们开始开发更多型号Pytorch.。生产这些模型也花了很多工作。我们在沿着tensorflow旁路和几个难以调试的其他问题时看到了内存损坏问题。然后Torchscript.我们又经历了一次类似的过程。

图1.多年来,优步ATG已经发展到机器学习方法,利用不同的流行深度学习框架。

自2018年以来,几个DL框架已开放,包括Ludwig(由优步建造!),jax.Trax.亚麻Haiku.,和rlax.其中很多都是在过去九个月里被释放的。

即使是研究人员很容易尝试新框架,在所有系统和流程雷竞技是骗人的中为新的DL框架添加生产支持也不是小任务。这一部分使得这很困难是它需要为我们的基础架构和工具的每件作品集成和优化工作。

图2.难以为新框架添加支持,因为运行模型的每一块基础架构都需要支持所有框架。这些基础架构组件可以是度量流水线,型号服务或其他生产和测试环境。

2018年底,Uber ATG开始构建多种模型,以不同的方式解决了同样的问题。例如,使用LIDAR的3D对象检测可以进行范围视图要么鸟瞰。这两种方法都有效,具有不同的利弊。不同团队建造的模型有时也在不同的框架中实现。

为了使生产更容易,我们希望能够轻松地互换解决同样问题的模型,即使它们是在不同的框架中实现的。

我们还会看到一些案例,新的研究将在Pytorch中的代码出来,我们希望雷竞技是骗人的快速比较Tensorflow中的现有模型。由于我们有框架特定于每个模型的模型级度量管道,因此很难这样做。

要在新框架中部署模型,我们需要重建模型级度量流水线,整合在我们所有系统和流程中的框架,然后进行额外的优化,以确保我们在我们的延迟预算中运行模型。

虽然这些步骤看起来很简单,但是像上面描述的问题(内存损坏、依赖冲突等)导致我们花费大量的精力来解决集成问题,而不是专注于模型开发。

我们需要一种方法来最大限度地在研究期间最大限度地提高灵活性,而无需重做工作过程中的其他部分。雷竞技是骗人的

介绍神经飞机

我们解决这个问题的方法是神经,一个开源库,使DL框架在运行模型时看起来相同。现在,在所有工具和基础架构上添加对新框架的支持就像将其添加到Neuropod一样简单。

图3. neuropod是一种抽象层,提供统一接口,以从多个框架运行深度学习模型。

目前,Neuropod支持几个框架,包括Tensorflow,Pytorch,Keras和Torchscript,同时简单地添加新的框架。

自2019年初在优步内部发布以来,Neuropod一直在帮助优步快速部署新模式。在过去的一年里,我们在Uber ATG、Uber AI和Uber核心业务上部署了数百个Neuropod模型。这些模型包括需求预测模型、预计到达时间(ETA)预测模型、Uber Eats的菜单转录模型以及自动驾驶汽车的目标检测模型。与Neuropod开源释放,我们希望机器学习社区的其他人也能发现它的帮助!

概要

神经pod从问题定义的概念开始-对模型要解决的“问题”的正式描述。在这种情况下,问题可能是图像的语义分割或文本的语言翻译。通过正式地定义一个问题,我们可以将其视为一个接口,并抽象出具体的实现。每一个Neuropod模型都实现了一个问题定义。因此,任何解决相同问题的模型都是可互换的,即使它们使用不同的框架。

Neuropod通过在Neuropod封装(或“神经内容”短暂)中包装现有模型来作用。此包包含原始模型以及元数据,测试数据和自定义操作(如果有)。

使用Neuropod,任何模型都可以从任何支持的语言执行。例如,如果用户想要从C ++运行Pytorch模型,则Neuropod将旋转罩下的Python解释器并与其通信以运行模型。这是必要的,因为Pytorch模型需要一个Python解释器来运行。此功能可让我们快速测试Pytorch型号,然后努力将它们转换为Torchscript.,它可以从c++本地运行。

Neuropod目前支持从Python和C ++的运行模型。但是,为库编写额外的语言绑定是直接的。例如,米开朗基罗如,Uber的ML平台,使用Neuropod作为其核心DL模型格式,并实现了Go绑定以运行其生产模型。

图4。Neuropod有一个特定于框架的封装API和一个框架无关的推理API。

推断概述

在我们挖掘NeioPod如何运作之前,让我们来看看传统上融入应用程序的深度学习模型:

图5.通常,应用程序在整个推理过程中直接与深度学习框架交互。

在上图中,应用程序在推理过程的所有部分中直接与TensorFlow API相互作用。

使用Neuropod,应用程序仅与框架 - 不可知的API(下面的紫色中的一切)互动,而Neuropod将这些框架 - 不可知的呼叫转化为对底层框架的调用。我们可以在尽可能使用零拷贝操作的情况下实现这一点。有关更多详细信息,请参阅下面的“优化”部分。

图6。使用Neuropod,应用程序与框架无关的API交互,而Neuropod与底层框架交互。

Neuropod具有可插拔后端层,每个支持的框架都有自己的实现。这使得将新框架添加到Neuropod的简单方面是直接的。

深度学习neuropod

让我们来看看使用Neuropod的整体深度学习过程,看看它如何有助于进行实验,部署和迭代更容易。

问题定义

要打包neuropod,我们必须首先创建一个问题定义。如上所述,这是我们试图解决问题的输入和输出的规范描述。此定义包括所有输入和输出张量的名称,数据类型和形状。例如,2D对象检测的问题定义可能看起来像这样:

请注意,上面的定义在形状定义中使用“符号”(num_classes.num_detections.)。符号的每个实例都必须在运行时解析到相同的值。这提供了比仅设置形状元素的制约形状更强大的方式没有。在上面的例子中,num_detections.都是一样的吗盒子object_class_probability.

为了简单起见,我们将在这篇文章中使用一个更简单的问题:添加。

上面的代码片段还定义了我们将在下面讨论的测试输入和输出数据。

生成占位符

一旦我们定义了一个问题,我们就可以使用Neuropod自动生成一个占位符模型来实现问题规范。这允许我们在还没有实际模型的情况下就开始集成。

生成的模型采用问题规范中描述的输入,并返回与输出规范匹配的随机数据。

建立模型

在我们建立了问题定义(以及选择占位符模型)之后,我们可以构建我们的模型。我们经历了所有正常的建筑和培训模型的步骤,但现在我们将Neuropod出口步骤添加到该过程的结尾:

在上面的代码段中,我们将模型作为NeUropod导出以及可选的测试数据。如果提供了测试数据,库将在导出后立即在模型上运行自检。

选项create_tensorflow_neuropod所有其他包装纸都很好记录

建立指标管道

现在我们有我们的模型,我们可以在Python中构建一个标准管道。与没有Neuropod的唯一区别在没有Neuropod的情况下,我们现在使用Neuropod Python库运行模型的代替使用框架特定的API。

neuropod.文件包含有关更多详细信息load_neuropod推断

使用Neuropod构建的任何指标管道只需要每次问题建造一次,从那里开始,在比较模型时成为真理源(甚至跨框架)。

整合

现在,我们可以将我们的模型集成到生产C ++系统中。下面的示例显示了Neuropod C ++ API的非常简单的用法,但库也支持更复杂的使用,允许有效,零复制操作和包装现有内存。请参考Neuropod文档更多细节。

与没有Neuropod的集成过程不同,此步骤必须仅发生一次,每个框架也不一次。用户不需要弄清楚Tensorflow或Torch C ++ API的复杂性,但是当研究人员决定他们想要使用的框架时,仍然可以提供很多灵活性。雷竞技是骗人的

此外,由于核心神经内容库是在C ++中,我们可以为各种其他语言写入绑定(包括GO,Java等)。

优化

在Uber ATG,我们具有非常严格的延迟要求,因此有许多关键操作的零拷贝路径。我们将大量工作投入剖析和优化,现在Neuropod可以成为实现适用于所有模型的推理优化的中央处。

作为这项工作的一部分,每个Neuropod提交都在我们的连续集成(CI)管道中的以下平台上进行了测试:

    • Mac,Linux,Linux(GPU)
    • Python的5个版本
    • 每个版本都支持深度学习框架

看看我们的文件最新的支持平台和框架列表。

Neuropod还提供了一种使用高性能共享内存桥接器在工作进程中运行模型的方法。这使得我们可以在不增加延迟损失的情况下隔离模型。我们将在本文的最后详细讨论这一点。

迭代

一旦我们构建和集成了我们模型的第一个版本,我们就可以迭代并改进我们的解决方案。

作为此过程的一部分,如果我们想尝试武器脚本模型代替我们创建的Tensorflow模型,这是一个替代品。

没有Neuropod,我们需要重做很多以前的步骤。使用Neuropod,任何实现相同问题规范的模型都是可互换的。我们可以重用我们之前创建的指标管道以及我们所做的所有集成工作。

运行模型的所有系统和流程都与框架无关,从而在构建模型时提供了更大的灵活性。Neuropod让用户专注于他们想要解决的问题,而不是他们正在使用的技术。

问题 - 无话用工具

虽然Neuropod通过专注于“问题”(如2D对象检测,但是给定图像,文本的情绪分析),但我们可以在神经内容的顶部构建工具,这是框架 - 不可知和问题无关。这让我们构建可以使用任何模型的一般基础架构。

规范输入建筑管道

Neuropod的有趣问题 - 无话用用例是规范输入建筑管道。在ATG,我们有一个定义的格式/规范,了解如何在张量中代表我们的输入数据。这涵盖了包括LIDAR,雷达和相机图像的传感器数据以及高分辨率映射等其他信息。定义此标准格式使得在训练方面可以轻松管理极大的数据集。这也让我们快速构建新型号,因为我们的许多模型使用该输入数据的子集(例如,在仅在相机和LIDAR上运行的模型)。

通过将此一般输入格式与Neuropod组合,我们可以构建一个优化的输入构建管道,这些管道由我们所有的模型使用,而不管他们在其中实现的框架。

只要每个模型都使用相同的特征集的子集,输入构建器就是问题不可知论。输入构建器中的任何优化都有助于改善我们的所有模型。

图7。Neuropod允许我们构建一个单一的、优化的输入构建管道,它可以与许多模型一起工作,而不是为每个模型或每个框架都构建一个单独的管道。

型号服务

另一个有用的问题 - 不可知的基础设施是模型服务。在Uber ATG,我们的一些模型是相当重量的,因为他们采取大型投入,模型本身很大。对于这些模型中的一些,在脱机模拟中的任务中运行CPU是不可行的。在所有群集机器中包括GPU,从资源效率的角度来看,我们还有一个服务,让用户在远程GPU上运行模型。这与基于GRPC的模型服务非常相似。

没有Neuropod,一个模型服务平台需要擅长远程运行Keras,远程张力流,Pytorch远程,orChscript等,它可能需要实现序列化,反序列化,与C ++ API的交互,以及每个框架的优化。所有应用程序还需要擅长从本地的所有这些框架运行模型。

因为在本地和远程有不同的实现中,整体系统需要关心2 *框架数量案件。

然而,通过使用Neuropod,为服务服务的模型可以很好地远程运行Neuropod,而Neuropod也可以很好地运行来自多个框架的模型。

通过分离关注点,系统需要关注的案例数量可相加(2 +框架#)而不是乘法。随着支持更多框架,这种差异变得更加剧烈。

然而,我们可以使这更强大。如果我们将型号作为Neuropod后端添加,则任何基础架构都可以轻松地远程运行型号。

图8.添加模型作为Neuropod后端允许任何使用Neuropod的应用程序远程运行模型,而无需显着变化。

在引擎盖下,它可能看起来像这样:

图9.应用程序可以使用neuropod来代理模型执行到远程计算机。

此解决方案不是特定的或框架特定的问题,并为使用Neuropod的应用提供更大的灵活性。

upout-process执行

图10. neuropod包括使用低延迟共享存储器桥来支持在孤立的工作过程中运行模型。

由于Uber ATG的输入通常相当大,因此我们延迟敏感,因此本地GRPC不是隔离模型的理想方式。相反,我们可以使用基于优化的共享内存基于流程的执行(OPE)实现,避免复制数据。这让我们在不引入显着的延迟损失的情况下彼此隔离型号。

这种隔离是重要的,因为在过去,我们在同一过程中运行的框架之间看到了冲突,包括微妙的CUDA错误和内存损坏。这些问题仍然很难追踪。

在运行Python模型时,这种隔离对于性能也很有用,因为它允许用户避免在所有模型中具有共享GIL。

在单独的工人流程中运行每个模型还可以实现一些附加功能,该功能包含在下面的“下一步”部分中。

下一步

Neuropod允许优步快速构建和部署新的深度学习模型,但这只是一开始。

我们积极努力的一些东西包括:

      1. 版本选择:此功能使用户能够在导出模型时指定框架的所需版本范围。例如,模型可能需要TensorFlow 1.13.1并且Neuropod将自动运行模型使用开放的使用正确版本的框架。这使用户能够在单个应用程序中使用多个框架和多个版本的每个框架。
      2. 密封操作:此功能使应用程序能够使用Tensor“完成”何时指定。一旦密度密度密度密度密度,Neuropod就可以将数据与正确的目的地异步传输到正确的目的地(例如,在运行推理之前或在工人过程等)。这有助于用户并行化数据传输和计算。
      3. 码头工人流程:这样做允许我们在模型之间提供更多隔离。例如,使用此功能,甚至需要不同的CUDA版本的模型也可以在相同的应用程序中运行。

随着我们通过加强目前的特征和引入新的功能并介绍新的特征,我们继续扩大Neuropod,我们期待着与开源社区合作以改善图书馆。

Neuropod在优步的各种深度学习队伍中非常有用,我们希望它也有利于他人。请试试看让我们知道你的想法!

特别感谢Yevgeni Litvin,他为Neuropod的成功做出了贡献。

评论

没有帖子可以显示