使用 Intel® Advisor 的 Flow Graph Analyzer 驱动性能
优化自动驾驶应用程序的性能
现代汽车中部署的高级驾驶辅助系统 (ADAS) 和自动驾驶技术依赖于通过雷达、激光雷达和摄像头等传感器进行环境感知。提供这种感知能力的基础机器学习或深度学习算法计算量很大,并且随着传感器分辨率的提高,其计算需求变得更加严苛。例如,在视频流中检测和分类对象需要检查帧中的所有感兴趣对象,并考虑所有可能的纵横比和尺寸。实时对象检测系统也需要大量计算资源。随着我们朝着近乎完美的系统迈进,这种需求只会增加。
这些系统通常涉及一个候选区域生成过程(即,它们会提议然后分析图像中的潜在感兴趣区域)。幸运的是,候选区域生成是可重复的,并且可以并行化以提高性能。表达出的并行性是可扩展的,因为候选区域生成可以包括整个图像作为一个候选区域,一直细化到帧中的每个像素作为一个单独的候选区域。由于处理候选区域之间没有依赖关系,因此可以根据系统资源可用情况和它们变得可用时(即,以流水线方式)将它们分批处理。
在本文中,我们将使用 **Intel® Advisor** 的 Flow Graph Analyzer (FGA) 来解释如何设计和分析此类应用程序中的并行性。FGA 是 Intel 提供的一个工具,它支持使用 **Intel® Threading Building Blocks (Intel® TBB)** 流图接口的并行应用程序。Intel TBB 是一个广泛使用的 C++ 模板库,它使开发人员能够轻松创建并行应用程序,以利用多核架构和异构系统。流图接口于 2011 年在 Intel TBB 中引入,通过提供依赖图和数据流算法的高效实现,在更高级别上利用并行性。[编者注:“Intel® Threading Building Blocks 迎来十周年”,在 The Parallel Universe 特刊 中,包含了几篇关于 Intel TBB API 的演变和未来方向的有趣文章。]
尽管 Intel TBB 使并行性的表达更加容易,但 ADAS 和自动驾驶应用程序很复杂,可能包含许多相互关联的算法和并行层,这使得它们在设计和调优方面都具有挑战性。FGA,现在作为 Intel Advisor 中的一项技术预览功能提供,使得这项任务更易于管理。我们将通过分析一个使用 Intel TBB 流图 API 实现的 **OpenCV*** 驱动的自动驾驶示例,来讨论如何使用 FGA 的功能。
高级驾驶辅助示例
我们将使用一个 ADAS 的演示框架作为运行示例。我们的示例框架支持两种操作模式:
- 在线模式,其中框架从安装在后视镜上的摄像头传感器接收实时馈送,并捕获汽车前部的传感器数据。
- 离线模式,其中从文件中读取记录的帧以模拟摄像头传感器功能。
传入的压缩摄像头帧被解码并转发到视频输入处理模块,该模块对帧进行后处理,以确保它们已准备好供计算机视觉算法使用。
然后,后处理后的数据会被广播到框架中注册的计算机视觉用例(例如,对象识别、车道偏离警告、前方碰撞警告)。这些用例可以对同一帧独立(并行)执行。其中许多用例内部都使用候选区域生成过程,该过程也允许在用例级别进行并行化。通常,用例是使用已经包含循环级别并行性的 OpenCV* 算法实现的。因此,我们有一个具有多个并行级别的框架。该框架是可扩展的,因为它允许通过插件注册新算法。计算机视觉算法在解压缩的帧上运行,并生成与检测到的对象/车道相关的元数据,以及车道偏离和前方碰撞警告的警报。一个组合模块将所有信息融合在一起,并将其叠加在解压缩的帧之上,然后渲染显示,如图 1 中的彩色高亮所示。顶部的较小的灰度图像突出显示了每个用例的输出。
并行框架的演变
一般来说,视频处理应用程序的关键性能指标是帧完成率,这意味着在完成每帧的固定时间预算内完成了多少帧。如果一帧的处理超过了预算,它将被丢弃。因此,在 24 毫秒的截止日期下,70% 的完成率意味着在给定此截止日期的情况下可以完成 70% 的帧,而 30% 的帧必须丢弃。
在优化此框架的过程中,我们检查了三种实现:
- 原始的串行/原生实现
- 并行/原生实现
- Intel TBB 流图实现
图 2 显示了这三种实现的帧完成率,表明随着优化的应用,更短的截止日期变得可行。
串行/原生实现是在多核处理器上以串行方式执行用例。许多用例是使用 OpenCV 实现的,即使它们可能包含嵌套的循环级并行性,这种方法也会导致系统核心利用率低下。暴露的单个算法的并行性有限,这直接影响了应用程序的可扩展性。
并行/原生实现是基于任务的,允许使用标准线程并发执行算法模块。然而,这会导致过度订阅,因为除了 Intel TBB 在 OpenCV 中创建的线程之外,还会为任务创建线程。为了拥有一个真正灵活且可扩展且避免过度订阅的框架,流图实现将在两个级别都使用 Intel TBB。
图 3 显示了实现为 Intel TBB 数据流图的高级驾驶辅助框架。执行从一个标准的流图函数节点(Init)开始,该节点封装了应用于每一帧的初始设置例程。随后,与外部活动(实际的每一帧解码)的交互通过异步节点(Decode)来表达。视频输入处理(VIP)节点将输入图像广播到每个用例(即,对象识别、车道偏离警告、前方碰撞警告)和一个多功能节点(Copy)。此节点执行两个操作:
- 存储未修改的输入图像,以便稍后与用例的输出合并。
- 生成每个用例的令牌。
下一个节点生成此令牌和输出缓冲区的元组,然后由多功能 Combine 节点消耗。图 1 中的高亮显示是不同用例的输出,在图 3 的中心由流图复合节点表示。在我们的示例中,对象识别(OR)、车道偏离警告(LDW)和前方碰撞警告(FCW)是使用 OpenCV 实现的。图中的 Display 节点显示输出图像。[编者注:完整的图节点属性超出了本文的范围。有关 API 详细信息,请参阅 **Intel® Threading Building Blocks Flow Graph** 文档。]
我们的数据流设计的最大优势在于可以表达更多的并行性,从而提高性能。此外,我们的实现不需要修改现有的用例,因为它们可以表示为单个分组的节点函数,这些函数仅调用其 process_frame() 函数。这样,流图实现就向后兼容所有现有的框架插件。
接下来,我们将使用 Intel FGA 工具中的功能来分析此流图的性能,以更深入地了解其行为,并发现尽管它目前优于之前的实现,但仍有改进的空间。
Intel FGA 概述
图 4 显示了 Intel FGA 可视化图及其相关的性能跟踪数据。该工具有五个查看区域:
- 菜单/工具栏区域:提供用于设计、操作、可视化和分析图的操作。
- 索引区域,分为三个类别。设计器模式显示用于构建新图的可用节点类型。分层视图将图拓扑表示为分层树。分析模式(图 4)将图性能表示为树状图中的方块。(在本文中,我们重点关注分析模式。)
- 画布区域:这是主要的图查看区域,可以在其中构建或显示图。此区域支持常用的编辑操作,以方便设计新图。
- 报告区域:这里包含所有基本报告,如图和节点属性,以及由分析生成的报告,如语义规则检查和关键路径算法。
- 图表区域:此区域显示具有相关跟踪数据的图的性能统计信息和执行跟踪时间线图。这些数据由跟踪收集器自动捕获,跟踪收集器可以从 GUI 或命令行实用程序调用。
在 Intel FGA 中,可以使用查看区域和模式来创建两个主要的工作流:设计和分析。
- 设计工作流 使用拖放模式来交互式地构建 Intel TBB 流图。
- 分析工作流 从 Intel 流图应用程序捕获性能数据。
该工具能够可视化和交互性能数据。我们使用此分析工作流来检查为我们的 ADAS 示例收集的性能数据。
ADAS 示例的性能分析
为了优化我们示例的性能,我们首先需要识别瓶颈。Intel FGA 允许开发人员捕获运行 Intel TBB 流图应用程序的图拓扑和任务执行跟踪。图 5 显示了允许用户指定要跟踪的应用程序的跟踪收集对话框窗口。数据收集完成后,将生成两个文件:
- GraphML 文件,描述刚刚执行的图的拓扑。
- TraceML 文件,包含来自图的任务执行跟踪。
找到应用程序中最重要部分
分析应用程序性能的常见第一步是确定应用程序中大部分时间花在哪里。Intel FGA 有两个功能可以帮助完成此步骤。
首先,树状图视图显示总 CPU 时间,表示为一个大矩形,该矩形被细分为表示图中的节点的较小矩形。节点的大小与其消耗的总 CPU 时间成正比。颜色反映了节点执行时的并发性(红色表示低并发)。图 6 显示了我们 ADAS 示例的树状图视图。由此图,我们可以得出结论,用例需要不同的计算时间,并且 OR 主导了框架的 CPU 时间。用例执行时间上的差异支持我们允许每个用例独立地将其结果发送到叠加节点的决定。任何类型的屏障都可能导致负载不平衡。
Intel FGA 还可以计算应用程序的关键路径,并将其投影到流图的拓扑上。第二种视图显示在图 7 中。我们 ADAS 示例的关键路径突出了要考虑优化的一组关键节点。通过结合树状图和关键路径视图,我们现在知道 OR 不仅是单个节点中最耗时的,它也位于应用程序中最重要的路径上。因此,图的性能受限于 OR 的性能,因此它应该是我们优化的最高优先级。有时,可能需要确定哪些算法是卸载到加速器的候选对象,以满足严格的性能规范。
分析瓶颈的性能特征
既然我们已经确定 OR 是最重要的算法,我们可以通过查看 Intel FGA 中的时间线视图进一步检查其性能。按线程分组的逐时任务数据提供了收集到的跟踪的原始视图。在此图中,我们可以看到每个线程执行的任务及其持续时间。图 8 显示了单个帧处理数据的放大视图以及描述颜色的图例。任务的颜色基于任务类型。图任务的颜色基于任务持续时间,较浅的颜色用于突出显示相对于任务调度成本而言较小的任务。蓝色显示嵌套并行任务和异步任务。
图任务的颜色使用从 1µs 到 1ms 的渐变进行量化,以便开发人员可以识别那些执行时间较短且可能影响性能扩展性的任务(因此是节点)。在时间线中选择一个任务会在画布上的图节点上突出显示。此图使我们能够专注于那些太小而不适合在线程上生成的任务,并在我们看到低并发时调试图的性能。
从图 8 中,我们看到尽管线程有时在 OR 期间忙碌,但仍有改进的空间。蓝色任务表示存在使用 Intel TBB 的嵌套并行性,但黑色区域表示核心空闲的时间。由于 OR 是我们示例中的主要计算,我们可能希望查看哪些任务对应于它。图 8 中显示了所有任务。如果我们只想关注关键路径上的任务,我们可以使用选择性高亮显示来显示关键路径上的任务。
图 9 显示了仅突出显示与关键路径相关的任务时的时间线视图。请注意,显示嵌套任务目前是 Intel FGA 的一项实验性功能,需要手动插桩。从图中可以看出,时间线中的大多数任务都可以映射到 OR 节点。核心空闲时间(由黑色区域表示)可以通过缩短计算 OR 所需的时间来消除空闲时间,或者通过调度可以并行执行并保持空闲核心繁忙的其他算法来解决。
图 9. 显示在执行跟踪上的关键路径
让我们检查图 9 中显示的帧的 OR 节点执行跟踪。放大到该帧会显示在此帧中由 OR 节点执行的四个嵌套并行算法(图 10)。为并行算法提供了额外的信息,以帮助我们确定这些算法是否高效执行。Statistics(统计信息)视图具有每个节点的按表格显示的数据,该表格显示了每个节点在图级别的性能统计信息。在对 OR 节点进行分析时,我们更关心每个节点中执行的算法。图 10 显示了在我们选择的帧中执行的四个并行算法的每个算法数据。我们可以看到 OR::tbb149
和 OR::tbb213
的效率相当高,需要的性能调优较少。另一方面,OR::tbb261
和 OR::tbb284
的效率较低,可能是因为这些算法执行的任务数量很少。这可能导致负载不平衡,从而降低并行效率和可扩展性。
图 10. 显示 OR::tbb149、OR::tbb213、OR::tbb261 和 OR::tbb284 的算法统计信息的图统计信息表
由于 Intel TBB 使用工作窃取来调度任务,我们可能还希望查看哪些线程执行了特定的节点。通过切换到时间线的每个节点视图(图 11),在 Intel FGA 中很容易看到这一点。现在我们可以看到 OR 节点经常由同一个线程(绿色)执行,但在某些时候其他线程也会执行它。
除了时间线、算法统计信息和图拓扑视图之外,我们还可以以表格形式查看每个节点的数据(图 12)。这允许开发人员对数据进行排序,并确定最佳优化区域。选择一行将突出显示图视图中的相应节点。
结论
Intel FGA 为开发人员提供了一套全面的工具来检查、调试和分析 Intel TBB 流图。通过将其应用于我们的 ADAS 示例应用程序,我们能够快速识别最重要的优化节点。我们还能够确定,尽管 OR 用例中有一些嵌套并行性的使用,但仍有空闲核心可供我们寻找额外的并行性。
用于性能测试的软件和工作负载可能已针对仅在 Intel 微处理器上优化性能进行了优化。性能测试(如 SYSmark 和 MobileMark)是使用特定的计算机系统、组件、软件、操作和功能测量的。这些因素的任何更改都可能导致结果有所不同。您应该参考其他信息和性能测试,以帮助您全面评估您打算购买的产品,包括该产品与其他产品结合使用时的性能。有关更完整的信息,请访问 http://www.intel.com/performance。
Intel 的编译器可能不会针对非 Intel 微处理器针对非 Intel 微处理器独有的优化程度相同。这些优化包括 SSE2、SSE3 和 SSSE3 指令集以及其他优化。Intel 不保证在非 Intel 制造的微处理器上任何优化的可用性、功能或有效性。本产品中的特定于微处理器的优化旨在与 Intel 微处理器一起使用。某些非 Intel 微体系结构特定的优化保留给 Intel 微处理器。有关此通知涵盖的特定指令集,请参阅适用的产品用户和参考指南。