门户网站网站开发,微指数查询,营销资源网,电子购物网站开发简介#xff1a;AI 生态系统是怎样的#xff1f;其中又有哪些关键技术#xff1f;
AI 计算力的指数增长意味着#xff0c;为了解决越来越复杂的用例#xff0c;即使是 1000 倍的计算性能增长也很容易被消耗。因此#xff0c;需要通过软件生态系统的助力#xff0c;才能…简介AI 生态系统是怎样的其中又有哪些关键技术
AI 计算力的指数增长意味着为了解决越来越复杂的用例即使是 1000 倍的计算性能增长也很容易被消耗。因此需要通过软件生态系统的助力才能达到更好的性能。我们相信构建 AI 软件生态系统是将人工智能和数据科学项目推向生产的关键。本文整理自龙蜥大讲堂技术直播第四期由龙蜥社区AI SIG核心成员、英特尔 AI 软件开发⼯程师黄文欢分享——用技术和实例讲解英特尔 x86 平台 AI 能力演进的关键。 以下是本期龙蜥大讲堂技术直播回顾文
人工智能的发展为社会各个领域带来了无限可能但这些应用都需要很强的计算性能和优化来提供准确、及时的结果。人工智能模型复杂性的增长速度是飞速的大约三年前像 ELMo 这样的自然语言模型只有 9400 万个参数而今年最大的模型达到了超过 1 万亿个参数。
一、英特尔 x86 平台 AI 能力演进
自 Skylake 以来英特尔通过从 AVX256 升级到 AVX512将 AVX 的能力提高了一倍这极大地提高了深度学习训练和推理能力。一年后在 Cascade Lake 中引入 DL Boost VNNI大大提高 INT8 乘加吞吐量。自 Cooper Lake 之后英特尔将BFloat16(BF16) 添加到 DL Boost 指令集中以进一步提高深度学习训练和推理性能。硬件一直在向前发展AMX 自 Sapphire Rapids 开始推出将会进一步提高 VNNI 和 BF16 从 1 维-向量到 2 维-矩阵的能力。英特尔可扩展处理器通过英特尔
Deep Learning Boost (Intel®DL Boost) 将嵌入式 AI 性能提升到一个新的水平。英特尔的 Deep Learning Boost ( DL Boost ) 是 x86-64 上指令集架构功能的名称旨在提高深度学习任务例如训练和推理的性能。DL Boost 包含两组关键技术
AVX-512 VNNI主要用于卷积神经网络的快速乘法累加。AVX-512 BF16用于更快计算的低精度 BFloat16 浮点数。图1. 英特尔x86平台AI能力演进
Intel® DL Boost – VNNI
英特尔深度学习加速包括 AVX512 VNNIVNNI 代表向量神经网络指令是对标准英特尔指令集 AVX512 的扩展。AVX512 VNNI 旨在加速基于卷积神经网络的算法。AVX512 通过引入 4 个新指令加快内部卷积神经网络环路。AVX512 VNNI 扩展背后的主要动机是观察到许多紧密的循环需要两个 16 位值或两个 8 位值的重复乘法并将结果累加到 32 位累加器。 图2. 利用基础AVX 512 vs. 利用AVX512 VNNI 做向量乘加
深度学习的核心计算可以简化为乘加运算。在 VNNI 之前我们需要做图 1 中这样的向量乘加使用基础 AVX-512对于 16 位这可以使用两条指令实现 VPMADDWD用于将两个 16 位对相乘并将它们加在一起然后将 VPADDD 添加累加值。利用基础 AVX512 需要 3 条指令而 VNNI 只需要 1 个周期就可以完成。通过将三条指令融合为一条可以最大化利用计算资源提升 cache 利用率及避免潜在的带宽瓶颈。因此在这个意义上VNNI 通过与非 VNNI 比较将为 INT8 带来 3x 峰值计算的提升。此外由于在一个 AVX512 寄存器中与 FP32 相比可以容纳 4 倍 INT8 数据如果与 FP32 相比又可以带来 4x 峰值计算的提升。
Intel® DL Boost – BFloat16
BFloat16(BF16) 主要思想是提供 16 位浮点格式其动态范围与标准 IEEE-FP32 相同但精度较 FP32 变低。相当于指数区和 FP32 保持了相同的 8 位并将 FP32 分数字段的小数区缩减到到了 7 位。大多数情况下用户在进行神经网络计算时BF16 格式与 FP32 一样准确但是以一半的位数完成任务。因此与 32 位相比采用 BF16 吞吐量可以翻倍内存需求可以减半。此外fp32 到 bf16 的转化相对于 fp32 到 fp16 的转化更加简单。 图3. BFloat16数据类型介绍
英特尔® 深度学习加速技术包括以下 BFloat16 指令 二、英特尔AI 软件开发及部署生态系统
随着 AI 应用在视觉、语音、推荐系统等方面不断增长和多样化英特尔的目标是提供一套优越的 AI 开发和部署生态系统使每个开发人员、数据科学家、研究人员和数据工程师尽可能无缝使用以加快他们从边缘到云端的 AI 之旅。对于所有硬件和软件优化以及模型量化算法我们需要了解它们以更好地利用为了使每个用户都可以便捷使用这些优化英特尔提供了一套自顶向下的全栈 AI 软件系统。对于不同需求的工程师都可以在英特尔 AI 软件生态系统中找到适合他们的应用。对于想要开发自己的高性能应用程序或库的深度开发人员可以直接调用相关的指令。对于想要摆脱框架开销的框架开发人员或 AI工程师你可以直接使用 OneDNN。对于那些已经拥有 TensorFlow/PyTorch 等 AI 框架训练的模型的人来说Intel 已经将大部分补丁上流到开源中直接使用它们并享受性能或者进一步使用英特尔对于这些框架的扩展优化。对于那些想要追求更多特定于推理的优化的人可以使用 INC 工具库。
2.1 深度神经网络库 OneDNN
oneDNN 是一个开源的跨平台高性能库包含用于深度学习应用程序的基本构建模块。基于英特尔平台oneDNN 对深度神经网络进行 op 级以及指令集级的优化。
帮助开发人员创建高性能深度学习框架相同的 API 为英特尔 cpu 和 gpu使用最好的技术来完成这项工作支持 Linux、Windows 和 macOS
该底层库围绕四个概念建立
1.原语(Primitive)是一个封装了特定计算过程的函数对象特定计算过程如前向卷积LSTM 反向计算等。可以通过原语的属性来控制原语表达更复杂的融合操作例如前向卷积和 ReLU 的融合。这里需要注意的是创建原语是重量级操作最好的方式是一次创建、重复使用。或者可以通过缓存具有相同参数的原语来减少原语创建成本。
2.引擎(Engine)是计算设备的抽象包括 CPU特定 GPU 卡等。创建的大多数原语是在一个特定引擎上执行计算引擎类似于异构计算的 host 和 device 概念的统一是可执行计算的设备的抽象。
3.流(Stream)是绑定到特定引擎的执行上下文的封装。
4.内存对象 (memory) 封装了分配给特定引擎的内存句柄、 tensor 的维度、数据类型、数据排布等信息。内存对象在执行期间被传递给原语进行处理。可以通过内存描述符 (memory::desc) 创建内存对象。 图4. OneDNN 关系图
优势
支持关键数据类型float32、float16、bfloat16 和 int8实现了丰富的操作convolution, matrix multiplication, pooling, batch normalization, activation functions, recurrent neural network (RNN) cells, and long short-term memory (LSTM) cells支持自动检测硬件指令提高神经网络在指定硬件特别是英特尔 CPU 和 GPU 上的执行速度。
2.2 优化深度学习框架TensorFlow, PyTorch
深度学习框架通过高级编程接口为数据科学家、AI开发人员和研究人员提供模块以构建、训练、验证和部署模型。英特尔通过 oneDNN 库进行的软件优化为几个流行的深度学习框架带来了数量级的性能提升而且大多数优化已经上传到默认框架分发版中。但是对于 TensorFlow 和 PyTorch我们还维护单独的 Intel 扩展作为尚未上传的优化的缓冲区。
2.2.1 Intel® Optimization for TensorFlow*
英特尔对于 TensorFlow 的优化主要包括以下三个方面
1在算子优化部分,将默认的(Eigen)内核替换为(使用oneDNN)高度优化的内核OneDNN优化了一系列TensorFlow操作。OneDNN 库是开源的在构建 TensorFlow时自动下载。
2在图优化方面图优化主要是希望在不影响模型的数值特性的基础上通过图变换达到简化计算、资源开销提升性能所以是性能优化时的首选方法之一。Intel® Optimization for TensorFlow*中所做的图优化包括算子融合及布局传播。
算子融合
算子融合是一个常见的性能优化方法在融合之前每个算子计算前后都需要把数据从内存读到缓存再从缓存写回到内存。而融合之后可以避免算子之间内存读写从而提高性能。 图5. 算子融合
所以在做算子融合的时候本质上便是把多个 Tensor 整合到一个 Node 下。虽然只是简单的算子融合但是在计算过程中可以提高速度。
布局传播
在布局传播方面数据布局是会很大程度影响性能的因此我们需要做到
顺序访问尽可能在最内层的循环中进行迭代提高向量利用率尽可能的重用数据例如卷积层中的权重
通常对于 CPU 上的某些张量操作原生 TensorFlow 数据格式并不是最有效的数据布局。对于 TensorFlow 中的 tensor, 所有 OneDNN 中的算子使用都是高度优化的数据布局。在这种情况下我们插入一个从 TensorFlow 原生格式到内部格式的数据布局转换操作在 CPU 上执行操作并将操作输出转换回 TensorFlow 原生格式。需要注意的是我们应该避免冗余的转化开销。而这些转换会带来性能开销因此带来的挑战在于如何避免不必要的转换。所以我们应该采用布局传播方式布局传播就是用于识别出相邻的互逆 reorder并消除它们从而减少了无效的操作。也就是最右边的这张图中的结构。 图6. 布局传播
在布局传播方面Intel® Optimization for TensorFlow*中所做的优化为
查找子图这个子图中所有算子都有OneDNN支持在这样的子图的边界上引入数据布局转换
3在系统级优化方面包括负载均衡与内存分配两部分。对于负载均衡我们知道不正确的设定线程模型参数会引发性能问题。因此可以参阅TensorFLow里的相关说明文档正确的为模型设置参数。对于内存分配TensorFlow中的神经网络算子会分配大量的内存。但 TensoeFlow 中默认的 CPU 分配器不能很好地处理这种情况: 频繁alloc/dealloc 会带来频繁的mmap/munmap。在Intel® Optimization for TensorFlow*中实现了 Pool allocator 来解决这个问题。
2.2.2 Intel®Optimization for PyTorch*
我们已经将大部分优化上传到 社区版本的 PyTorch 中同时还保留了一个单独的英特尔 PyTorch 扩展包Intel® Extension for PyTorch* IPEX作为目前尚未upstream的这些优化的一个缓冲区。 图7. Intel® Extension for PyTorch*
IPEX 在英特尔硬件上对比社区版本的 pytorch 具有额外的性能提升。大多数优化最终将包含在社区 PyTorch 版本中扩展包的目的是在英特尔硬件上为 PyTorch 提供最新的特性和优化包括 AVX512 VNNI) 和 Intel®AMX。IPEX可以作为Python程序中的模块进行加载也可以作为 C 程序的 C 库链接。用户可以通过导入 intel_extension_for_pytorch 在脚本中动态启用这些优化。优化扩展包 IPEX 中所包含的优化有
算子优化为提高性能IPEX优化了算子并实现了多个定制的算子。(通过ATen注册机制一些ATen操作符会被在Intel® Extension for PyTorch*的优化版本所取代。)还针对几种流行的拓扑实现了一些定制算子。如Mask R-CNN中的 ROIAlign and NMS.图优化IPEX支持常用的算子融合如Conv2DReLU, LinearReLU等。算子融合带来的好处以透明的方式传递给用户。IPEX支持FP32 和 BF16 融合模式以及INT8融合模式Runtime 优化 为用户提供了多个 PyTorch 前端 API以便对线程运行时进行更细粒度的控制。它提供通过 Python 前端模块 MultiStreamModule 进行多流推理从 Python 和 C 前端生成异步任务从 Python 和 C 前端为 OpenMP 线程配置核心绑定
2.3 优化工具 INC
INC全称为Intel® Neural Compressor是一个运行在Intel CPU和GPU上的开源Python 库它为流行的网络压缩技术 (如量化、剪枝、知识蒸馏) 提供跨多个深度学习框架的统一接口。 图8. INC基础架构图
可以看到这个工具支持自动的精度驱动的调优策略帮助用户快速找到最佳量化模型。 这些调优策略包括贝叶斯/MSE/TPE…对于量化部分模型量化主要是通过降低模型中tensor和weights精度的手段从而减少计算需求和数据存储与传输需求来达到加速的目的。主要方法分两派一是训练后量化(Post-training Quantization)二是量化感知训练(Quantization-Aware Training)。INC工具支持
训练后静态量化Post-training Static Quatization)训练后动态量化Post training dynamic Quatization)量化感知训练Quantization-aware training)
对于剪枝部分深度学习网络模型从卷积层到全连接层存在着大量冗余的参数大量神经元激活值趋近于 0将这些神经元去除后可以表现出同样的模型表达能力这种情况被称为过参数化而对应的技术则被称为模型剪枝。INC 中采用多种剪枝算法如非结构化剪枝(Magnitude-based 基于幅度剪枝) 结构化剪枝(Gradient sensitivity梯度敏感剪枝)生成具有预定义稀疏性目标的剪枝模型。
同时 INC 也支持知识蒸馏。模型蒸馏采用的是迁移学习的方法通过采用预先训练好的复杂模型(Teacher Model)的输出作为监督信号去训练另外一个简单的网络(Student Model)最后把 Student Model 用于推理。
以在 TensorFlow 上的使用举例用户模型可以是 saved model、 ckpt、 pb 各种形式通过 INC 工具运行后得到一个优化后的模型依然为之前的用户模型格式可以在 Tensorflow 上使用相较于原始模型来说获得更好的性能效果。 图9. INC性能表现
这是在 150 个业内常用的模型使用 INC 工作后的评估结果。这些模型涉及各个领域包括图像分类中常用的ResNet、GoogLeNet、Inception目标检测中常用的Mobilenet、Yolo、Faster RCNN推荐中常用的 Widedeep、DLRM自然语言处理中常用的 bert 等。这张图展现的是 int8 相对于fp32 的性能结果比较。横轴为相应的精度改变纵轴为 Int8 与 fp32 相比在实时 latency 的提升。可以看到几何平均提升达到 2.3 倍。
三、性能优化方法及案例分享
3.1 性能优化方法
在推理的性能优化方面, 工作可归成四类算子优化、图优化、模型压缩和部署优化。
算子优化 算子优化中微架构优化的主要焦点是如何充分利用好微架构的内置加速器的能力去最大化算子的性能。OneDNN底层库就可以帮大家很好的做这部分的优化。
图优化主要通过子图变换和算子融合等方式来达到减少计算量或者其他系统开销如访存开销从而达到性能优化的目的。图优化主要是希望在不影响模型的数值特性的基础上通过图变换达到简化计算、资源开销提升性能所以是性能优化时的首选方法之一。英特尔对于深度学习框架tensroflow, pytorch的优化包含这些图优化。
模型压缩如果还需要额外的性能增益这时候需要考虑模型压缩方案。模型压缩(Compression)主要手段有模型量化、剪枝和模型蒸馏。工程师们也可以通过刚刚介绍的INC压缩工具来便捷的使用到这些压缩方案。
部署优化主要通过调整模型在部署时的资源分配和调度的参数来进一步优化性能。
3.2 案例分享Bfloat16 优化在第三代英特尔至强可扩展处理器上提升阿里云 BERT 模型性能
BERT 模型是一个自然语言处理中的一个常用模型。阿里巴巴阿里云团队与 Intel 工程师密切合作进行 BERT 推理性能优化。接下去介绍我们是怎样一步步开展这些优化的。首先我们在原始数据类型即fp32的情况下我们首先使用“模型转换”将多层多操作的复杂 BERT 模型替换为单个 BERT 操作。为了在 TensorFlow上实现高效的 BERT op我们需要创建一个优化的Kernel从而产生一个新的自定义 BERT 算子。这是一个具有 算子 融合和优化的实现。
在 TensorFlow 中“前端”负责图描述“后端”负责算子的执行。因此我们可以将模型从原始 BERT 模型转换为前端带有 BERT op 的新模型并将新的 BERT 内核实现注册到后端。因此我们不需要重新安装 TensorFlow 框架。我们只需要加载实现 BERT 代码的动态库即可并通过 oneAPI 深度神经网络库 (oneDNN)等高性能工具来提升性能。 图10. BERT 模型优化方案
对于优化实现我们分析BERT图进行层融合和张量融合。这张图显示了 12 层 BERT 中的一层细节。在这个案例中又可以进行横向融合和纵向融合。关于横向融合我们可以看到三个张量即查询 query、键 key 和值 value都需要进行 MatMul 和 BiasAdd 操作。我们可以把这些操作融合为一个操作即 QKV MatMul 和 BiasAdd。关于纵向融合可以参照下图。 图11. 新BERT模型实现
接下去我们分析优化的 FP32 BERT 模型时我们注意到推理过程中超过 80% 的运行时间花费在 MatMul 操作中。如何优化 MatMul 运算以减少延迟已成为最紧迫的挑战之一。众所周知减少内存访问、优化缓存、提高并行度可以优化程序性能。随着第 3 代英特尔至强可扩展处理器的引入使用最开始介绍的英特尔 DL Boost 的 bfloat16 指令与 FP32 的点积相比在理论上能将 BF16 的点积加速 2 倍。
英特尔® 深度学习加速技术包括以下 BFloat16 指令 为了减少内存访问我们将 FP32 权重转换为 BF16 权重像下图中右边的图结构所示。我们将 FP32 权重转换为 BF16 权重并将 BF16 权重缓存在 BF16 MatMul op 中以供重用并在每次执行时并行的将 FP32 输入转换为 BF16 输入。 图12. BFloat16 优化方案
在这样的转化下我们可以使用 bfloat16 的点积计算 MatMul op可以看到输入为 BF16 类型 输出为 fp32 类型。这些实现是利用了 oneDNN的 支持。因此我们只需要创建一个新的 BF16 MatMul op 来替换优化的 FP32 解决方案BaselineMatMul op然后我们就可以实现BF16与 FP32 优化相比带来的性能提升。
对于 BF16 优化方案通过简单的运算替换来提高性能可以保持尽可能高的精度。对于 BiasAdd 操作我们仍然保持 FP32 操作以减少精度损失。
最后是一个优化后方案的性能和进度评估结果为了比较优化后的 FP32 Bert 和优化后的 BF16 Bert 的性能差异我们将batch size 设为1token size 设为128这也符合实际的线上业务。输入是 MRPC 数据集。以延时为 21.70 毫秒的 FP32 解决方案为基准可以看到优化的 BF16 解决方案与基线相比延迟为 11.83 毫秒端到端的性能提升达到了 1.83 倍并且没有 Accuracy 的损失。 敲重点啦
本次直播视频回放已上线至龙蜥社区官网首页-社区-视频直播 PPT 获取方式关注龙蜥社区公众号后台回复【龙蜥课件】或【龙蜥视频回放】即可。
原文链接
本文为阿里云原创内容未经允许不得转载。