从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…...

网络编程套接字(一)
学习任务: 我们先来认识端口号,区分好主机IP和端口号的区别,以及涉及到进程PID和端口号的区别。 然后简单认识一下TCP协议和UDP协议,这两个协议都是传输层的。接着了解什么是网络字节序,它有什么作用。然后是网络编程的…...
Mysql数据库存储过程
1、参数分类 存储过程的参数类型可以是IN、OUT和INOUT。根据这点分类如下: 1、没有参数(无参数无返回) 2、仅仅带 IN 类型(有参数无返回) 3、仅仅带 OUT 类型(无参数有返回) 4、既带 IN 又带 O…...
当我开始学习人工智能:人工智能的学派及研究目标
上课真是不认真啊,现在都写不来了作业了,真的会谢 一、人工智能的学派及其争论 1.1 对人工智能方法的争论 三个学派 符号主义 认为人的认知基元是符号,认知过程即符号操作过程。 认为人是一个物理符号系统,计算机也是一个物理符…...

Html5钢琴块游戏制作与分享(音游可玩)
当年一款手机节奏音游,相信不少人都玩过或见过。最近也是将其做了出来分享给大家。 游戏的基本玩法:点击下落的黑色方块,弹奏音乐。(下落的速度会越来越快) 可以进行试玩,手机玩起来效果会更好些。 点击…...
MySQL数据库——数据库设计概念和数据库设计步骤
数据库设计就是根据业务系统的具体需求,结合我们所选用的数据库,建立好表结构及表与表之间的管理关系,为这个业务系统构造出最优秀的数据存储模型的过程。使之能有效的对应用的数据进行存储,并高效的对已经存储的数据进行访问。 …...

【云原生】Kubernetes(k8s)之Pod概念和使用
k8s之Pod概念和使用一、Pod简介1.1、Pod的阶段(状态)1.2、容器状态二、Pod的定义2.1、restartPolicy2.2、imagePullPolicy2.3、command2.4、args2.5、resources三、Pod的使用3.1、创建并访问Pod3.2、多个应用容器3.3、Init容器3.3.1、Init容器与普通容器…...

数组(九)-- LC[316][321][402] 去除重复字母
1 移掉 K 位数字 1.1 题目描述 题目链接:https://leetcode.cn/problems/remove-k-digits/ 1.2 思路分析 这道题让我们从一个字符串数字中删除 k 个数字,使得剩下的数最小。也就说,我们要保持原来的数字的相对位置不变。 以题目中的 num1432…...

ubuntu下Thrift安装
thrift是一种常用rpc框架,工作中经常会用到,本文记录一下其安装过程。 目录 1.下载软件包 1.1thrift下载 1.2libevent下载 1.3boost下载 2.安装(注意步骤) 2.1安装libevent 2.2安装boost 2.3安装与Python2.7版本对应的py…...

读懂AUTOSAR :DiagnosticLogAndTrace DLT(四)-- API解析
一、周期调用的函数:Dlt_TxFunction 根据参数DltGeneralTrafficShapingSupport,决定如何去发送DLT消息。如果为TRUE,那需要参考参数DltLogChannelTrafficShapingBandwidth为每个Log通道设置发送带宽;如果为FALSE,那么…...

【LeetCode】剑指 Offer 56. 数组中数字出现的次数 p275 -- Java Version
1. 题目介绍(56. 数组中数字出现的次数) 面试题56.:数组中数字出现的次数, 一共分为两小题: 题目一:数组中只出现一次的两个数字题目二:数组中唯一只出现一次的数字 2. 题目1:数组中…...