首页 > 文章 > 带有 HBM 的 Alveo加速卡的DPUv3E介绍

带有 HBM 的 Alveo加速卡的DPUv3E介绍

Gang Yuan 2020年02月05日

DPUv3E 简介

DPUv3E 是 Xilinx® DPU IP 产品系列中的一员,面向卷积神经网络 (CNN) 推断应用。借助 HBM 的技术支持,它专为最新 Xilinx Alveo U50/U280 灵活应变加速卡而设计。 DPU V3E 是高性能 CNN 推断 IP,用于吞吐量和数据中心工作负载的优化。 DPUv3E 在高度优化的指令下运行,支持 VGG、ResNet、GoogLeNet、YOLO、SSD、MobileNet 和FPN 等所有主流卷积神经网络。

DPUv3E 是 Xilinx Vitis™ AI 发展环境的基本IP(叠加)之一,借助 DPUv3E用户可以使用 Vitis AI 工具链完成全堆栈 ML 开发。此外,用户还可以使用标准的 Vitis 流程(可,完成 对DPUv3E 与其他定制加速内核进行集成),来实现强大的 X+ML 解决方案。DPUv3E 以加密 RTL 或 XO 文件格式提供给基于 Vivado 或 Vitis 的集成流程。

支持神经网络的主要操作步骤如下:

  • Convolution / Deconvolution
  • Max pooling / Average pooling
  • ReLU, ReLU6, and Leaky ReLU
  • Concat
  • Elementwise-sum
  • Dilation
  • Reorg
  • Fully connected layer
  • Batch Normalization
  • Split

DPUv3E 是高度可配置的。一个 DPUv3E 内核包括多个批量引擎、一个指令调度器、一个共享权重缓冲器和一个控制寄存器约束。以下是 DPUv3E 内核框图,包括5个批处理引擎。

DPUv3e Kernel

批处理引擎

批处理引擎是 DPUv3E 的核心计算单元。 一个批处理引擎能一次处理一个输入图像,因此 DPUv3E 内核中的多个批处理引擎能同时处理多个图像。DPUv3E 内核中批处理引擎的数量可依照 FPGA 资源条件和客户对性能的要求进行配置。例如,在 Alveo U280 卡中, SLR0(具有 HBM 直连)可包括一个 DPUv3E 内核,最多可带 4 个批处理引擎,而 SLR1 或 2 则可包括一个 DPUv3E 内核,带 5 个批处理引擎。批处理引擎中的卷积引擎可处理一般卷积/去卷积计算,以及一个MISC引擎处理池化、ReLu 和其他各项操作。MISC 引擎也可根据具体神经网络要求配置可选功能。每个批处理引擎都使用 AXI 读写主接口实现器件存储器之间的特性映射数据交换 (HBM)。

指令调度器

指令调度器在概念上与通用处理器类似,执行指令获取、解码和分配工作。由于 DPUv3E 内核中的所有批处理引擎都在相同的神经网络内运行,因此指令调度器服务于所有带有相同指令流的批处理引擎。指令流由主机 CPU 通过 PCIe 接口载入器件存储器 (HBM),而指令调度器使用一个 AXI 读取主接口,以获取批处理引擎的DPU指令。

共享权重缓冲器

共享权重缓冲器包括复杂的策略和控制逻辑,以管理从 Alveo 器件存储器加载神经网络权重,并将其传输至批处理引擎。由于 DPUv3E 内核中的所有批处理引擎都在相同的神经网络内运行,因此权重数据很得当地加载到片上缓冲,并由所有批处理引擎分担,从而避免不必要的内存访问,以节约带宽。共享权重缓冲器使用两个 AXI 读取主接口从器件存储器 (HBM) 加载到权重数据。

控制寄存器约束

控制寄存器约束是 DPUv3E 内核和主机 CPU 之间的控制接口。它操作实施一系列控制器寄存器,以符合 Vitis 开发流程。控制寄存器约束具有一个 AXI 从接口。


性能和资源利用

下表列出 DPUv3E 单内核/单批处理引擎(最小配置)结合部分典型神经网络的性能数据,并给出 Alveo U50/U280 上的两种可能实施方案。请注意,由于 HBM 内存系统的特点,整体性能几乎与内核及批处理引擎的数量呈线性关系,二者提供了很大的灵活性,在最少的资源占用和功耗条件下,满足具体的性能要求。

Configuration NN Model Frame Rate (FPS)

单内核,单批处理引擎

ResNet50 98
Inception V1 193
Inception V2 138
Inception V3 44
Inception V4 23
Yolo V2 30
Tiny Yolo V2 90
FRCNN 35

双内核,带 5 个批处理引擎 (5+5)

(U50 无功率阀限制)

ResNet50 1000

(5+5+4)三个内核、5 个批处理引擎,对应两个内核、4 个批处理引擎  (5+5+4)

(U280)

ResNet50 1550

以下给出带 5 个批处理引擎的典型 DPUv3E 内核资源利用率数据。

配置

LUT

FF

BRAM

URAM

DSP

Leaky ReLU 支持的5 个批处理引擎
250290 310752 628 320 2600

使用 Vitis 流程在 Alveo HBM 卡上集成 DPUv3E

DPUv3E 使用 Alveo HBM 卡(U280、U50)的 HBM 作为外部内存。 Alveo U280 和 U50 具有 8GB HBM(两个 4GB 堆栈),提供 32 个用作客户逻辑的 HBM 伪通道,以及 32 个 256 位硬化 HBM AXI 端口。 面向 U280 和 U50 (如 xilinx_u280_xdma_201920_1 和 xilinx_u50_xdma_201920_1)的Vitis 目标平台,与提供所需的 AXI 总线结构以及主机-器件的互动层。

使用 Vitis,集成 U280/U50 卡上 DPUv3E 的步骤非常简单明了:

  1. 使用特定配置准备 DPUv3E 内核文件(官方发布的 .XO 文件)
  2. 准备特定的加速内核文件(如果有 .XO 文件的话)
  3. 确定 DPUv3E 内核和其他定制内核(如果有的话)的 HBM 端口分配
  4. 编辑 v++ 命令行脚本、Makefile 和/或配置文件
  5. 使用 v++ 完成系统构建,获得最终 U50/U280 的 XCLBIN 覆盖文件 
  6. 使用 Vitis 和 Vitis AI 软件流程进行主机应用开发

下图是 Alveo U280 的设计 HBM 连接方案示例,其带有两个 DPUv3E 内核(5 个批处理引擎)、4 个 JPEG 解码器内核和一个图形大小调整器内核。

hbm-connection

示例中的 JPEG 解码器为赛灵思 IP ,它是一个打包到 XO 文件的 RTL 内核。以下给出顶级端口示意图,内核名称为 jpage_decoder_v1_0。

jpeg-decoder

图形大小调整器内核为基于 Vitis 视觉库的 HLS 内核,综合到 XO 文件。以下给出内核的主体,内核名称为 resize_accel。

 

    #include "ap_int.h"
#include "common/xf_common.hpp"
#include "common/xf_utility.hpp"
#include "hls_stream.h"
#include "imgproc/xf_resize.hpp"
 
#define AXI_WIDTH 256
#define NPC XF_NPPC8
#define TYPE XF_8UC3
#define MAX_DOWN_SCALE 7
 
#define PRAGMA_SUB(x) _Pragma(#x)
#define DYN_PRAGMA(x) PRAGMA_SUB(x)
 
#define MAX_IN_WIDTH 3840
#define MAX_IN_HEIGHT 2160
#define MAX_OUT_WIDTH 3840
#define MAX_OUT_HEIGHT 2160
 
#define STREAM_DEPTH 8
#define MAX_DOWN_SCALE 7
 
extern "C"
{
    void resize_accel (ap_uint *image_in,
                            ap_uint *image_out,
                            int width_in,
                            int height_in,
                            int width_out,
                            int height_out)
    {
#pragma HLS INTERFACE m_axi port = image_in offset = slave bundle = image_in_gmem
#pragma HLS INTERFACE m_axi port = image_out offset = slave bundle = image_out_gmem
#pragma HLS INTERFACE s_axilite port = image_in bundle = control
#pragma HLS INTERFACE s_axilite port = image_out bundle = control
#pragma HLS INTERFACE s_axilite port = width_in bundle = control
#pragma HLS INTERFACE s_axilite port = height_in bundle = control
#pragma HLS INTERFACE s_axilite port = width_out bundle = control
#pragma HLS INTERFACE s_axilite port = height_out bundle = control
#pragma HLS INTERFACE s_axilite port = return bundle = control
 
        xf::cv::Mat in_mat(height_in, width_in);
        DYN_PRAGMA(HLS stream variable = in_mat.data depth = STREAM_DEPTH)
 
        xf::cv::Mat out_mat(height_out, width_out);
        DYN_PRAGMA(HLS stream variable = out_mat.data depth = STREAM_DEPTH)
 
#pragma HLS DATAFLOW
 
        xf::cv::Array2xfMat(image_in, in_mat);
        xf::cv::resize(in_mat, out_mat);
        xf::cv::xfMat2Array(out_mat, image_out);
    }
}

以下给出示例v++配置文件,与 HBM 连接块图相对应。

    [connectivity]
# ---------------------------------------------------------------
# multiple instances of 'jpeg_decoder_v1_0'
nk=jpeg_decoder_v1_0:4:jpeg_decoder_1.jpeg_decoder_2.jpeg_decoder_3.jpeg_decoder_4
 
# SLR assignment of 'jpeg_decoder'
slr=jpeg_decoder_1:SLR0
slr=jpeg_decoder_2:SLR0
slr=jpeg_decoder_3:SLR0
slr=jpeg_decoder_4:SLR0
 
# HBM port assignment of 'jpeg_decoder'
sp=jpeg_decoder_1.m00_axi:HBM[16]
sp=jpeg_decoder_2.m00_axi:HBM[17]
sp=jpeg_decoder_3.m00_axi:HBM[18]
sp=jpeg_decoder_4.m00_axi:HBM[19]
 
# ---------------------------------------------------------------
# single instance of 'resize_accel'
nk=resize_accel:1:resize_accel_1
 
# SLR assignment of 'resize_accel'
slr=resize_accel_1:SLR0
 
# HBM port assignment of 'resizer'
sp=resize_accel_1.m_axi_image_in_gmem:HBM[20]
sp=resize_accel_1.m_axi_image_out_gmem:HBM[21]
 
# ---------------------------------------------------------------
# multiple instances of 'dpuv3e_5be'
nk=dpuv3e_5be:2:dpuv3e_5be_1.dpuv3e_5be_2
 
# SLR assignment of 'dpuv3e_5be'
slr=dpuv3e_5be_1:SLR1
slr=dpuv3e_5be_2:SLR2
 
# HBM port assignment of 'dpuv3e_5be'
sp=dpuv3e_5be_1.dpu_axi_0:HBM[0]
sp=dpuv3e_5be_1.dpu_axi_1:HBM[1]
sp=dpuv3e_5be_1.dpu_axi_2:HBM[2]
sp=dpuv3e_5be_1.dpu_axi_3:HBM[3]
sp=dpuv3e_5be_1.dpu_axi_4:HBM[4]
sp=dpuv3e_5be_1.dpu_axi_i:HBM[5]
sp=dpuv3e_5be_1.dpu_axi_w0:HBM[6]
sp=dpuv3e_5be_1.dpu_axi_w1:HBM[7]
 
sp=dpuv3e_5be_2.dpu_axi_0:HBM[8]
sp=dpuv3e_5be_2.dpu_axi_1:HBM[9]
sp=dpuv3e_5be_2.dpu_axi_2:HBM[10]
sp=dpuv3e_5be_2.dpu_axi_3:HBM[11]
sp=dpuv3e_5be_2.dpu_axi_4:HBM[12]
sp=dpuv3e_5be_2.dpu_axi_i:HBM[13]
sp=dpuv3e_5be_2.dpu_axi_w0:HBM[14]
sp=dpuv3e_5be_2.dpu_axi_w1:HBM[15]

以下命令行可用来完成 xclbin 构建(假定 DPUv3E、JPEG 解码器和图形大小调整器的 XO 文件为 dpuv3e_5be.xo、jpeg_decoder_v1_0.xo 和 resize_accel.xo):

    v++ --link                               \
    --target hw                          \
    --platform xilinx_u280_xdma_201920_1 \
    --config example_config.txt          \
    --output dpuv3e_integration.xclbin   \
    dpuv3e_5be.xo jpeg_decoder_v1_0.xo resize_accel.xo

结论

DPUv3E 是一款灵活且高性能的卷积神经网络推断 IP ,专门针对 Alveo HBM 卡设计。所需 DPUv3E 内核的数量以及每个 DPUv3E 内核的批处理引擎数量都是完全可配置的,这就使其具有很强的自适应性来满足具体场景的需要。用户可以使用 Vitis和 Vitis AI 流程,轻松地将 DPUv3E 与自身特定的加速内核进行集成。 


更多参考资料