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

从FPGA说起的深度学习(四)

a0f88c17759103a2ce86b09d69cc09d0.png

这是新的系列教程,在本教程中,我们将介绍使用 FPGA 实现深度学习的技术,深度学习是近年来人工智能领域的热门话题。

在本教程中,旨在加深对深度学习和 FPGA 的理解。

  • 用 C/C++ 编写深度学习推理代码

  • 高级综合 (HLS) 将 C/C++ 代码转换为硬件描述语言

  • FPGA 运行验证

585319f89f5e3c3045dc08065a475db1.png

在上一篇文章中,我们用C语言实现了一个卷积层,并查看了结果。在本文中,我们将实现其余未实现的层:全连接层、池化层和激活函数 ReLU。

每一层的实现

全连接层

全连接层是将输入向量X乘以权重矩阵W,然后加上偏置B的过程。下面转载第二篇的图,能按照这个图计算就可以了。

ba2f4bf0fca2cd2c53c47b1263e9e03f.png

全连接层的实现如下。

void linear(const float *x, const float* weight, const float* bias,int64_t in_features, int64_t out_features, float *y) {for (int64_t i = 0; i < out_features; ++i) {float sum = 0.f;for (int64_t j = 0; j < in_features; ++j) {sum += x[j] * weight[i * in_features + j];}y[i] = sum + bias[i];}
}

该函数的接口和各个数据的内存布局如下。

考虑稍后设置 PyTorch 参数,内存布局与 PyTorch 对齐。

输入

  • x: 输入图像。shape=(in_features)

  • weight: 权重因子。shape=(out_features, in_features)

  • bias: 偏置值。shape=(out_features)

输出

  • y: 输出图像。shape=(out_features)

参数

  • in_features: 输入顺序

  • out_features: 输出顺序

在全连接层中,内部操作数最多为out_channels * in_channels一个,对于典型参数,操作数远低于卷积层。

另一方面,关注权重因子,卷积层为shape=(out_channels, in_channels, ksize, ksize),而全连接层为shape=(out_features, in_features)。例如,如果层从卷积层变为全连接层,in_features = channels * width * height则以下关系成立。width, height >> ksize考虑到这一点,在很多情况下,全连接层参数的内存需求大大超过了卷积层。

由于FPGA内部有丰富的SRAM缓冲区,因此擅长处理内存访问量大和内存数据相对于计算总量的大量复用。单个全连接层不会复用权重数据,但是在视频处理等连续处理中,这是一个优势,因为要进行多次全连接。

另一方面,本文标题中也提到的边缘环境使用小型FPGA,因此可能会出现SRAM容量不足而需要访问外部DRAM的情况。如果你有足够的内存带宽,你可以按原样访问它,但如果你没有足够的内存带宽,你可以在参数调整和训练后对模型应用称为剪枝和量化的操作。

池化层

池化层是对输入图像进行缩小的过程,这次使用的方法叫做2×2 MaxPooling。在这个过程中,取输入图像2x2区域的最大值作为输出图像一个像素的值。这个看第二张图也很容易理解,所以我再贴一遍。

76ac90120ad41baf98386f5aa945b94d.png

即使在池化层,输入图像有多个通道,但池化过程本身是针对每个通道独立执行的。因此,输入图像中的通道数和输出图像中的通道数在池化层中始终相等。

池化层的实现如下所示:

void maxpool2d(const float *x, int32_t width, int32_t height, int32_t channels, int32_t stride, float *y) {for (int ch = 0; ch < channels; ++ch) {for (int32_t h = 0; h < height; h += stride) {for (int32_t w = 0; w < width; w += stride) {float maxval = -FLT_MAX;for (int bh = 0; bh < stride; ++bh) {for (int bw = 0; bw < stride; ++bw) {maxval = std::max(maxval, x[(ch * height + h + bh) * width + w + bw]);}}y[(ch * (height / stride) + (h / stride)) * (width / stride) + w / stride] = maxval;}}}
}

这个函数的接口是:

此实现省略了边缘处理,因此图像的宽度和高度都必须能被stride整除。

输入

  • x: 输入图像。shape=(channels, height, width)

输出

  • y: 输出图像。shape=(channels, height/stride, width/stride)

参数

  • width: 图像宽度

  • height: 图像高度

  • stride:减速比

ReLU

ReLU 非常简单,因为它只是将负值设置为 0。

void relu(const float *x, int64_t size, float *y) {for (int64_t i = 0; i < size; ++i) {y[i] = std::max(x[i], .0f);}
}

由于每个元素的处理是完全独立的,x, y因此未指定内存布局。

硬件生成

到这里为止的内容,各层的功能都已经完成了。按照上一篇文章中的步骤,可以确认这次创建的函数也产生了与 libtorch 相同的输出。此外,Vivado HLS 生成了一个通过 RTL 仿真的电路。从这里开始,我将简要说明实际生成了什么样的电路。

如果将上述linear函数原样输入到 Vivado HLS,则会发生错误。这里,将输入输出设为指针->数组是为了决定在电路制作时用于访问数组的地址的位宽。另外,in_features的值为778=392,out_将features的值固定为32。这是为了避免Vivado HLS 在循环次数可变时输出性能不佳。

static const std::size_t kMaxSize = 65536;void linear_hls(const float x[kMaxSize], const float weight[kMaxSize], const float bias[kMaxSize], float y[kMaxSize]) {dnnk::linear(x, weight, bias, 7*7*8, 32, y);
}

linear_hls函数的综合报告中的“性能估计”如下所示:

05117923823efed58aee7f48b232211a.png

在Timing -> Summary中写入了综合时指定的工作频率,此时的工作频率为5.00 ns = 200MHz。重要的是 Latency -> Summary 部分,它描述了执行此函数时的周期延迟(Latency(cycles))和实时延迟(Latency(absolute))。看看这个,我们可以看到这个全连接层在 0.566 ms内完成。

在 Latency -> Detail -> Loop 列中,描述了每个循环的一次迭代所需的循环次数(Iteration Latency)和该循环的迭代次数(Trip Count)。延迟(周期)包含Iteration Latency * Trip Count +循环初始化成本的值。Loop 1 是out_features循环到loop 1.1  in_features。在Loop1.1中进行sum += x[j] * weight[i * in_features + j]; 简单计算会发现需要 9 个周期才能完成 Loop 1.1 所做的工作。

使用HLS中的“Schedule Viewer”功能,可以更详细地了解哪些操作需要花费更多长时间。下图横轴的2~10表示Loop1.1的处理内容,大致分为x,weights等的加载2个循环,乘法(fmul)3个循环,加法(fadd)4个循环共计9个循环。

4629edffcc1efc0ea7d4e180f0855af0.png

在使用 HLS 进行开发期间通过添加#pragma HLS pipeline指令,向此代码添加优化指令以指示它创建高效的硬件。与普通的 FPGA 开发类似,运算单元的流水线化和并行化经常用于优化。通过这些优化,HLS 报告证实了加速:

  • 流水线:减少迭代延迟(min=1)

  • 并行化:减少行程次数,删除循环

正如之前也说过几次的那样,这次的课程首先是以FPGA推理为目的,所以不会进行上述的优化。有兴趣进行什么样的优化的人,可以参考以下教程和文档。

  • 教程

https://github.com/Xilinx/HLS-Tiny-Tutorials

  • 文档

https://www.xilinx.com/support/documentation/sw_manuals/xilinx2019_2/ug902-vivado-high-level-synthesis.pdf

最后,该函数的接口如下所示。

08f29ecc3998d37667e910154a2fe82a.png

由于本次没有指定接口,所以数组接口如x_ 等ap_memory对应FPGA上可以1个周期读写的存储器(BRAM/Distributed RAM)。在下一篇文章中,我们将连接每一层的输入和输出,但在这种情况下,我们计划连接 FPGA 内部的存储器作为每一层之间的接口,如本例所示。

总结

在本文中,我们实现了全连接层、池化层和 ReLU。现在我们已经实现了所有层,我们将在下一篇文章中组合它们。之后我们会实际给MNIST数据,确认我们可以做出正确的推论。

897856bfe8614cf6daad44288f46f251.jpeg

从FPGA说起的深度学习(三)

c336a9886ecf92e4c1583cb636940ada.jpeg

从FPGA说起的深度学习(二)

3a4df417995406d5a0f9ff0cd4688045.jpeg

从FPGA说起的深度学习(一)

相关文章:

从FPGA说起的深度学习(四)

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

pytorch入门7--自动求导和神经网络

深度学习网上自学学了10多天了&#xff0c;看了很多大神的课总是很快被劝退。终于&#xff0c;遇到了一位对小白友好的刘二大人&#xff0c;先附上链接&#xff0c;需要者自取&#xff1a;https://b23.tv/RHlDxbc。 下面是课程笔记。 一、自动求导 举例说明自动求导。 torch中的…...

QT 之wayland 事件处理分析基于qt5wayland5.14.2

1. Qt wayland 初始化 接收鼠标/案件&#xff0c;触摸屏等事件事件 QWaylandNativeInterface : public QPlatformNativeInterface 在QWaylandNativeInterface 继承qpa 接口类QPlatformNativeInterface; 1.1 初始化鼠标&#xff1a; void *QWaylandNativeInterface::nativeR…...

【this 和 super 的区别】

在 Java 中&#xff0c;this 和 super 都是关键字&#xff0c;表示当前对象和父类对象。 this 关键字可以用于以下几种情况&#xff1a; 引用当前对象的成员变量&#xff0c;方法和构造方法&#xff0c;用于区分局部变量和成员变量重名的情况&#xff1b; 调用当前类的另外一…...

K8s:Monokle Desktop 一个集Yaml资源编写、项目管理、集群管理的 K8s IDE

写在前面 Monokle Desktop 是 kubeshop 推出的一个开源的 K8s IDE相关项目还有 Monokle CLI 和 Monokle Cloud相比其他的工具&#xff0c;Monokle Desktop 功能较全面&#xff0c;涉及 k8s 管理的整个生命周期博文内容&#xff1a;Monokle Desktop 下载安装&#xff0c;项目管理…...

自动化测试实战篇(8),jmeter并发测试登录接口,模拟从100到1000个用户同时登录测试服务器压力

首先进行使用jmeter进行并发测试之前就需要搞清楚线程和进程的区别还需要理解什么是并发、高并发、并行。还需要理解高并发中的以及老生常谈的&#xff0c;TCP三次握手协议和TCP四次握手协议**TCP三次握手协议指&#xff1a;****TCP四次挥手协议&#xff1a;**进入Jmeter&#…...

ATTCK v12版本战术实战研究—持久化(二)

一、前言前几期文章中&#xff0c;我们介绍了ATT&CK中侦察、资源开发、初始访问、执行战术、持久化战术的知识。那么从前文中介绍的相关持久化子技术来开展测试&#xff0c;进行更深一步的分析。本文主要内容是介绍攻击者在运用持久化子技术时&#xff0c;在相关的资产服务…...

python函数式编程

1 callable内建函数判断一个名字是否为一个可调用函数 >>> import math >>> x 1 >>> y math.sqrt >>> callable(x) False >>> callable(y) True 2 记录函数&#xff08;文档字符串&#xff09; >>> def square(x): …...

3.linux下安装mysql

1.安装前的环境准备 查看是否安装过mysql 首先检测Linux操作系统中是否安装了MySQL&#xff1a; # rpm -qa | grep -i mysql 卸载安装包 如果有信息出现&#xff0c;则进行删除&#xff0c;命令如下&#xff1a; # rpm -e --nodeps 包名 删除老版本mysql的开发头文件和…...

17、MySQL分库分表,原理实战

MySQL分库分表,原理实战 1.MyCAT分布式架构入门及双主架构1.1 主从架构1.2 MyCAT安装1.3 启动和连接1.4 配置文件介绍2.MyCAT读写分离架构2.1 架构说明2.2 创建用户2.3 schema.xml2.4 连接说明2.5 读写测试2.6 当前是单节点3.MyCAT高可用读写分离架构3.1 架构说明3.3 schema.xm…...

【C++的OpenCV】第九课-OpenCV图像常用操作(六):图像形态学-阈值的概念、功能及操作(threshold()函数))

目录一、阈值&#xff08;thresh&#xff09;的概念二、阈值在图形学中的用途三、阈值的作用和操作3.1 在OpenCV中可以进行的阈值操作3.2 操作实例3.2.1 threshold()函数介绍3.2.2 实例3.2.3 结果上节课的内容&#xff08;作者还是鼓励各位同学按照顺序进行学习哦&#xff09;&…...

[Java代码审计]—MCMS

环境搭建 MCMS 5.2.4&#xff1a;https://gitee.com/mingSoft/MCMS/tree/5.2.4/利用 idea 打开项目 创建数据库 mcms&#xff0c;导入 doc/mcms-5.2.8.sql 修改 src/main/resources/application-dev.yml 中关于数据库设置参数 启动项目登录后台 http://localhost:8080/ms/l…...

《程序员面试金典(第6版)》面试题 01.08. 零矩阵

题目描述 编写代码&#xff0c;移除未排序链表中的重复节点。保留最开始出现的节点。 示例1: 输入&#xff1a;[1, 2, 3, 3, 2, 1] 输出&#xff1a;[1, 2, 3] -示例2: 输入&#xff1a;[1, 1, 1, 1, 2] 输出&#xff1a;[1, 2] 提示&#xff1a; 链表长度在[0, 20000]范…...

初识 Python

文章目录简介用途解释器命令行模式交互模式输入和输出简介 高级编程语言&#xff0c;解释型语言代码在执行时会逐行翻译成 CPU 能理解的机器码代码精简&#xff0c;但运行速度慢基础代码库丰富&#xff0c;还有大量第三方库代码不能加密 用途 网络应用工具软件包装其他语言开…...

常用sql语句分享

SELECT COUNT(DISTINCT money) FROM ac_association_course;#COUNT() 函数返回匹配指定条件的行数SELECT AVG(money) FROM ac_association_course;#AVG 函数返回数值列的平均值。NULL 值不包括在计算中SELECT id FROM ac_association_course order by id desc limit 1;#返回最大…...

极狐GitLab DevSecOps 为企业许可证安全合规保驾护航

本文来自&#xff1a; 小马哥 极狐(GitLab) 技术布道师 开源许可证是开源软件的法律武器&#xff0c;是第三方正确使用开源软件的安全合规依据。 根据 Linux 发布的 SBOM 报告显示&#xff0c;98% 的企业都在使用开源软件&#xff08;中文版报告详情&#xff09;。随着开源使用…...

后端程序员的前端基础-前端三剑客之HTML

文章目录1 HTML简介1.1 什么是HTML1.2 HTML能做什么1.3 HTML书写规范2 HTML基本标签2.1 结构标签2.2 排版标签2.3 块标签2.4 基本文字标签2.5 文本格式化标签2.6 标题标签2.7 列表标签(清单标签)2.8 图片标签2.9 链接标签2.10 表格标签3 HTML表单标签3.1 form元素常用属性3.2 i…...

VS2019加载解决方案时不能自动打开之前的文档(回忆消失)

✏️作者&#xff1a;枫霜剑客 &#x1f4cb;系列专栏&#xff1a;C实战宝典 &#x1f332;上一篇: 错误error c3861 :“_T“:找不到标识符 逐梦编程&#xff0c;让中华屹立世界之巅。 简单的事情重复做,重复的事情用心做,用心的事情坚持做&#xff1b; 文章目录前言一、问题描…...

ConcurrentHashMap-Java八股面试(五)

系列文章目录 第一章 ArrayList-Java八股面试(一) 第二章 HashMap-Java八股面试(二) 第三章 单例模式-Java八股面试(三) 第四章 线程池和Volatile关键字-Java八股面试(四) 提示&#xff1a;动态每日更新算法题&#xff0c;想要学习的可以关注一下 文章目录系列文章目录一、…...

互联网衰退期,测试工程师35岁的路该怎么走...

国内的互联网行业发展较快&#xff0c;所以造成了技术研发类员工工作强度比较大&#xff0c;同时技术的快速更新又需要员工不断的学习新的技术。因此淘汰率也比较高&#xff0c;超过35岁的基层研发类员工&#xff0c;往往因为家庭原因、身体原因&#xff0c;比较难以跟得上工作…...

Windows Cannot Initialize Data Bindings 问题的解决方法

前言 拿到一个调试程序, 怎么折腾都打不开, 在客户那边, 尝试了几个系统版本, 发现Windows 10 21H2 版本可以正常运行。 尝试 系统篇 系统结果公司电脑 Windows 8有问题…下载安装 Windows10 22H2问题依旧下载安装 Windows10 21H2问题依旧家里的 笔记本Window 11正常 网上…...

Leetcode每日一题 1487. 保证文件名唯一

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法......感兴趣就关注我吧&#xff01;你定不会失望。 &#x1f308;个人主页&#xff1a;主页链接 &#x1f308;算法专栏&#xff1a;专栏链接 我会一直往里填充内容哒&#xff01; &…...

Linux常用命令——lsusb命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) lsusb 显示本机的USB设备列表信息 补充说明 lsusb命令用于显示本机的USB设备列表&#xff0c;以及USB设备的详细信息。 lsusb命令是一个学习USB驱动开发&#xff0c;认识USB设备的助手&#xff0c;推荐大家使用…...

Python——我愿称之为最简单的语言

Python——我愿称之为最简单的语言开发工具基础语法变量和数据类型列表和元组字典if语句while语句函数类文件与异常测试代码参考书籍&#xff1a;《python编程从入门到实践》 开发工具 python编程环境分为两个部分&#xff1a;python解释器和文本编辑器。运行.py文件时&#…...

java.io.IOException: Broken pipe

1、问题出现的场景 线上环境&#xff0c;拉取对账单&#xff0c;走的接口的形式&#xff0c;当天单量比较大&#xff0c;就出现了&#xff0c;拉取订单超时&#xff0c;报了个错java.io.IOException: Broken pipe。 2、解决方案 我们设置的超时时间是100S&#xff0c;由于当…...

Python——列表排序和赋值

&#xff08;1&#xff09;列表排序&#xff1a; 列表排序方法 ls.sort() 对列表ls 中的数据在原地进行排序 ls [13, 5, 73, 4, 9] ls.sort()ls.sort(reverseFalse) 默认升序&#xff0c;reverseTrue&#xff0c;降序 ls [13, 5, 73, 4, 9] ls.sort(reverseTrue)key指定排序时…...

python+pytest接口自动化(7)-cookie绕过登录(保持登录状态)

在编写接口自动化测试用例或其他脚本的过程中&#xff0c;经常会遇到需要绕过用户名/密码或验证码登录&#xff0c;去请求接口的情况&#xff0c;一是因为有时验证码会比较复杂&#xff0c;比如有些图形验证码&#xff0c;难以通过接口的方式去处理&#xff1b;再者&#xff0c…...

【连接池】什么是HikariCP?HikariCP 解决了哪些问题?为什么要使用 HikariCP?

文章目录什么是连接池什么是HikariCPHikariCP 解决了哪些问题&#xff1f;为什么要使用 HikariCP&#xff1f;HikariCP 的使用Maven支持数据库什么是连接池 数据库连接池负责分配、管理和释放数据库的连接。 数据库连接复用&#xff1a;重复使用现有的数据库长连接&#xff0…...

Tapdata Cloud 基础课:新功能详解之「微信告警」,更及时的告警通知渠道

【前言】作为中国的 “Fivetran/Airbyte”, Tapdata 是一个以低延迟数据移动为核心优势构建的现代数据平台&#xff0c;内置 60 数据连接器&#xff0c;拥有稳定的实时采集和传输能力、秒级响应的数据实时计算能力、稳定易用的数据实时服务能力&#xff0c;以及低代码可视化操作…...

【巨人的肩膀】JAVA面试总结(四)

&#x1f4aa;、JVM 目录&#x1f4aa;、JVM1、说一下JVM的主要组成部分及其作用2、什么是JVM内存结构&#xff08;谈谈对运行时数据区的理解&#xff09;3、堆和栈的区别是什么4、堆中存什么&#xff1f;栈中存什么&#xff1f;5、为什么不把基本类型放堆中呢&#xff1f;6、为…...

松岗做网站费用/百度官网推广

首先假设2个参数&#xff1a; 总记录数&#xff1a;totalRecord 每页最大记录数&#xff1a;pageSize 方法一&#xff08;推荐&#xff09;: 总页数 &#xff08;总记录数 每页数据大小 - 1&#xff09; / 每页数据大小 totalPage (totalRecord pageSize - 1) / pageS…...

网站安全如何做/深圳网站建设开发公司

首先把应用程序发布&#xff0c;发布到文件系统在winR里面输入inetmgr,进入iis点击网站右键添加网站选择右边的属性&#xff0c;选择处理程序映射然后打开处理程序映射&#xff0c;选择右边的可执行的文件时找到aspnet_isapi.dll的文件在选择右边的添加通配符脚本映射这里的可执…...

做兼职网站的主要参考文献/超级外链工具有用吗

JavaScript之原型链 参考&#xff1a;http://zhangjiahao8961.iteye.com/blog/2070650原型链 概念 原型链是一种机制&#xff0c;指的是JavaScript每个对象包括原型对象都有一个内置的[[proto]]属性指向创建它的函数对象的原型对象&#xff0c;即prototype属性。 作用 原型链的…...

力软框架做网站/网站接广告

一、前言 JDOM是Breet Mclaughlin和Jason Hunter两大Java高手的创作成果&#xff0c;2000年初&#xff0c;JDOM作为一个开放源代码项目正式开始研发。JDOM是一种解析XML的Java工具包。 DOM 适合于当今流行的各种语言&#xff0c;包括Java,JavaScripte,VB,VBScript&#xff…...

微信端微网站怎么做/seo网站管理

2.1 问题 沿用练习一&#xff0c;通过调整Nginx服务端配置&#xff0c;实现以下目标&#xff1a; 访问Web页面需要进行用户认证 用户名为&#xff1a;tom&#xff0c;密码为&#xff1a;1234562.2 方案 通过Nginx实现Web页面的认证&#xff0c;需要修改Nginx配置文件&#x…...

凡客诚品是什么/seo网站优化平台

试验网站#1搜索引擎优化收录情况记录日期Yahoogooglebaidusogou每日收录每日收录增量每日收录每日收录增量每日收录每日收录增量每日收录每日收录增量2007-6-24288 333 1060 4813 2007-6-25164013523330108020481302007-6-26空间超过本月流量限制……&#xff0c;快到月底了…...