从FPGA说起的深度学习(六)-任务并行性
这是新的系列教程,在本教程中,我们将介绍使用 FPGA 实现深度学习的技术,深度学习是近年来人工智能领域的热门话题。
在本教程中,旨在加深对深度学习和 FPGA 的理解。
用 C/C++ 编写深度学习推理代码
高级综合 (HLS) 将 C/C++ 代码转换为硬件描述语言
FPGA 运行验证

从这篇文章中,我们将从之前创建的网络模型中提取并行性,并确认处理速度得到了提高。首先,我们检查当前模型的架构,并考虑什么样的并行化是可性的。
并行化方法研究
当前模型架构的框图如下所示。限于篇幅省略了maxpool2d和relu。

在这个模块中,conv1、conv2、fc1、fc2都是作为不同的模块实现的。FPGA内部的SRAM在每一层之间插入一个缓冲区(x', x'', x''' ),这个缓冲区成为每一层的输入和输出。此后,每一层(conv1、conv2、fc1、fc2)被称为一个任务。
顺序处理(基线)
下图显示了使用该模块对 3 帧图像执行推理处理时的执行时间可视化。
每个任务的执行时间以推理模块的实际运行波形为准,是conv2>conv1>fc1>fc2的关系。在该模块中,conv1、conv2、fc1和fc2作为单独的任务实施,但是这些任务一次只能运行一个(后面会解释原因)。因此,如果将conv1、conv2、fc1、fc2各层的执行时间作为最终的执行时间,则这3帧图像的t0, t1, t2, t3处理时间为3 * (t0 + t1 + t2 + t3)

任务并行度
假设我们可以修复这些任务并发运行。这种情况下的执行时间如下所示,多个任务可以同时处理不同的帧。

提取并行性使多个任务可以同时运行,称为任务并行化。在这个过程中,conv2的执行时间占主导地位,所以3帧的处理时间为t0 + 3 * t1 + t2 + t3。
理想的任务并行度
最后,我们考虑可以理想地执行任务并行化的模式。如上所述,如果只提取任务并行性,最慢的任务就会成为瓶颈,整体处理速度会受到该任务性能的限制。因此,最有效的任务并行是所有任务都具有相同的执行时间。

在这种情况下,处理时间t0 + 3 * t1 + t2 + t3保持不变,但t0 = t1 = t2 = t3调整了每个任务的执行时间,从而提高了性能。在本课程中,实现这种加速的技术被称为循环并行化和数据并行化。这两种并行度提取方法将在下一篇文章中介绍。
任务并行化
在本文中,第一个目标是执行任务并行化。
由于这次创建的模块中有多个任务,貌似已经可以并行处理了,但在实际波形中并不是这样。之所以不能并行化,是因为作为x', x'', x'''任务间接口的buffer()不能被多个任务同时使用。对于任务并行化,任务之间的接口必须可以同时被两个或多个任务读写。
在这个模块x'中,任务级并行化是通过在任务之间使用乒乓缓冲区来实现的。乒乓缓冲区有两个缓冲区,一个用于写入,一个用于读取。带有乒乓缓冲器的框图如下所示:

如果以这种方式配置电路,存储 conv1 输出的缓冲区和 conv2 从中读取输入的缓冲区是分开的,因此 conv1 和 conv2 可以同时运行。虽然图中省略了,但所有层都可以通过双缓冲conv2 <-> fc1,fc1 <-> fc2同时操作。
要在 RTL 中实现这一点,准备两个缓冲区并实现切换机制会很麻烦,但在 Vivado/Vitis HLS 中,只需添加一些 pragma 即可实现这种并行化。
代码更改
对于此任务并行化,我们需要添加以下三种类型的编译指示。
#pragma HLS dataflow
#pragma HLS stable
#pragma HLS interface ap_ctrl_chain
在解释每个pragma的作用之前,我先inference_dataflow展示一下新增函数的源代码。与第五篇中的inference_top函数重叠的部分省略。
60 void inference_dataflow(const float x[kMaxSize],61 const float weight0[kMaxSize], const float bias0[kMaxSize],62 const float weight1[kMaxSize], const float bias1[kMaxSize],63 const float weight2[kMaxSize], const float bias2[kMaxSize],64 const float weight3[kMaxSize], const float bias3[kMaxSize],65 float y[kMaxSize]) {66 #pragma HLS dataflow67 #pragma HLS interface m_axi port=x offset=slave bundle=gmem0...76 #pragma HLS interface m_axi port=y offset=slave bundle=gmem977 #pragma HLS interface s_axilite port=x bundle=control...86 #pragma HLS interface s_axilite port=y bundle=control87 #pragma HLS interface s_axilite port=return bundle=control88 #pragma HLS interface ap_ctrl_chain port=return bundle=control8990 #pragma HLS stable variable=x91 #pragma HLS stable variable=weight092 #pragma HLS stable variable=bias093 #pragma HLS stable variable=weight194 #pragma HLS stable variable=bias195 #pragma HLS stable variable=weight296 #pragma HLS stable variable=bias297 #pragma HLS stable variable=weight398 #pragma HLS stable variable=bias399 #pragma HLS stable variable=y
100
101 dnnk::inference(x,
102 weight0, bias0,
103 weight1, bias1,
104 weight2, bias2,
105 weight3, bias3,
106 y);
107 }
第66 行添加#pragma HLS dataflow的 pragma使inference_dataflow这些内部函数之间的接口成为乒乓缓冲区并启用任务并行化。第 101 行调用的函数dnnk::inference是下面的函数,它通过第 20 行的#pragma HLS inline编译指示在函数内inference_dataflow内嵌展开。因此,诸如 conv2d, relu的函数符合任务并行化的条件,它们的接口 ( x1, x2, ...) 是一个乒乓缓冲区。
14 static void inference(const float* x,15 const float* weight0, const float* bias0,16 const float* weight1, const float* bias1,17 const float* weight2, const float* bias2,18 const float* weight3, const float* bias3,19 float* y) {20 #pragma HLS inline...3435 // 1st layer36 conv2d(x, weight0, bias0, kWidths[0], kHeights[0], kChannels[0], kChannels[1], 3, x1);37 relu(x1, kWidths[0] * kHeights[0] * kChannels[1], x2);38 maxpool2d(x2, kWidths[0], kHeights[0], kChannels[1], 2, x3);39...4849 // 4th layer50 linear(x8, weight3, bias3, kChannels[3], kChannels[4], y);51 }
inference_dataflow从函数的第90行#pragma HLS stable开始,在x, weight0, y输入/输出等函数inference_dataflow的入口/出口处自动完成同步。如果不去掉这个同步,两个进程之间就会产生依赖,比如“上一帧y输出完成->下一帧x输入准备好”,多任务就不行了。另请参阅Vivado HLS 官方文档 ( UG902 ),了解有关稳定阵列部分的详细说明。
最后,inference_dataflow该函数第88行的pragma修改了外部寄存器接口,使得#pragma HLS interface ap_ctrl_chain port=return该函数可以用于同时处理多个帧。inference_dataflow如果没有这个 pragma,即使你实现了 ping-pong 缓冲区,主机端也只会尝试一个一个地执行它们,性能不会提高。
综合结果确认
可以在检查综合时检查任务并行化是否顺利进行。
下面是HLS综合结果报告,Latency -> Summary一栏列出了整个函数的延迟和执行间隔(Interval)。在这里,整体延迟仍然是所有任务处理时间的总和,但执行间隔的值conv2d_232_U0与第二个卷积层的执行周期数相匹配。该模块的吞吐量是第二个卷积层执行间隔的倒数。

正如本文开头所解释的,conv2d_232_U0处理时间成为此任务并行化后电路中的瓶颈。任务并行化的速度提升率为947407 / 504898 = 1.88倍。
通过这种方式,我们能够确认 HLS 能够正确实现任务并行化。
总结
在本文中,我们通过提取任务并行性来加速处理。本来conv2占用了一半以上的执行时间,所以提速幅度不到2倍,如果设置为N,最大提速为N倍。
在下一篇文章中,我们将通过对卷积层应用数据并行化和循环并行化来解决每一层处理时间的不平衡。
关注我们
OpenFPGA,与数万打工人共同成长
相关文章:

从FPGA说起的深度学习(六)-任务并行性
这是新的系列教程,在本教程中,我们将介绍使用 FPGA 实现深度学习的技术,深度学习是近年来人工智能领域的热门话题。在本教程中,旨在加深对深度学习和 FPGA 的理解。用 C/C 编写深度学习推理代码高级综合 (HLS) 将 C/C 代码转换为硬…...

5.39 综合案例2.0 - STM32蓝牙遥控小车4(体感控制)
综合案例2.0 - 蓝牙遥控小车4- 体感控制成品展示案例说明器件说明小车连线小车源码遥控手柄遥控器连线遥控器代码1.摇杆PS2模块说明2.六轴MPU-6050说明成品展示 案例说明 用STM32单片机做了一辆蓝牙控制的麦轮小车,分享一下小车的原理和制作过程。 控制部分分为手机…...

Scala之面向对象
目录 Scala包: 基础语法: Scala包的三大作用: 包名的命名规范: 写包的好处: 包对象: 导包说明: 类和对象: 定义类: 封装: 构造器: 主从…...

深度学习目标检测项目实战(四)—基于Tensorflow object detection API的骨折目标检测及其界面运行
深度学习目标检测项目实战(四)—基于Tensorflow object detection API的骨折目标检测及其界面运行 使用tensorflow object detection进行训练检测 参考原始代码:https://github.com/tensorflow/models/tree/master/research 我用的是1.x的版本 所以环境必须有gpu版…...

嵌入式工程师如何快速的阅读datasheet的方法
目录 ▎从项目角度来看datasheet ▎各取所需 ▎最后 Datasheet(数据手册)的快速阅读能力,是每个工程师都应该具备的基本素养。 无论是项目开始阶段的选型还是后续的软硬件设计,到后期的项目调试,经常有工程师对着英…...
(三)合约广告
1. 广告位(CPT)合约 系统:广告排期系统 网站把某一个广告位卖给广告商,这段时间归广告商所有,到点了下线 (1)流量选择的维度:时间段、地域等 (2)典型场景…...

【Android -- 软技能】分享一个学习方法
前言 很多人都想通过学习来提升自己,但是,可能因为两个问题,阻碍了自己的高效提升: 学什么? 怎么学? 本文将从自己的学习实践出发,针对这两个问题,给出自己的一套学习流程。 1…...
Python-DQN代码阅读(10)
目录 1.代码 1.1 代码阅读 1.2 代码分解 1.2.1 f open("experiments/" str(env.spec.id) "/performance.txt", "a") 1.2.2 f.write(str(ep) " " str(time_steps) " " str(episode_rewards) " " str(…...

MongoDB入坑
MongoDB入坑一、体系架构1、简介2、MongoDB VS RDBMS3、文件4、体系结构二、权限管理1、开启2、角色三、存储引擎四、备份 & 恢复五、高可用0、主从复制1、副本集2、分片一、体系架构 1、简介 DBMS No.5;NoSQL Document No.1 1)BSON BSON(Binary …...

【论文总结】针对操作系统级虚拟化的抽象资源攻击
介绍 这是一篇来自2021CCS的论文,作者有Nanzi Yang, Wenbo Shen, Jinku Li, Yutian Yang, Kangjie Lu, Jietao Xiao, Tianyu Zhou, Chenggang Qin, Wang Yu, Jianfeng Ma, Kui Ren。 概述 本文的贡献如下: 新的攻击面:作者揭示了一个影响操…...
C# 提取 PDF 文档中的文本
C# .Net 使用 IText7 从PDF文件中提取出所有文本内容 【文 / 张赐荣】 首先在 Nuget 包管理器中,安装"itext7" 和 "itext7.font-asian"。 如果不安装 "itext7.font-asian" PDF 文件中有非Unicode编码的字符,将会抛出运行时异常:iText.IO.Excep…...

mac如何升级node版本、切换node版本
一、mac如何升级node版本 当前官网稳定版本是18.15.0 所以我从v14.17.4升级到v18.15.0 二、mac如何切换node版本 切换到16.20.0版本 三、这里是用node.js的多版本管理器n来升级和切换的,命令如下: 1、sudo npm cache clean -f //清除node.js的cache …...
一位大专学历的女程序员要求月薪25K,学历重要吗?来看看面试过程
“请提供一份完整的简历,以便我审查。从您的简历中,我感觉您写得还不错。方便的话,您可以自我简单介绍一下吗?“ ”好的,我叫李娟,拥有大专学位,目前正在寻找一份Java开发架构师的工作岗位。“…...

ESP32驱动1.28寸GC9A01播放视频(一、视频分辨率的调整和视频格式的转换)
ESP32驱动1.28寸GC9A01播放视频(一、视频分辨率的调整和视频格式的转换)播放前准备转换视频分辨率用FFmpeg将.MP4转换为.mjpeg格式FFmpeg的win10环境搭建FFmpeg的下载环境变量的搭建MP4转换成mjpeg格式总结播放前准备 1.28寸GC9A01屏幕的分辨率是240x24…...

epoll的LT模式(水平触发)和ET模式(边沿触发)
前言 epoll的触发模式是个引发讨论非常多的话题,网络上这方面总结的文章也很多,首先从名字上就不是很统一,LT模式常被称为水平触发、电平触发、条件触发,而ET模式常被称为边缘触发、边沿触发等,这些都是从英文翻译过来…...
Java基础面试20题
Java的八大基本数据类型 答:可以分4种类型:布尔类型(boolean),字符类型(char),浮点类型(double,float),整型(byte,short,int, long)。 String,StringBuffer与StringBuilder的区别? …...
Java面向对象封装
目录 封装的概念 封装具体实现步骤 示例代码如下 封装具体语法 封装的概念 Java封装是一种面向对象的编程方法,它的主要思想是将类的内部细节(包括数据和方法)隐藏起来,对外只提供公共的访问接口,从而保证了程序的安全性和稳定性。 封装具体实现步骤 1、声明类的成…...

队列实现图书信息管理(C语言)
文章目录Queue.hmain.cQueue.c用队列实现一个图书信息管理,这里放一下有哪些文件。(ps:我之前写的是学生信息管理,但是有人说我们的作业是写图书,就该了下内容,没有改文件名)队列是用链表实现的…...

Java开发 - 读写分离初体验
前言 上一篇中,我们介绍了主从复制,相信学过的小伙伴已经能够很好的掌握主从复制的技术,实际上也并没有那么难,虽然没有讲一主多从,多主多从的配置,但是从一主一从的配置中也很容易联想到该怎么配置&#…...

图文详解CAN Log文件 - ASC文件格式
目录 1 CAN Log文件 -- ASC文件格式 1.1 Header 1.2 版本编号 1.3 经典CAN网络中的描述 1.3.1 经典CAN Standard标准帧的描述 1.3.2 经典CAN Extended扩展帧的描述 1.3.3 CAN Remote远程帧的描述 1.3.4 CAN Error错误帧的描述 1.4 CANFD网络中的描述 1.4.1 经典CAN S…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...

linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...