从fpga说起的深度学习

碎碎思 碎碎思     2023-03-13     456

关键词:

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

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

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

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

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

  • FPGA 运行验证

到上一篇为止,我们已经完成了卷积层、全连接层、池化层、激活函数ReLU的所有C的编程实现。在本文中,我们将结合这些层来创建一个完整的推理函数。

模型实现

下面是在第 2 篇文章中创建的推理模型的图表。

首先输入一张1x28x28的图片,然后两次通过Conv2d -> ReLU -> MaxPool2d提取特征,最后转为linear,> ReLU -> Linear为10阶向量值。

用C写的时候,只需按如下依次逐层处理即可。

void conv2d(const float* x, const float* weight, const float* bias, int32_t width, int32_t height,
             int32_t in_channels, int32_t out_channels, int32_t ksize, float* y) 
   for (int32_t och = 0; och < out_channels; ++och) 
     for (int32_t h = 0; h < height; ++h) 
       for (int32_t w = 0; w < width; ++w) 
         float sum = 0.f;

         for (int32_t ich = 0; ich < in_channels; ++ich) 
           for (int32_t kh = 0; kh < ksize; ++kh) 
             for (int32_t kw = 0; kw < ksize; ++kw) 
               int32_t ph = h + kh - ksize/2;
               int32_t pw = w + kw - ksize/2;

               // zero padding
               if (ph < 0 || ph >= height || pw < 0 || pw >= width) 
                 continue;
               

               int64_t pix_idx = (ich * height + ph) * width + pw;
               int64_t weight_idx = ((och * in_channels + ich) * ksize + kh) * ksize + kw;

               sum += x[pix_idx] * weight[weight_idx];
             
           
         

         // add bias
         sum += bias[och];

         y[(och * height + h) * width + w] = sum;
       
     
   
 

函数内部的缓冲区 (x1-x8) 用于连接各层之间的特征数据。

在HLS中,在哪里定义这个buffer很重要,如果像这次一样把它放在函数中,就可以指定使用FPGA中的RAM(或寄存器)。另一方面,如果将此缓冲区作为函数的参数提供,则可以将数据连接到外部 DRAM。这个区域需要根据应用来设计,但是这次内部SRAM已经够用了,所以定义在函数内部。

如果像以前一样编写接口规范,将如下所示:

输入

  • x: 输入图像。shape=(1, 28, 28)

  • weight0:第一个卷积层的权重。shape=(4, 1, 3, 3)

  • bias0:第一个卷积层的偏差。shape=(4)

  • weight1:第二个卷积层的权重。shape=(8, 4, 3, 3)

  • bias1:第二个卷积层的偏差。shape=(8)

  • weight2:第一个全连接层的权重。shape=(32, 8 * 7 * 7)

  • bias2:第一个全连接层的偏差。shape=(32)

  • weight3:第二个全连接层的权重。shape=(10, 32)

  • bias3:第二个全连接层的偏差。shape=(10)

输出

  • y:输出向量。shape=(10)

界面设置

在目前创建的函数中,我们还没有具体定义创建电路的接口。未指定接口时,HLS 会为简单 SRAM 生成一个接口。

该接口不能用于访问DRAM等访问时间不确定的接口,不方便在真机上操作。为此,我们告诉HLS使用一种称为AMBA AXI4接口协议(以下简称AXI)的协议,该协议主要用于Xilinx FPGA上IP之间的接口。

简单介绍一下AXI,AXI是ARM公司提供的一种接口标准。

Xilinx IP主要使用以下三种协议。

  • AXI4:高速内存访问协议(主要用途:访问DRAM、PCIe等)

  • AXI4-Lite:AXI4的一个子集,一种用于低速内存访问的协议(主要用途:IP寄存器控制)

  • AXI4-Stream:仅用于单向数据传输的协议,无地址(主要用途:流数据处理)

这次我们将使用 AXI4 访问输入/输出数据,使用 AXI4-Lite 控制 IP。

具有接口定义的推理函数如下所示:

void inference_top(const float x[kMaxSize],
                   const float weight0[kMaxSize], const float bias0[kMaxSize],
                   const float weight1[kMaxSize], const float bias1[kMaxSize],
                   const float weight2[kMaxSize], const float bias2[kMaxSize],
                   const float weight3[kMaxSize], const float bias3[kMaxSize],
                   float y[kMaxSize]) 
#pragma HLS interface m_axi port=x offset=slave bundle=gmem0
#pragma HLS interface m_axi port=weight0 offset=slave bundle=gmem1
#pragma HLS interface m_axi port=weight1 offset=slave bundle=gmem2
#pragma HLS interface m_axi port=weight2 offset=slave bundle=gmem3
#pragma HLS interface m_axi port=weight3 offset=slave bundle=gmem4
#pragma HLS interface m_axi port=bias0 offset=slave bundle=gmem5
#pragma HLS interface m_axi port=bias1 offset=slave bundle=gmem6
#pragma HLS interface m_axi port=bias2 offset=slave bundle=gmem7
#pragma HLS interface m_axi port=bias3 offset=slave bundle=gmem8
#pragma HLS interface m_axi port=y offset=slave bundle=gmem9
#pragma HLS interface s_axilite port=x bundle=control
#pragma HLS interface s_axilite port=weight0 bundle=control
#pragma HLS interface s_axilite port=weight1 bundle=control
#pragma HLS interface s_axilite port=weight2 bundle=control
#pragma HLS interface s_axilite port=weight3 bundle=control
#pragma HLS interface s_axilite port=bias0 bundle=control
#pragma HLS interface s_axilite port=bias1 bundle=control
#pragma HLS interface s_axilite port=bias2 bundle=control
#pragma HLS interface s_axilite port=bias3 bundle=control
#pragma HLS interface s_axilite port=y bundle=control
#pragma HLS interface s_axilite port=return bundle=control
   dnnk::inference(x,
                  weight0, bias0,
                  weight1, bias1,
                  weight2, bias2,
                  weight3, bias3,
                  y);

dnnk::inference函数就是前面提到的推理函数,这个函数将dnnk::inference“包起来”了。

和上一篇文章一样,top函数的接口是一个数组,而不是一个指针。在仿真 HLS 时,此符号对于指定仿真器保留的内存缓冲区的大小是必需的,但它并不是很重要。

第 30-50 行 #pragma HLS interfaceport=<参数名称>bundle=<要分配的接口名称> 使用语法为每个函数参数指定接口协议,使用的协议有两个,m_axi和s_axilite,其中m_/s_部分表示请求是发送还是接收(AXI术语中的master/slave),后面的部分就是前面提到的协议部分增加。

在此函数中,每个数据端口都成为 AXI4 主端口并主动从 DRAM (L30-39) 中获取数据。此时主机CPU等访问的存储器地址可以通过AXI4-Lite从端口(L40-49)进行设置。

最后,用于开始处理的控制寄存器和用于检查处理完成的状态寄存器port=return链接到 AXI4-Lite 从端口 (L50)。

综合/结果确认

界面

将这个电路作为IP输出,放到Vivado的IP Integrator中,如下图。每个端口的名称对应于上面的interface pragma bundle位置。

熟悉 Vivado 开发的都知道,剩下要做的就是适当地连接端口,将能够创建能够进行推理处理的 FPGA 图像。

综合

综合时的表现如下:执行时间最短 1.775 ms,最长 7.132 ms。

在这里,我想知道为什么输入图像大小是固定的,但执行时间不固定,这是因为第三篇文章中创建的卷积函数continue包括补零处理。

由于这个补零过程只在屏幕边缘进行,实际执行时间几乎是最大时间7.132 ms。

for (int32_t kw = 0; kw < ksize; ++kw) 
     int32_t ph = h + kh - ksize/2;
     int32_t pw = w + kw - ksize/2;

     // zero padding
     if (ph < 0 || ph >= height || pw < 0 || pw >= width) 
       continue;
     

     int64_t pix_idx = (ich * height + ph) * width + pw;
     int64_t weight_idx = ((och * in_channels + ich) * ksize + kh) * ksize + kw;

     sum += x[pix_idx] * weight[weight_idx];
   

在这里为了可读性,用continue中止,但是在FPGA上,与在这里中断循环的处理相比,使用已经安装的乘法加法器进行0加法运算的成本更少。

资源使用

FPGA的资源利用率如下所示:总体使用量是微不足道的,因为没有增加并行化和流水线等资源的加速。

总结

在本文中,从第 3 篇文章开始创建的整个推理函数终于完成了。在下一篇文章中,可能是优化可能是先FPGA实现。

数字信号处理相关2(深度学习基本单元(2d卷积模块)的fpga实现)

...自:https://www.moore8.com/courses/1570 课程介绍  鉴于在深度学习加速方面的独特优势,FPGA已成为眼下最受关注的深度学习加速芯片。而Intel收购FPGA厂商Altera、亚马逊、腾讯、阿里等先后推出FPGA公有云,更使得“FPGA+... 查看详情

为什么fpga在深度学习领域有着得天独厚的优势?

01 FPGA在深度学习领域有哪些优势FPGA(Field-ProgrammableGateArray)是一种灵活的可编程硬件设备,它在深度学习应用领域中具有许多优势。首先,FPGA具有非常高的并行性。在深度学习中,许多计算都可以并行化... 查看详情

fpga教程案例59深度学习案例6——基于fpga的cnn卷积神经网络之整体实现

FPGA教程目录MATLAB教程目录--------------------------------------------------------------------------------------------------------------------------------目录1.软件版本2.CNN整体结构复习3.CNN的verilog实现  查看详情

fpga教程案例54深度学习案例1——基于fpga的cnn卷积神经网络之理论分析和fpga模块划分

FPGA教程目录MATLAB教程目录--------------------------------------------------------------------------------------------------------------------------------目录1.软件版本2.CNN卷积网络理论介绍2.1卷积层2.2池化层 查看详情

深度学习fpga实现基础知识6(deeplearning(深度学习)学习资料大全及csdn大牛博客推荐)

需求说明:深度学习FPGA实现知识储备来自:时间的诗第一部分:博客大牛(深度学习方向)1、http://blog.csdn.net/zouxy09研究方向:机器学习、计算机视觉、人机交互和人工智能等领域作品:DeepLearning(... 查看详情

fpga教程案例58深度学习案例5——基于fpga的cnn卷积神经网络之图像缓存verilog实现

FPGA教程目录MATLAB教程目录--------------------------------------------------------------------------------------------------------------------------------目录1.软件版本2.图像缓存的理论介绍3.图像缓存的verilog实现  查看详情

fpga教程案例57深度学习案例4——基于fpga的cnn卷积神经网络之卷积层verilog实现

FPGA教程目录MATLAB教程目录--------------------------------------------------------------------------------------------------------------------------------目录1.软件版本2.卷积层理论介绍3.卷积层的verilog实现  查看详情

fpga教程案例55深度学习案例2——基于fpga的cnn卷积神经网络之relu激活层verilog实现

FPGA教程目录MATLAB教程目录--------------------------------------------------------------------------------------------------------------------------------目录1.软件版本2.ReLu激活层理论介绍3.ReLu激活层的verilog实现 查看详情

fpga教程案例60深度学习案例7——基于fpga的cnn卷积神经网络之testbench编写以及cnn仿真测试

FPGA教程目录MATLAB教程目录--------------------------------------------------------------------------------------------------------------------------------目录1.软件版本2.CNN的仿真测试3.注意事项1.软件版本vivado2019 查看详情

深度学习/机器视觉/数字ic/fpga/算法手撕代码目录总汇

...算法手撕代码总汇FPGA工程师经典面试题数字IC经典面试题深度学习/人工智能/机器学习面试题数字图像/计算机视觉面试题FPGA/数字IC手撕代码总汇FPGA/数字IC手撕代码1——数据上下边沿检测更新中常用算法手撕代码总汇算法手撕代... 查看详情

从 fpga 控制的最佳深度相机是啥? intel realsense vs kinect v1 vs kinect v2?

】从fpga控制的最佳深度相机是啥?intelrealsensevskinectv1vskinectv2?【英文标题】:Whatisthebestdepthcameratobecontrolledfromanfpga?intelrealsensevskinectv1vskinectv2?从fpga控制的最佳深度相机是什么?intelrealsensevskinectv1vskinectv2?【发布时间】:2015-04-... 查看详情

刻意学习从提问题说起

    刻意学习从提问题说起    什么是刻意练习,关于这个问题我从一个简单的问题比如提问题开始切入?    提问题又分好几种,首先看第一类一上来就是两个字:在吗?然后就没下文... 查看详情

深度学习之概述(overview)

...究竟能够做什么?对我们有什么影响?我们从下面两张图说起:图1是工业革命时期的《纱厂女孩CottonMillGirl》,说明了工业革命导致机器替代人的体力劳动,把大量人从繁重的体力劳动中解放出来,更多人从事思考的、创新的、... 查看详情

深度学习硬件:tpu,dsp,fpga,aiasic,systolicarray动手学深度学习v2

1.TPU和其他1.1手机芯片1.2DSPdigitalsignalprocessor数字信号处理1.3可编程阵列FPGA-field-programmablegatearray1.4AIASIC-Application-specificintegratedcircuitsSystolicArrayFPGA华为用了很多去做路由器。造一个芯片出来,必须有生态,开发生态和研究... 查看详情

c++学习笔记---02---从一个小程序说起

从一个小程序说起这一讲的主要目的是帮助大家在C语言的背景知识上与C++建立联系。 问题探索 问题:对一个整型数组求和。要求:定义一个存储着n个元素的数组,要求用C语言完成这个任务。赶紧的:大家一起动手!参... 查看详情

深度学习的异构加速技术:螺狮壳里做道场

...高级研究员,隶属腾讯TEG-架构平台部,主要研究方向为深度学习异构计算与硬件加速、FPGA云、高速视觉感知等方向的构架设计和优化。“深度学习的异构加速技术”系列共有三篇文章,主要在技术层面,对学术界和工业界异构... 查看详情

c++学习笔记---03---从一个小程序说起2

从一个小程序说起2 要求:编写一个程序,要求用户输入一串整数和任意数目的空格,这些整数必须位于同一行中,但允许出现在该行中的任何位置。当用户按下键盘上的“Enter”键时,数据输入结束。程序自动对所有的整数... 查看详情

从语言只是工具说起

  “语言只是工具”,你会无数次听到这句话。在最开始学习一门语言时,赞同这句话;在慢慢深入时,特别是遇到困难时(这里的困难更多指的是一门语言语法上的学习的困难,例如最开始学习C的时候的指针就让很多人觉... 查看详情