25

徽州骆驼 · 3月10日

英伟达、地平线与华为智驾芯片成功的关键—工具链

高端 MCU、系统级 SoC 和 AI 加速器以及 GPU 都需要工具链。芯片工具链,简言之,是用于设计、开发和测试芯片的一系列软件和硬件工具,涵盖了编程语言、编译器、调试器、性能分析工具、仿真器等多个方面,旨在提高芯片的性能、能效和可靠性。

首先是编程语言与编译器:编程语言是开发者与硬件之间的桥梁,例如 CUDA,而编译器则负责将高级语言程序如 Python 转换为机器码。高效的编程语言和编译器能够显著提升芯片的开发效率和程序性能。

其次是调试器与性能分析工具:调试器帮助开发者定位并修复程序中的错误,而性能分析工具则能实时监测芯片的运行状态,为开发者提供性能优化的建议。

最后是仿真器:仿真器能够在没有实际硬件的情况下,模拟芯片的运行情况,从而加快开发周期。

对 AI 类端侧芯片来说还会添加一个模型量化与转换的环节,这个环节包括经过 Parser(转换为 ONNX 模型)- Optimizer(图优化)- Calibrator(模型量化校准和量化参数选择)- Quantizer(转换为全整形模型) - Compiler(模型编译) 几个步骤,最后转换成一个可部署的 Hybrid model。图优化部分比较复杂,主要是算子的转换、融合和拆分。

工具链决定了芯片的易用程度、性能利用率和准确度,做工具链的员工数量往往比做硬件的员工还多。汽车领域,工具链更为重要,因为汽车领域算力和存储资源有限,因此都默认使用整数 8 位精度,而 AI 端侧领域则是浮点 8 位或 16 位精度,这是一个比较窄的领域。地平线的工具链是天工开物 OpenExplorer,简称 OE。华为 MDC 工具链比较复杂,主要有 Mind Studio、MDS 以及 MMC,英伟达则有 TensorRT,高通则有 Snapdragon Ride SDK。可以说要做大汽车 AI 芯片,工具链至少要占到近 50%的权重。由于 CUDA 深入 AI 骨髓,不得不说,英伟达的工具链还是目前最强的。地平线和华为能够从一众 AI 芯片中脱颖而出,工具链居功甚伟。

image.png
图片来源:知乎@OpenMMLab

一个 AI 模型的上车流程,首先是用各种 AI 训练框架来训练大模型,这些框架包括 Meta 的 PyTorch、谷歌的 TensorFlow、Meta 的 Caffe、由公共云提供商亚马逊云计算服务(AWS)和 Microsoft Azure 联合支持的开源 MXNET,百度的飞桨以及 MathWorks。然后转换为微软提出的 ONXX 中间态,再通过推理引擎,在 AI 芯片上推理运算。算法工程师定义神经网络,然后使用 AI 框架(如 PyTorch、MindSpore、PaddlePaddle 等框架)编写对应的程序;通常使用 Python 语言,AI 框架将 Python 语言自动构建正向计算图,又称图编译器即 GraphIR,根据自动微分机制构建反向计算图;然后将计算图转变成算子的执行序列,再转换为 LLVM IR(Intermediate Representation),然后才在 AI 芯片上运行。

在 ONNX(Open Neural Network Exchange)模型中,除了输入和输出,其他都是算子(Operations)。算子是表示神经网络模型中的不同操作或层的元素。一个 ONNX 模型由一系列算子组成,通过连接这些算子来定义模型的计算流程。常见的算子包括卷积 Convolution、全连接 Fully-connected、池化、激活函数(如 ReLU、Sigmoid)、批归一化(如 Batch Normalization)、Dropout 等。每个算子都有自己的输入和输出张量,并且可能有一些可调参数用于控制其行为。

算子之间的连接关系形成了一个有向图,反映了模型中不同操作的计算顺序。输入张量通过算子进行计算,然后产生输出张量,这些输出张量又可以作为其他算子的输入。最后一个算子的输出张量即为模型的输出。ONNX 提供了一种通用的中间表示形式,使得各种深度学习框架之间可以相互转换模型。通过使用 ONNX,可以将模型从一个框架导出为 ONNX 格式,然后将其导入到另一个框架中进行训练或推理。这种灵活性使得研究人员和开发人员能够更方便地在不同框架之间共享和使用模型。

Image

对每一个独立的算子,用户需要编写算子描述文件,描述算子的整体逻辑、计算步骤以及相关硬件平台信息等。然后用深度学习编译器对算子描述文件进行编译,生成可在特定硬件平台上运行的二进制文件后,将待处理数据作为输入,运行算子即可得到期望输出。将神经网络所有被拆分后的算子都按照上述过程处理后,再按照输入输出关系串联起来即可得到整网运行结果。

某些模型如 LSTM 长短期记忆,没有现成的算子对应到 LSTM,导致 LSTM 这个模型是不能部署的。LSTM 就是由 Conv+Sigmoid+Tanh+Mul 这些基本算子组成的,就把 LSTM 拆分为这 4 个算子。Softmax 也是如此,包含了 6 个算子,还有 transformer 包含比较多的非线性函数,如 ReLU、Sigmoid、Tanh、Exp,transformer 还有独特的 Self-Attention Operators。高级用户还能自创算子,当然这需要工具链配合,否则无法部署。算子讲起来非常复杂,想要详细了解可以看这篇论文《A Mathematical Guide to Operator Learning》。

Image
图片来源:网络

每家都有自己专用的量化工具,量化工具自然与推理引擎乃至硬件芯片是捆绑的,不可能通用,芯原、寒武纪、地平线这些厂家都有自己的量化工具。

计算图优化后是模型量化,根据谷歌量化白皮书中定义,分为 PTQ 和 QAT 两种,而 PTQ 又包括三种量化方式:QAT, PTQ Dynamic, PTQ Static。

1.量化感知训练 (Quant Aware Training, QAT):

  • 量化训练让模型感知量化运算对模型精度带来的影响,通过 finetune 微调训练降低量化误差。这种方法会降低训练速度,但能够获得更高的精度。QAT 是将训练过的模型量化后又再进行重训练。由于定点数值无法用于反向梯度计算,实际操作过程是在某些 op 前插入伪量化节点(fake quantization nodes), 用于在训练时获取流经该 op 的数据的截断值,便于在部署量化模型时对节点进行量化时使用。需要在训练中通过不断优化精度来获取最佳的量化参数。由于它需要对模型进行训练,对操作人员技术要求较高。

2.动态离线量化 (Post Training Quantization Dynamic, PTQ Dynamic):

  • 动态离线量化仅将模型中特定算子的权重从 FP32 类型映射成 INT8/16 类型,bias 和激活函数 在推理过程中动态量化。但对于不同的输入值来说,其缩放因子是动态计算的(“动态”的由来)。动态量化是几种量化方法中性能最差的,但 PTQ 无需对原始模型进行任何训练,只对几个超参数调整就可完成量化过程,过程简单快速,对于汽车行业来说,从业人员大多对大模型训练完全不熟悉,汽车行业又特别注重效率,因此行业大部分都用 PTQ。动态 PTQ 也有叫 1 级 PTQ。

3.静态离线量化 (Post Training Quantization Static, PTQ Static):

  • 静态离线量化使用少量无标签校准数据,采用 KL 散度等方法计算量化比例因子。也有称这种为 2 级 PTQ 或先进 PTQ。

对 AI 芯片用户来说,基本上只考虑用 Python 定义神经网络,其余的环节均由工具链完成,完全透明。

工具链的另一个作用是监控运行资源消耗,评估性能。地平线征程 6 工具链目前提供了两种方式生成性能评估报告:使用 hb_compile 工具编译模型时会自动生成性能评估报告;编译出 hbm 模型后,使用编译器提供的 python API hbm_perf 生成性能评估报告。这里需要注意,调用 compile 接口编译模型时需要开启 debug 后才能生成 layerdetails。

Image

性能主要是帧率、一次推理所需时间、每帧算子计算量。上面就是一个例子,单核情况每秒帧率 34.12Hz,每次推理延迟 29.31 毫秒,运算量 273Gops。一般来说,高速 NOA 帧率至少要到 30Hz 以上,如果你发现帧率很低,要么是模型太大,无法运行在这个芯片上;要么就是模型缺乏优化,优化后或许能流畅运行。

芯片资源使用率和存储动作量
Image
图片来源:地平线

上图是芯片资源使用率和存储动作量,关键计算单元利用率,要是利用率太低,大概率是因为存储瓶颈导致的,计算单元在等待数据搬运到位,也有可能是缺乏优化,算子支持度不够。目前大模型 Transformer 架构,非线性计算多,矩阵向量乘法运算多,存储带宽远比算力重要,大约 80%的时间计算单元都在等待数据搬运,利用率低于 20%,而 CNN 架构,计算单元利用率最高可到 95%。

地平线工具链流程
Image
图片来源:地平线

经过量化训练工具链生成的模型还仅仅是量化模型,比如 TensorFlow 量化训练工具训练后生成的是 PB 格式量化模型,在部署到地平线芯片之前,需要使用 HBDK 芯片编译器工具链对模型进行编译,将 PB 格式模型转换为指令集模型(文件后缀名为.hbm)。

浮点转定点工具链生成物是异构混合模型 bin 文件,与量化训练方案中最后的定点模型 hbm 文件有概念上的差异,HBM 文件内部指令为在地平线 BPU AI 加速器进行计算,而 BIN 文件内部除了可以包含多个 HBM 段以外,还有一些会在 CPU 上执行的模型算子 比如 Abs,Clip,Div,Elu,Exp 等算子,它们会在 CPU 上按照 FP32 方式进行计算,当然 CPU 的 FP32 运算能力非常低,如果有 GPU 的话,自然会交给 GPU 执行,CPU 是可以处理任何形态数据,只是效率高低问题。

地平线天工开物
Image
图片来源:地平线

华为的工具链包括:

  • Mind Studio:支持 AI 算子开发、调试调优,仿真及运行,提供离线模型转化与自定义算子开发功能。
  • MDC Manifest Configurator:基于 AUTOSAR 规范的 ARXML 配置工具,提供模块化配置、模型关系图形化,拖拽式配置、配置项校验等功能。
  • MDC Development Studio:集成开发环境,提供工程管理、代码自动生成、编辑编译、调试运行,远程部署,UT 管理,性能分析、平台软件管理等功能。
  • Measure Calibration Diagnosis Tool:基于 AUTOSAR 的诊断调测工具,提供视频回放、故障诊断、关键指标测量、软硬件拓扑展示,License 管理、版本升级等功能。
  • MDC Application Visualizer:基于 AUTOSAR 的可视化调测工具,提供智能驾驶应用常用数据和用户自定义数据的 2D/3D 可视化显示功能。

Image
图片来源:网络

Mind Studio 主要是负责 AI 模型的生成,之后作为库文件导入到 MDS 中进行整合。这里有点像一个单独编写库文件的软件,编写好的库作为资源导入,可以直接使用。

Image
图片来源:网络

尽管 MDC 很少有外部用户,但开放性仍然挺强的,支持 CPU。

Image
图片来源:网络

MMC 负责 AUTOSAR 的具体实施。

最后我们来说说 CUDA,训练阶段,几乎清一色是英伟达的显卡,想绕开 CUDA 几乎不可能。AI 芯片加速的关键就是并行,并行有几种,按照数据与指令之间的关系,关于并行处理的硬件架构主要有 SISD(单指令流单数据流)、SIMD(单指令流多数据流)、MSID(多指令流单数据流)和 MIMD(多指令流多数据流)四种。还有三种硬件架构,分别是 SIMD、SIMT 和 DSA,其中 DSA 基本可以对应 AI 加速器或 AI 芯片,SIMD 则主要是用在 DSP 和 CPU 领域,SIMT 则是 GPU。MIMD 延伸一步就是 SPMD(Single Program, Multiple Data),多线程 SPMD 指的是在 SPMD 模型中使用多个线程来执行并行计算任务。在多线程 SPMD 中,每个线程(Thread i)都执行相同的程序,但处理不同的数据,通过并发执行来加速计算过程。SPMD 通过循环中的每个迭代独立实现,在程序上,程序员或编译器生成线程来执行每次迭代,使得每个线程在不同的数据上执行相同的计算,SIMT 独立的线程管理硬件来使能硬件处理方式。GPU 的 SIMT 实际上是具体硬件执行 SIMD 指令,采用并行编程模式使用 SPMD 来控制线程的方式。每个线程对不同的数据执行相同的指令代码,同时每个线程都有独立的上下文。执行相同指令时一组线程由硬件动态分为一组 Wrap,硬件 Warp 实际上是由 SIMD 操作形成的,由 SIMT 构成前端并在 SIMD 后端中执行。在英伟达 GPU 中,Warp 是执行相同指令的线程集合,作为 GPU 的硬件 SM 调度单位,Warp 里的线程执行 SIMD,因此每个 Warp 中就能实现单指令多数据。这个编程模式就是 CUDA。

很不幸,推理框架与 CUDA 是深度绑定的,95%的模型都使用 TensorFlow 或 PyTorch 框架,它们与英伟达的 CUDA 是深入骨髓的绑定,例如 PyTorch 的版本必须与 CUDA 版本一一对应。

Image

例如:你需要 1.7.0 的 PyTorch,那么 CUDA 只能 11.0 及以下。否则会频频闪烁的警报「CUDA 版本必须与安装的 PyTorch 匹配!!!」

云端或者说数据中心是离不开 GPU 的,自然也离不开 CUDA,所以不管做什么推理芯片,都必须兼容 CUDA,英伟达 CUDA 的底层自然是不开放的,但是有个中间状态,即 PTX。

DeepSeek 采用了 NVIDIA PTX 指令集(Parallel Thread Execution ISA)来提升执行效能。然而有人声称 PTX 将取代 CUDA,甚至可以用 aPTX 来绕过 CUDA。实际上,PTX 是 NVIDIA GPU 最底层的控制语言,正因为它非常接近硬件层,对于大部分开发者来说学习门槛较高,所以才有了 CUDA 来简化开发过程,PTX 是一个简化版的硬核 CUDA,是 CUDA 汇编语言,可以看作是一个虚拟指令集。PTX 为通用并行编程提供了一个稳定的编程模型和指令集。PTX 旨在在支持 NVIDIA Tesla 架构计算功能的 GPU 上高效运行。高级语言编译器(如 CUDA 和 C/C++)生成 PTX 指令,这些指令经过优化并翻译成目标架构的本机指令。PTX 定义了一个虚拟机和指令集架构,用于通用目的的并行线程执行。这个虚拟机和指令集架构为开发者提供了一个抽象的编程接口,使得他们能够编写高效的并行程序。由于 PTX 指令集与特定的 GPU 硬件架构解耦,跨平台性不强,可能更换一个 GPU 型号就需要重新编写 PTX,这也是很少人用 PTX 的原因之一。PTX 的开发效率特别低,PTX 现在只被用来优化某些关键部分,是以镶嵌在 CUDA 里的形式存在的。

要怎么绕开 CUDA,实际 PyTorch 本来就有一个使用 AMD ROCm 的 PyTorch 版本,它是一个用于 AMD GPU 编程的开源软件堆栈,当然绕开了 CUDA。

CUDA 提供了一套基于 C、C++和 Fortran 的编程接口,使得开发者能够使用熟悉的高级语言编写 GPU 代码。CUDA 扩展了这些语言,引入了特殊的语法和函数库,以便于表达并行计算任务、管理内存、同步线程等操作。CUDA 开发工具链,包括编译器(nvcc)、调试器(Nsight Systems/Nsight Compute)、性能剖析器(Visual Profiler)、数学算子库(cuBLAS、cuFFT、cuDNN 等)以及各种示例代码和教程,帮助开发者便捷地编写、调试、优化 CUDA 应用程序。

在 CUDA 编程中,开发者通常需要编写两部分代码:主机代码(Host Code)和设备代码(Device Code)。主机代码在 CPU 上运行,负责与 GPU 进行交互,包括数据传输和资源管理;而设备代码则在 GPU 上执行,承担主要计算任务。二者相互配合,充分利用 CPU 和 GPU 的协同处理能力,以达到高效并行计算的目的。主机代码运行在 CPU 上,负责控制整个程序的逻辑流程。它管理 CPU 和 GPU 之间的数据传输,分配和释放 GPU 资源,并配置 GPU 内核参数。这部分代码不仅定义了如何组织数据并将其发送到 GPU,还包含了启动设备代码的指令,从而让 GPU 接管计算密集的任务。主机代码起到管理和协调的作用,确保 CPU 与 GPU 之间的高效协作。所以 CPU 的重要性似乎不低于 GPU,这也是几乎所有 AI 芯片厂家都要自己搞 CPU 的原因。

END

作者:周彦武
来源:佐思汽车研究

推荐阅读:

更多汽车电子干货请关注汽车电子与软件专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。
推荐阅读
关注数
5771
内容数
506
汽车电子与软件行业的相关技术报道及解读。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息