地平线X3芯片中有两个BPU IP核,针对两个IP核,我们提供了多种使用方式。这篇文档我们会详细解释如何利用好BPU双核资源。但是在此之前,我们首先需要理解单核模型和双核模型的概念。
单核模型和双核模型
正常情况下,针对单个模型输入数据/图片,我们会在单个BPU核上进行模型的推理计算,这种类型的模型我们叫做单核模型,此时对于单帧图片,只利用了单个BPU的物理计算资源进行计算。此时对于多张图片的推理场景,可以并发的独立的去使用两个BPU核。因此针对单核模型,我们日常评测都是基于单BPU进行评测,输出“单帧单核”的FPS数据和推理延迟,对于整个X3芯片来算,“多帧多核”场景的,可以获取*2倍的FPS,并且保持着推理延迟的不变。
对于一些场景,针对单帧图片仅利用单个BPU的物理计算资源,推理延迟不满足预期,我们希望可以同时利用两个BPU核的物理资源来对推理进行加速,降低单帧图片推理延迟,即“真双核”模式。对于一个模型是否可以运行在“真双核”模式下,是在模型编译环节通过core_num参数来决定,即将一个模型编译成双核模型,详细参考如下配置文件:
# 编译器相关参数compiler_parameters: # 编译策略,支持bandwidth和latency两种优化模式; # bandwidth以优化ddr的访问带宽为目标; # latency以优化推理时间为目标 compile_mode: 'latency' # 设置debug为True将打开编译器的debug模式,能够输出性能仿真相关信息,如帧率、DDR带宽占用等 debug: False # 编译模型指定核数,不指定默认编译单核模型, 若编译双核模型,将下边注释打开即可 core_num: 2 # 优化等级可选范围为O0~O3 # O0不做任何优化, 编译速度最快,优化程度最低, # O1-O3随着优化等级提高,预期编译后的模型的执行速度会更快,但是所需编译时间也会变长。 # 推荐用O2做最快验证 optimize_level: 'O3'
对于双核模型,它可以针对单帧图片显著降低推理延迟,但是会带来部分BPU调度开销,它无法像单核模型一样,针“多帧多核”获得*2倍的FPS的提升。对于双核模型,它的单帧场景和多帧场景,可以获得FPS数据是一样的。
理解BPU利用率和BPU MAC利用率
地平线 BPU 硬件加速核是一个独占式物理资源,这个对如何正确使用BPU资源非常重要。在针对单帧图片进行推理的时候,Runtime API会发起对 BPU 资源的锁定,推理结束即会对资源进行释放。此时每个BPU 核整体上会进入 Busy 和 Idle 状态,最后 BPU 整体 Busy 状态占比即为 BPU 利用率。在我们开发板上,可以利用系统软件命令 hrut_somstatus 来看 BPU 利用率。
在很多业务场景下,模型的前后处理和模型推理过程串行进行处理,此时如果没有采用多线程技术,BPU整体上利用率较低,无法获得预期的模型推理帧率数据。同时在一些场景下,也可能会因为BPU资源紧张,堵塞业务线程,导致模型推理延迟加大。所以在使用BPU核过程中,需要密切关注BPU核的利用率数据,基于BPU核的利用率来合理分配模型在多个核之间的调度规则,详细参见后面的多核调度内容。
另外一个与此类似的概念叫做 BPU MAC 利用率,这个是和模型相关的,即 BPU 资源被推理任务锁定以后,针对模型进行推理,此时 BPU MAC 计算单元使用率。地平线编译器目标就是去优化这个 BPU MAC 利用率。目前 BPU MAC 利用率无法实时进行获取,可以利用编译器静态性能评估工具 hbdk-pref 来获取模型 BPU MAC 利用率。
双核调度策略
详细参考《BPU SDK API文档》中HB_BPU_runModel接口描述,其中有以下几个点需要关注:
- 以同步方式去使用该接口。此时针对单核模型,我们可以手动指定本次runmodel推理计算使用的bpu core_id,也可以由系统自动基于BPU状态去选择相应的bpu core。但是对于双核模型,无法去指定所使用的bpu core_id,它会同时使用两个bpu core。
- 以异步方式去使用该接口。此时业务层面无法去选择相应的core id,驱动层面会基于两个核的状态去选择相应的bpu core来进行推理计算。