这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 企业专区 » OpenVINO生态社区 » 开发者实战|速度起飞!AI大模型基于OpenVINO™优化初次推理启动速度的小妙

共1条 1/1 1 跳转至

开发者实战|速度起飞!AI大模型基于OpenVINO™优化初次推理启动速度的小妙招

高工
2024-03-05 15:30:39     打赏

01 本文目的

一般来说,开发者在启动基于  OpenVINO™ 的 AI  应用进行深度学习模型推理的时候,特别是在推理大模型的时候,往往会发现从程序启动到完成初次推理所消耗的时间(称之为初次推理的响应时间)会比常规一次推理要长一些,这是因为在启动第一次推理之前,OpenVINO™  Runtime 的工作流程是需要先读取模型文件,之后编译模型文件,完成后才开始模型推理。这就导致了用户启动 AI  大模型应用后,拿到首次推理结果的时间相对比较长,用户体验不佳,AI  应用初次推理过长的响应时间也随之成为了大模型应用需要解决的痛点之一。本文将会介绍 OpenVINO™  提供缩短初次推理响应时间的优化选项,同时对不同的推理硬件进行对比,目的是让开发者使用 OpenVINO™ 部署 AI  推理时,能够更熟悉针对初次模型推理响应的优化方法,并将这些优化策略合理地部署在自己 AI 大模型应用中。

02 优化推理响应的策略

我们先梳理一下基于 OpenVINO™ 工具套件构建应用程序的整体思路,总体的流程是这样的:

图片

图 1:OpenVINO™ 应用推理准备阶段流程图

1 首先需要创建一个 Core 对象,然后需要管理当前系统下的可用设备

2 使用 read_model()  读取 Intermediate Representation(IR )到 ov::Model 的对象中

3 确定模型的输入和输出格式,模型运行的执行精度、数据通道的排列顺序、图像的大小或颜色格式,将需要的配置文件加载传递到设备中

4 在特定的硬件设备下编译网络并加载模型到设备中:使用 ov::Core::compile_model() 的方式完成操作

5 准备 input tensor 作为模型输入

6 执行推理,最终获得结果

通过以上的流程图,我们可以很清晰的知道在  AI  程序在第一次执行推理前,还有这么多的准备步骤需要完成 。如果我们要去做模型初次推理响应的优化,从以往的经验可以得知:由于读取模型和编译网络模型这两步会产生很大的计算量,因此会消耗比较多的时间,所以我们也会重点优化这两个步骤,来减少推理响应耗费的时间。其次,对于相同的模型来说,基于  OpenVINO™ 的 AI 推理在 CPU 上的响应速度往往会比 GPU  上快得多,不同的推理设备也会对模型初次推理响应产生影响。接下来,我们将介绍一些比较常用的优化策略。

优化策略一:使用模型缓存减少模型编译时间

在模型推理之前,程序会执行读取模型和编译模型的操作,这些操作实际上是在对推理硬件设备进行特定优化并且完成深度神经网络(DNN)在当前设备的编译操作,编译完成之后方可运行推理。为了减少应用程序启动时的延迟,不论在  CPU 还是在 GPU 中,在任何推理设置情况下,你都可以使用“Model  Cache”的方式来优化第一次推理的响应时间,以减少程序启动时的延迟。

图片

图 2:Cache Model 优化流程示意图

如上图所示,应用“Cache  Model”之后,在编译模型阶段,可以大幅降低这一阶段所消耗的时间。模型缓存是 OpenVINO™  工具套件自带的一个功能,它在完成编译模型网络之后,可以自动导出已编译好的模型,将这个缓存模型放置在特定的文件目录下,程序会在指定的文件目录下生成一个大小和模型  bin 文件差不多的 Blob 文件作为缓存文件,下一次启动程序是可以直接读取 Blob  缓存模型进行模型复用,这个操作也可以在应用启动阶段显著减少模型编译时间,加快推理程序启动的响应速度,这是最推荐大家去使用的策略因为不受它可以不受任何其他条件所影响。

在某些特定情况下,若应用程序不需要每次都调整模型的输入和输出,甚至可以在代码中省略 read_model() 这一步,直接使用 compile_model() 编译模型,这样能达到一个最快的推理响应速度。

使用”Cache Model”的方式如下,只需要指定一个保存缓存模型的文件夹路径,即可使用这个功能:

compiled_model = core.compile_model(model=model,config={ "CACHE_DIR":"PATH to folder to save cache model"})

优化策略二:在 PERFORMANCE_HINT中选择 Latency 模式

若在应用中设定多推理线程的话,势必会同时拉起非常多的推理线程,这样会导致推理设备的初始负载非常大,虽然可以得到比较大的图像推理吞吐量,但是初次推理延迟也会同样变得非常大。所以如果对于推理响应比较敏感的开发者,需要在推理程序中只拉起一个推理线程,设置单一推理流,一个   batch,就能达到推理延迟最小化,初次推理响应最快化。当然,更多的时候开发者也需要权衡线程数和推理延迟之间的关系,线程数越大,随之推理延迟就越大,所以在有些实际开发过程中需要牺牲一点响应时间来换取更大的吞吐量。

如果说追求最快的推理响应,可以设置 PERFORMANCE_HINT 的参数为“latency”模式,这样会自动选择相应的推理参数,以达到最快推理响应速度,Python 语言的使用方法如下:

compiled_model = core.compile_model(model=model,{"PERFORMANCE_HINT": "Lantency"}

优化策略三:优先选择 CPU 硬件进行推理

在使用 OpenVINO™ 进行 AI 推理时,同样的模型,不同的推理硬件会带来不一样的推理响应结果。英特尔 GPU 编译网络消耗的时间会比 CPU 大得多,所以在 AI 推理应用的第一步——设备管理阶段,开发者需要在设备的选择与推理的启动时间去做衡量。

若 AI 应用的需求选择单独 CPU 或者 GPU 去做推理,在推理响应要求高的场景下,可以优先选择使 CPU 进行 AI 推理,因为 CPU 的推理响应速度更快。

优化策略四:GPU 推理时应用 AUTO Plugin

在上一个优化策略中,我们知道  CPU 在推理响应上是会比 GPU 快的,那么当我们在使用 GPU 推理时,能不能将 CPU 推理加到 GPU  开始推理之前,以获得最快的推理响应速度呢?答案是可以的,并且 OpenVINO™ 将这个功能做成了一个单独的 Plugin。当你选择使用  AUTO Plugin 指定 CPU 和 GPU 并进行模型推理时,AUTO Plugin 将会默认同时在 CPU 和 GPU  上编译模型网络并开始推理,以填补 GPU 编译网络的这段时间空白。

图片

图 3:AUTO Pugin 工作流程分解示意图

由上图可以很清晰地看到  CPU 的推理工作在 GPU 完成模型编译后停止,AUTO Plugin 充分利用了这段空闲时间并且也不会产生过多的内存占用。特别是针对  GPU 的推理时候,虽然没有直接缩短编译网络的时间,但是通过 CPU 推理的前置组合加入,当 GPU 开始推理时,AUTO Plugin 会将  CPU 中的推理任务转移到 GPU 设备继续进行。这样,对于编译模型速度比较慢的设备,例如使用 AUTO Plugin 部署 AI 应用到  GPU 中,这个应用在启动推理初始阶段的延迟将会变得非常低,接近于 CPU 推理的响应速度。在 OpenVINO™ 中使用 AUTO  Plugin 的方法也十分简单,只需要在 compile_model() 函数中,指定 device_name=“AUTO:CPU,GPU”  就可以实现了,例如下方所示是 Python 语言的使用方法:

compiled_model = core.compile_model(model=model, device_name="AUTO:CPU,GPU")

优化策略五:权衡是否使用 NNCF 量化的低精度模型

由于  FP32  全精度模型需要运算量相对比较大,很多开发者会将模型量化成低精度模型之后进行部署,这样由于模型计算量的减少,所以模型推理速度会快很多。但是,如果使用  OpenVINO™ 提供的 Neural Network Compression Framework(NNCF) 工具对 IR  模型进行量化,会导致低精度模型推理响应变慢,这是由于 NNCF 的压缩原理就是给原始模型插入很多 Fake Quantized  层来转换精度,低精度IR模型网络里是包含非常多的 Fake Quantized  层,在编译模型阶段,新插入的这些层将消耗很多时间进行全精度到低精度的计算转换。

图片

图 4:NNCF 量化 IR 模型示意图

所以在启动量化模型推理前的编译模型阶段,会消耗比原来全精度模型更多的时间。开发者需要权衡量化带来的模型响应变慢和推理速度之间的平衡。

优化策略六:将 ONNX 模型转换为 IR 模型进行推理

由于  OpenVINO™ 是可以直接支持 ONNX 模型进行推理的,所以有一部分的开发者会选择直接使用 ONNX 格式的模型进行推理。由于 ONNX  模型转成 IR 模型的过程中,会涉及模型层融合和裁剪的相关操作,IR 的网络层数肯定是比原来的 ONNX 模型要少的,再加上  OpenVINO™ Runtime 会针对 IR 文件的读取做优化,所以同一个原始模型下,用 IR 模型推理比 ONNX  模型推理的响应是要快的。所以建议开发者将 ONNX 格式模型转换为 IR 格式模型进行推理以获得更快的模型推理响应。

优化策略七:大模型推理使用最新版本的OpenVINO™ 工具套件

由于大模型的火热,目前 OpenVINO™ 每个版本都会针对大模型进行特定优化,若开发者使用的是比较新的大模型,我们建议大家使用最新版本的 OpenVINO™ 工具套件以获得大模型的最优推理响应和推理效果的的支持。 

优化策略八:模型映射

为了降低第一次推理的延迟,在读取模型阶段,我们可以将原本的模型读取替换为模型映射进入内存中以降低模型读取延迟,这是 OpenVINO™ 提供的 mmap 功能。

在默认设置中,这个功能是被打开的,也就是说  OpenVINO™ 是默认使用 mmap  读取模型的。但是需要注意的是,模型映射在少数一些使用场景下是会导致读取模型延迟增加的,就比如模型如果位于可移动存储或者网络驱动器上就有可能导致模型推理延迟增加,这个时候你可以选择禁用模型映射功能,例如在  C++ 的代码中进行设置 ov::enable_mmap(false) 就可以了。 

03 模型推理响应测试

我们将在如下环境下进行模型推理测试:

OS: Ubuntu 20.04 LTS 64bit

OpenVINO™ 版本号: 2023.2

CPU 型号 :英特尔® 酷睿™ i7-11700T 处理器

GPU 型号:Intel® Arc™ A770 16GB

i915 驱动版本:23.8.20_PSB_230810.22

1 Resnet-50 推理应用测试

测试脚本为测试运行一张图片推理的推理脚本,将脚本启动至第一帧推理完成的时间作为实验数据,以模拟实际应用启动的场景,推理线程数为 1,基准测试为运行模型为 FP32 精度的 Resnet-50 Pytorch 版本模型,模型较小,测试结果如下:

图片

本文所有测试均在基准环境下控制单一优化策略变量完成测试。

我们从测试结果中可以发现,首先,OpenVINO™  版本和模型映射对 Resnet-50 推理响应的影响差别不大,CPU 的推理响应速度确实是会比 GPU 更快。在 GPU 推理时应用了  AUTO Plugin 确实将推理的响应速度提升到了 CPU 的水准,这是 CPU 和 GPU  协同工作得到的结果。在应用模型缓存这个功能后,不论是 CPU 还是 GPU,模型进行第一次推理的时间都显著加快了,这个功能确实可以非常快速地提升  AI 推理程序的响应速度。当模型替换为 NNCF 量化后的模型,AI 应用响应会变得更慢。

在这个场景下,优化策略七(新版本  OV)和八(模型映射)效果就微乎其微了,所以在这种小模型 AI 应用场景,我们推荐考虑使用优化策略一(Model  Cache),三(CPU优先),四(AUTO plugin)和五(权衡 NNCF 的低精度模型)来加快模型的初次推理响应速度。

2 Transfomer 大模型推理响应测试

使用一个 Open Model Zoo 里比较经典的模型语言模型 GPT-2 进行测试,测试命令如下:

$benchmark_app -m “model_path” -d “device_name” -hint latency

测试结果如下所示:

图片

从图标的测试结果来看模型缓存在对于  CPU 推理编译模型加速还是很明显的,对于 GPU  来说就没那么明显了。当测试使用多线程的“throughput”模式虽然吞吐量变大,但是编译模型的时间也会加长。若使用 ONNX  模型,在读取模型和编译模型阶段都会比使用 IR 格式模型慢的多。

所以在这种场景下,推荐开发者使用优化策略一(模型缓存),优化策略二(Latency Mode)和优化策略六(ONNX 转 IR)进行部署。

3 Text-to-Image 大模型推理响应测试

由于  Resnet-50 的模型体积比较小,参数权重文件也仅有 110MB  的大小。模型编译的时间和模型的大小也有直接的关系,所以接下来我们将会测试一个体积稍微大一点的模型。Stable Diffusion  的文生图工作流程中,Unet  模型发挥了至关重要的作用,它负责将随机生成的原始图片,一步步修改校准为最后符合文字意思的图片。可想而知,这项工作需要的参数网络是相当大的,这同时也反映在  Unet 模型快接近于 3GB 的庞大体积上。所以,现在我们需要测试一些 Unet 模型在不同 OpenVINO™  版本下,在初次推理阶段的差异。测试 Unet 模型在读取模型和编译模型阶段所消耗的时间,测试命令如下:

$benchmark_app -m “model_path” -d “device_name” -hint latency

实验结果如下表:

图片

实验数据均为 10 次测试取平均值。

关于  OpenVINO™ 版本对于模型推理响应的影响,在 Resnet-50  中并不明显,原因是该模型相对比较经典,这两个版本对其的优化方法保持一致。但是由于近期大模型的火热,OpenVINO™ 在 2023  版本中对大模型的支持是不断在优化的,CPU 或者 GPU 运行推理在读取模型这一步的行动上,新版本就比老版本快了很多。在编译模型这步,CPU 在  OpenVINO™ 新版本相较于老版本也是快 2 倍多。并且,在 GPU  做推理的时候使用模型缓存的话,也能提升模型推理的响应速度。也可以看到这个模型在 CPU  中推理若应用模型缓存功能,得到的提升不明显,甚至还会更糟糕。

所以当模型缓存能够起到作用的情况下,推荐优先使用优化策略一(模型缓存)尽量使用模型缓存来优化大模型推理响应。并且推荐使用最新的 OpenVINO™ 工具套件来运行大模型的推理。

04 总结

在  AI 应用的日益普遍的今天,各种模型层出不穷,越来越多的 AI 模型被应用在了各行各业。OpenVINO™  工具套件作为英特尔为开发者提供的推理部署加速软件,可以很方便地被部署到包括了医疗,零售,交通或者工业场景中。无论是主流的视觉模型像 YOLO  系列,或者说最近火热的大模型像刚才展示的 Stable Diffusion 或者 GPT,ChatGLM 这样的大语言模型可以很轻松地使用  OpenVINO™ 部署到英特尔的硬件上进行 AI 推理。在运行这些 AI  推理应用的时候,往往会涉及到对推理启动时间的考量,特别是对于某些需要实时反馈的 AI 应用来说,初次推理的响应时间就会变得尤为重要,AI  程序的开发者也会去优化相关的代码程序,让 AI 推理的响应时间更短,让整个应用完成第一次推理的时间更快。

本文介绍了在使用  OpenVINO™ 工具套件部署 AI 推理时,如何利用 OpenVINO™ 提供的多种方式去优化程序启动初次推理的响应时间,包括了使用  AUTO Plugin,使用模型缓存或者说使用 mmap 方式读取模型。并且,充分分析了不同模型精度对模型初次推理响应时间的影响,由 NNCF  量化得到的 IR 模型会因为其模型结构中包含许多 FakeQuantized 层,使得模型网络编译的时间会比全精度 FP32 或半精度 FP16   的模型花的时间更多。当然,低精度模型的推理速度会比全精度模型的推理速度快的多,至于怎么去取舍推理速度和初次推理响应速度,也是需要AI应用程序开发者进行平衡的问题。

最后,在分析新老版本对模型初次推理响应速度的实验里,我们发现像  Resnet-50 这些问世比较久的经典模型,OpenVINO™ 对它们的优化策略是一致的,所以新旧版本对其推理结果影响不大。但是对于  Stable Diffusion 这样的大模型来说,由于 OpenVINO™ 2023.0  以后的每个小版本都会对大模型进行相关的优化,所以在新旧版本对比中,新版本的 OpenVINO™ 在推理 Stable Diffusion  的模型的时候,不论是读取模型还是推理模型方面,速度都做了相应的优化,比老版本快的多得多。若是在 GPU 中推理 Stable  Diffusion,使用模型缓存还能得到较于原本更快的初次推理响应速度。总的来说,如果有需要基于 OpenVINO™  做一些大模型的推理部署,建议开发者们选择最新版本的 OpenVINO™ 工具套件进行使用,以获得最新的优化以及模型支持。

05 参考资料

AUTO Plugin:

https://docs.openvino.ai/2023.2/openvino_docs_OV_UG_supported_plugins_AUTO.html 

Model Cache:

https://docs.openvino.ai/2023.2/openvino_docs_OV_UG_Model_caching_overview.html 

NNCF: 

https://docs.openvino.ai/2023.1/openvino_docs_model_optimization_guide.html 

Performance Mode: https://docs.openvino.ai/2023.2/openvino_docs_OV_UG_Performance_Hints.html


作者:周兆靖——英特尔高级应用工程师

对计算机视觉感兴趣?这个社区推荐给你~

>>点击了解OpenVINO生态开发社区




关键词: 实战     开发者     OpenVINO     推理    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]