当前位置: 首页 > article >正文

【Vitis AI】FPGA设备使用PyTorch 运行 ResNet18获得10000fps

来自 Vitis AI 库的 PyTorch 中的 ResNet18

  • 版本:Vitis AI 3.5 with Pytorch 1.13.1
  • 支持:ZCU102, ZCU102, VCK190, VEK280, Alveo V70

1 简介

1.1 理由

在本深度学习 (DL) 教程中,您将使用一个公共领域的卷积神经网络 (CNN),如 ResNet18,并通过 Vitis AI 3.5 堆栈在 FPGA 设备上运行 DL 推理;该应用程序对图像中“汽车对象”的不同颜色进行分类。

尽管 ResNet18 已经在 PyTorch 框架中的 ImageNet 数据集上进行了训练,但您将使用 Kaggle Vehicle Color Recognition 数据集(简称 VCoR)重新训练它。

1.2 Vitis AI 流程

假设您已经训练了 CNN 并拥有其原始模型,通常是一个扩展名为.h5 的 HDF5 文件,您将按照以下步骤将该 CNN 部署到 FPGA 目标板:

  1. (可选)运行 Model Inspector 检查原始模型是否与 AMD Deep Processor Unit (DPU) 架构兼容,该架构在目标板上可用(如果不是,您必须修改 CNN 并重新训练它)。

  2. 运行 Model Quantization 过程,从原始 32 位浮点 CNN 生成一个 8 位定点(简称“int8”)模型。如果您应用所谓的Post-Training Quantization (PTQ),这将是一个单步操作,否则您需要使用 Quantization-Aware-Training (QAT) 重新训练(或者更确切地说“微调”)CNN。

  3. (可选)在 Vitis AI 环境(在主机桌面上运行)上使用 int8 模型运行推理,以检查预测准确性:如果差异不可忽略(例如,大于 5%),您可以将 PTQ 替换为 QAT 重新进行量化。

  4. 在 int8 模型上运行 Model Compilation 过程,为目标板的 DPU IP 软核生成.xmodel 微代码。

  5. 使用带有 Vitis AI RunTime (VART) API 的 C++ 或 Python 代码编译在目标板的 ARM CPU(与 DPU 紧密耦合)上运行的应用程序。

基于此,您将能够测量推理性能,包括目标板上的平均预测准确性和每秒帧数 (fps) 吞吐量。

本文档中报告的所有命令也收集在 run_all.sh 脚本中。

2 前提条件

以下是您在开始本教程的实际内容之前需要具备和执行的内容。

  • 熟悉 DL 原理。

  • 在运行任何脚本之前,请从头到尾准确阅读此 README.md 文件。

  • 具有 Ubuntu >= 18.04.5 的主机 PC(并且可能具有 GPU 支持以运行 CNN 训练)。

  • 从 www.github.com/Xilinx 网站克隆 Vitis AI 3.5 堆栈的整个存储库。

  • 准确阅读 Vitis AI User 3.5 Guide 1414(简称 UG1414)。

  • 准确阅读 Vitis AI 3.5 在线文档。特别是,请注意主机 PC 和目标板的安装和设置说明,建议您构建一个基于 GPU 的带有 TF2 的 Docker 镜像。

  • AMD 目标板,例如:

    • Zynq® UltraScale+™ MPSoC ZCU102,或
    • Zynq® UltraScale+™ MPSoC ZCU104,或
    • Versal AI Core 系列 VCK190,或
    • Versal AI Edge 系列 VEK280,或
    • Alveo V70 AI 加速器。
  • 包含 Kaggle 图像数据集的archive.zip 文件,如第 4 VCoR 数据集 节中所述。

  • 大小为 179507695 字节的 模型动物园 pt_vehicle-color-classification_3.5.zip 存档,如第 [5.1 从 Vitis AI 模型动物园获取 ResNet18](#51-get-resnet18 -from-vitis-ai-model-zoo) 节中所述。

2.1 工作目录

在本文档的后续部分中,假设您已在文件系统中的某个位置安装了 Vitis AI 3.5(简称VAI3.5),这将是您的工作目录${WRK_DIR},例如export WRK_DIR=/media/danieleb/DATA/VAI3.5。您还在${WRK_DIR} 下创建了一个名为tutorials 的文件夹,并将本教程复制到该文件夹并将其重命名为PyTorch-ResNet18。使用命令tree -d -L 2,您应该看到以下目录:

${WRK_DIR} # 您的 Vitis AI 3.5 工作目录
├── bck
├── board_setup
│   ├── v70
│   └── vek280
├── demos
├── docker
│   ├── common
│   ├── conda
│   └── dockerfiles
├── docs
│   ├── docs
│   ├── _downloads
│   ├── doxygen
│   ├── _images
│   ├── _sources
│   └── _static
├── docsrc
│   ├── build
│   └── source
├── dpu
├── examples
│   ├── custom_operator
│   ├── ofa
│   ├── OnBoard
│   ├── vai_library
│   ├── vai_optimizer
│   ├── vai_profiler
│   ├── vai_quantizer
│   ├── vai_runtime
│   ├── waa
│   └── wego
├── model_zoo
│   ├── images
│   └── model-list
├── src
│   ├── AKS
│   ├── vai_library
│   ├── vai_optimizer
│   ├── vai_petalinux_recipes
│   ├── vai_quantizer
│   └── vai_runtime
├── third_party
│   ├── tflite
│   └── tvm
└── tutorials # 由您创建
    ├── PyTorch-ResNet18 # 本教程
    ├── TF2-Vitis-AI-Optimizer

2.2 Dos 到 Unix 的转换

如果您在脚本执行期间遇到一些奇怪的错误,您必须仅使用 dos2unix 实用程序处理所有 *.sh shell 脚本和 python *.py 脚本一次。
在这种情况下,请从 Ubuntu 主机 PC(在 Vitis AI Docker 镜像之外)运行以下命令:

sudo apt-get install dos2unix
cd ${WRK_DIR}/tutorials/PyTorch-ResNet18 #您的存储库目录
for file in $(find . -name "*.sh"); do
  dos2unix ${file}
done
for file in $(find . -name "*.py"); do
  dos2unix ${file}
done
for file in $(find . -name "*.c*"); do
  dos2unix ${file}
done
for file in $(find . -name "*.h*"); do
  dos2unix ${file}
done

这些操作已经包含在 run_all.sh 脚本中,该脚本由 run_all.sh 脚本启动,该脚本收集了本文档其余部分中显示的所有命令。

强烈建议您熟悉 run_all.sh 脚本,以便了解它所做的一切,最终了解主机计算机上的整个 Vitis AI 流程。

3 Docker 工具镜像

您必须了解有关 Docker 的一些知识,以便在您的主机 PC 环境上顺利运行 Vitis AI。

3.1 构建镜像

从 Vitis AI 3.5 存储库中,运行以下命令:

cd ${WRK_DIR}
cd docker
./docker_build.sh -t gpu -f pytoch

该过程完成后,使用命令docker images,您应该看到类似以下内容:

仓库 TAG 镜像 ID 创建时间 大小
xilinx/vitis-ai-pytorch-gpu 3.5.0.001-b56bcce50 3c5d174a1807 27 小时前 21.4GB

3.2 启动 Docker 镜像

要使用 Vitis AI 工具启动 Docker 容器,请从 ${WRK_DIR} 文件夹执行以下命令:

cd ${WRK_DIR} # 您现在位于 Vitis_AI 子文件夹中

./docker_run.sh xilinx/vitis-ai-pytorch-gpu:latest

conda activate vitis-ai-pytorch

cd /workspace/tutorials/

cd PyTorch-ResNet18 # 您的当前目录

请注意,该容器将共享文件夹 /workspace 与您从中启动上述命令的主机 PC 的文件系统映射。
此共享文件夹使您能够将文件从主机 PC 传输到 Docker 容器,反之亦然。

Docker 容器没有任何图形编辑器,因此建议您使用两个终端并指向同一个文件夹,在一个终端中使用 Docker 容器命令,在另一个终端中打开您喜欢的任何图形编辑器。

如果您需要添加一些其他软件包,例如randaugmenttorchsummary

sudo su
conda activate vitis-ai-pytorch
pip install randaugment
pip install torchsummary
#exit

然后记住从不同的终端(除了您正在运行 Docker 镜像的第一个终端之外的第二个终端)永久保存修改后的 Docker 镜像,
方法是启动以下命令:

$ sudo docker ps -l
$ sudo docker commit -m"COMMENT" CONTAINER_ID DOCKER_IMAGE

您应该看到类似以下内容:

$ sudo docker ps -l
容器 ID 镜像 命令 创建时间
8626279e926e xilinx/vitis-ai-pytorch-gpu:3.5.0.001-b56bcce50 "/opt/nvidia/nvidia_…" 6 小时前

$ sudo docker commit -m"pyt new_package" 8626279e926e xilinx/vitis-ai-pytorch-gpu:3.5.0.001-b56bcce50

3.3 需要了解的事项

  1. 如果您“无法连接到 unix:/var/d9f942cdf7de xilinx/vitis-ai-tensorflow2-gpu:3.5.0.001-b56bcce50 run/docker.sock 处的 Docker 守护程序。Docker 守护程序是否正在运行?”,只需启动以下命令:
sudo systemctl restart docker
  1. 请注意,到目前为止,Docker 没有自动垃圾回收系统。您可以使用此命令执行手动垃圾回收:
docker rmi -f $(docker images -f "dangling=true" -q)
  1. 为了清理 Docker 消耗的(通常是大量)空间,请查看此帖子:Docker Overlay2 清理。以下命令非常有效(尤其是最后一个命令):
docker system df
docker image prune --all
docker system prune --all

4 VCoR 数据集

本教程中采用的数据集是 Kaggle Vehicle Color Recognition,简称 VCoR。

您可以在 Vitis AI 模型动物园在线表格 中找到它的超链接。

此数据集由要分类的 15 类颜色(用于汽车)组成。它包含大小为 224x224x3 的标记 RGB 图像,并且是为论文开发的

  • Panetta, Karen, Landry Kezebou, Victor Oludare, James Intriligator, and Sos Agaian. 2021. “人工智能在基于文本的车辆搜索、识别和交通视频中的持续定位中的应用” AI 2, no. 4: 684-704. https://doi.org/10.3390/ai2040041

  • 开放访问:https://www.mdpi.com/2673-2688/2/4/41

在 Docker 容器之外,从 VCoR 网站下载约 602MB 的archive.zip 文件,然后将其解压缩到build/dataset/vcor 文件夹中
(如 run_all.sh 脚本中所示):

cd ${WRK_DIR}/tutorials/PyTorch-ResNet18/files
# 您必须已经下载了 zip 存档
unzip ./archive.zip -d ./build/dataset/vcor/

5 使用 ResNet18 进行车辆颜色分类

以下小节中显示的所有命令都可在 run_all.sh 脚本中使用,通常使用以下命令调用:

source ./run_all main_vocr

5.1 从 Vitis AI 模型动物园获取 ResNet18

您必须下载此 model.yaml 文件中报告的 ResNet18 的 pt_vehicle-color-classification_3.5.zip 存档。
正如文件名所说,此类 CNN 已经在输入大小为 224x224 的 RGB 图像上进行了训练
并且它需要每次图像计算 3.64GOP。

从 Docker 镜像中,解压缩 pt_vehicle-color-classification_3.5.zip 存档到files 文件夹中
并清理一些文件/文件夹,执行以下操作(已在 run_all.sh 脚本中提供):

cd ${WRK_DIR} # 您现在位于 Vitis_AI 子文件夹中
# 进入 Docker 镜像
./docker_run.sh xilinx/vitis-ai-pytorch-gpu:latest
# 激活环境
conda activate vitis-ai-pytorch
# 转到教程目录
cd /workspace/tutorials/
cd PyTorch-ResNet18/files # 您的当前目录
# 您必须已经下载了存档
unzip pt_vehicle-color-classification_3.5.zip
# 清理一些文件/文件夹
cd pt_vehicle-color-classification_3.5
rm -rf code data *.md *.txt *.sh
cd ..

您将获得 files/pt_vehicle-color-classification_3.5/ 文件夹,您可以在其中分别在子文件夹 floatquant 中找到预训练的浮点模型和量化模型。您可以忽略并删除所有其他子文件夹。

本教程中应用的 ResNet18 CNN 旨在识别输入图像中汽车车辆的颜色。

在实际应用中,输入图像通常包含多个车辆,或者存在许多区域作为背景,
因此通常与对象检测 CNN 一起使用,这意味着首先
使用对象检测网络检测车辆区域,并根据对象检测网络的输出边界框切割原始图像,然后将裁剪后的图像发送到网络进行分类。在pt_vehicle-color-classification_3.5
您可以使用 YoloV3 CNN 检测 VCoR 数据集中的汽车,并使用裁剪后的图像构建新数据集来训练和测试模型。
如果您的输入图像包含很少的背景,或者您的 CNN 没有与对象检测 CNN 结合使用,则可以跳过此步骤
(这确实是本教程中所做的)。

此车辆颜色模型属于 Vitis AI 库“分类”示例:

  • 模型名称为chen_color_resnet18_pt,这使得它不明显它实际上是车辆颜色分类。

  • 这是 汽车颜色列表。由于有 15 种颜色,因此也有 15 个要分类的类别。

  • DPU 输出将是具有 15 个类别的 分类结果数据结构。然后,ARM CPU 将使用此类输出张量来计算函数SoftMax 和相关的Top-5 预测准确性。

5.2 训练

如果您想从头开始在 VCoR 数据集上训练 ResNet18 CNN,只需启动脚本 run_train.sh(这已经从 run_all.sh 脚本中完成):

cd ${WRK_DIR} # 您现在位于 Vitis_AI 子文件夹中
# 进入 Docker 镜像
./docker_run.sh xilinx/vitis-ai-pytorch-gpu:latest
# 激活环境
conda activate vitis-ai-pytorch
# 转到教程目录
cd /workspace/tutorials/
cd PyTorch-ResNet18/files # 您的当前目录
bash -x ./scripts/run_train.sh main_vcor

您应该看到类似以下内容:

. . .

Train Epoch: 29 [0/7267 (0%)] Loss: 0.004103
Train Epoch: 29 [5120/7267 (71%)] Loss: 0.006058
Test set: Average loss: 0.4320, Accuracy: 1380/1550 (89.032%)

. . .

classes: ['beige', 'black', 'blue', 'brown', 'gold', 'green', 'grey', 'orange', 'pink', 'purple', 'red', 'silver', 'tan', 'white', 'yellow']

Test set: Average loss: 0.4320, Accuracy: 1380/1550 (89.032%)

请注意,当您在 train.py 和 test.py 文件中使用 ToTensor() 类时,PyTorch 自动将所有图像转换为 [0,1] 范围。

图像应该采用 RGB 格式,而不是 BGR 格式(通常由 OpenCV 库采用)

5.3 量化

如果您想从头开始量化浮点 ResNet18 CNN,只需启动脚本 run_quant.sh(这已经从 run_all.sh 脚本中完成)。

您应该看到类似以下内容:

. . .

[VAIQ_NOTE]: =>正在进行权重均衡化...
[VAIQ_NOTE]: =>已生成可量化模块。(quantized/ResNet.py)
[VAIQ_NOTE]: =>获取带有量化的模块。

Test set: Average loss: 0.4234, Accuracy: 1376/1550 (88.774%)

. . .

[VAIQ_NOTE]: =>成功将“ResNet_0”转换为 xmodel。(quantized/ResNet_0_int.xmodel)
[VAIQ_NOTE]: 已生成 ResNet_int.pt。(quantized/ResNet_int.pt)
[VAIQ_NOTE]: 已生成 ResNet_int.onnx。(quantized/ResNet_int.onnx)

5.4 编译目标 DPU

然后必须针对目标板的 DPU 架构编译量化的 CNN,使用脚本 run_compile.sh(这已经从 run_all.sh 脚本中完成)。

您应该看到类似以下内容:

-----------------------------------------
为 VCK190 编译模型..
-----------------------------------------
[UNILOG][INFO] 编译模式:dpu
[UNILOG][INFO] 调试模式:null
[UNILOG][INFO] 目标架构:DPUCVDX8G_ISA3_C32B6
[UNILOG][INFO] 图名称:ResNet_0,具有操作数:171
[UNILOG][INFO] 开始编译...
[UNILOG][INFO] 设备子图总数 3,DPU 子图数 1
[UNILOG][INFO] 编译完成。
[UNILOG][INFO] 元 json 已保存到“/workspace/tutorials/PyTorch-ResNet18/files/./build/compiled_vck190/meta.json”
[UNILOG][INFO] 编译后的 xmodel 已保存到“/workspace/tutorials/PyTorch-ResNet18/files/./build/compiled_vck190/vck190_ResNet_0_int.xmodel.xmodel”
[UNILOG][INFO] 编译后的 xmodel 的 md5sum 为 df3f607e0b632e90d4c8eafdd174bef8,并且已保存到“/workspace/tutorials/PyTorch-ResNet18/files/./build/compiled_vck190/md5sum.txt”
**************************************************

5.5 在目标板上运行

仅针对 VEK280 板显示以 fps 为单位测量的吞吐量,仅作为参考。对于其他板,结果可能会因不同的 DPU 架构和相关的批处理大小 (BS) 而有很大差异。

以下小节中说明的所有命令都在脚本 run_all_vcor_target.sh 中,它们通过启动命令 run_all_target.sh xxxyyy 直接应用于目标板 xxxyyy
(即 zcu102、vck190、v70、vek280 等),这涉及 run_all_target.sh 更高级别的脚本。

5.5.1 多线程 C++ 应用程序代码

在目标板的嵌入式 ARM CPU 上运行的 C++ 应用程序是在 main_int8.cc 文件中编写的。请注意,输入图像在进入 DPU 之前以与训练期间预处理的完全相同的方式进行预处理,即:

  • RGB 图像格式(而不是 BGR);

  • 像素范围 [0, 255] 被归一化为数据范围 [0,1]

以下是相关的 C++ 代码片段:

Mat image = imread(baseImagePath + images[n + i]);

/*图像预处理*/
Mat image2 = cv::Mat(inHeight, inWidth, CV_8SC3);
resize(image, image2, Size(inHeight, inWidth), 0, 0, INTER_NEAREST);
for (int h = 0; h < inHeight; h++)
{
  for (int w = 0; w < inWidth; w++)
  {
    for (int c = 0; c < 3; c++)
    {
      //在 RGB 模式下
      imageInputs[i*inSize+h*inWidth*3+w*3+2-c] = (int8_t)( (image2.at<Vec3b>(h, w)[c]/255.0f)*input_scale );
    }
  }
}

请注意,DPU API 应用 OpenCV 函数来读取图像文件(无论是png 还是jpg 还是任何格式),因此图像被视为 BGR 而不是本机 RGB。本教程中完成的所有训练和推理步骤都将图像视为 RGB,这对于上述 C++ 归一化例程也是如此。

5.5.2 运行时执行

可以直接在目标上编译应用程序(除了将其编译到主机计算机环境中之外),这是可能的并且很简单。
事实上,这就是脚本 run_all_vcor_target.sh 在目标上启动时所做的。

打开您的目标板并与来自 Ubuntu 的 putty 终端或来自您的 Windows 主机 PC 的 TeraTerm 终端建立串行通信。

确保您具有以太网点对点电缆连接,并具有正确的 IP 地址,以启用 ssh 通信,以便使用来自 Ubuntu 的 scp 或来自 Windows 主机 PC 的 pscp.exe 快速将文件传输到目标板。例如,您可以将目标板的 IP 地址设置为 192.168.1.217,而主机 PC 为 192.168.1.140

创建 build/target_vek280(或 build/target_vck190 等)文件夹的 tar 文件后,将其从主机 PC 复制到目标板。例如,在 Ubuntu PC 的情况下,使用以下命令:

scp target_vek280.tar root@192.168.1.217:~/

从目标板终端,运行以下命令(在 VEK280 的情况下):

tar -xvf target_vek280.tar
cd target_vek280
bash -x ./run_all_target.sh vek280

基于 VART C++ API 的应用程序使用 build_app.sh 脚本构建,最后针对每个 CNN 启动,通过 Python 脚本 check_runtime_top5_vcor.py 检查有效的 top-5 分类准确性,该脚本是从
vcor_performance.sh 脚本中启动的。

请注意,测试图像已使用 generate_target_test_images.py 脚本正确准备
以便将类名附加到图像文件名,从而启用使用 check_runtime_top5_vcor.py
检查预测准确性。

5.5.3 DPU 性能

在 VEK280 板上,以 fps 为单位测量的纯 DPU 性能(不包括 CPU 任务)为:

  • 使用 1 个线程时为 ~4804 fps,

  • 使用 3 个线程时为 ~10099 fps。

预测准确性为:

...
预测的总图像数 300
top1 错误预测数 41
top1 正确预测数 259
top5 错误预测数 4
top5 正确预测数 296
top1 准确性 = 0.86
top5 准确性 = 0.99
...

http://www.kler.cn/a/599730.html

相关文章:

  • 制作PaddleOCR/PaddleHub的Docker镜像
  • L2-052 吉利矩阵
  • 从双指针到单调栈,深挖“接雨水”的算法奥秘
  • 价值流映射(Value Stream Mapping):从流程可视化到敏捷效能革命
  • Haption力反馈遥操作机器人:6自由度高精度技术,定义远程操作新标准
  • 【Tauri2】001——安装及运行
  • 算法关键知识汇总
  • 人工智能笔记
  • 浅谈:《嵌入式软件中的那些数据结构》
  • 算法刷题整理合集(七)·【算法赛】
  • 深入理解 tree 命令行工具:目录结构可视化的利器
  • Elasticsearch 倒排索引 和 正排索引
  • python全栈-前端
  • 人工智能AI术语
  • Spring Boot(十五):集成Knife4j
  • 【redis】哨兵:人工恢复主节点故障和哨兵自动恢复主节点故障
  • 信号相关的程序
  • ResNet与注意力机制:深度学习中的强强联合
  • MySQL: 创建两个关联的表,用联表sql创建一个新表
  • SpringBoot+策略模式+枚举类,优雅消除if-else