Optimizing OpenCL-Based CNN Design on FPGA with Comprehensive Design Space Exploration and Collaborative Performance Modeling
文章的目的是:对于给定的CNN模型,通过作者自己设计的框架对设计空间进行探索,找到一个高效的FPGA设计。
这个框架包含三部分:
- LoopTree:在不写源代码的情况下,捕获CNN在FPGA上的硬件结构设计细节
- coarse-grained model:评估LoopTree的设计水平,选择最高效的LoopTree
- fine-grained model:基于源代码,以周期精确的方式优化粗粒度模型选择的设计
“对设计空间的探索”表示循环的顺序,循环之间的合并,循环的流水线设计,数据的获取方式等等。
通过提出的框架模型对得到的CNN硬件设计的性能进行评估,比如对吞吐量进行计算,作者提出的模型和之前的统计模型相比得到的预测结果相比误差更小,预测的结果更精确。
然后通过作者提出的性能指标的大小,对参数(比如说增加分块的大小tile size,增加kernel数量)进行细微调整,实现更好的性能。
创新点:
为了实现更高的性能和预测精度,提出了一系列模型和指标
- 新的数据结构:LoopTree
- 基于LoopTree创建的综合设计空间,包含loop orders, loop tiling,BRAM和DDR配置和OpenCL属性。
- 粗粒度模型为了选择一个最好的LoopTree,所以通过对MAC,BRAM访问,DDR访问,pipe访问以及带宽模型,对LoopTree生成的CNN设计结果的resource和latency进行评估,通过评估结果选择LoopTree
- 细粒度模型通过考虑源代码中每种语句结构的贡献评估性能。还有四个性能指标指导优化过程
- 上述三个部分都支持基于多核设计的OpenCL设计
Proposed Framework
框架分为三部分。首先,LoopTree捕捉CNN设计结构,以便在不知道源代码时,可以对不同的设计结构进行评估和比较。然后粗粒度模型通过不同分支的配置信息来评估LoopTree的资源和延迟,将挑选的候选设计送入细粒度模型。细粒度模型将源代码解析成LLVM的中间件和控制流图,通过CFG的关键路径和LLVM指令评估CFG的延迟。四个性能指标代表OpenCL设计评价并提供优化建议。
LoopTree Space Generation
下面是一个典型的卷积层架构:
卷积的featuremap和权重从DDR或者Pipe导入,BRAM用于数据缓存减少访问延迟。在计算单元进行乘法和累计之后,将生成的数据写回输出的DDR或者pipe。
卷积层由四个主要部分组成:加载权重,特征图加载,计算,输出数据存储。
每个组成可以进一步分为四个操作(每个组成可能包含其中的某几个操作):pipe access, BRAM access, DDR access and MAC computations
下面是有分块和缓冲的卷积层循环例子。每个节点表示一个循环,节点名表示迭代变量的名字。子节点表示当前循环的子循环
硬件上的设计:
LoopTree生成过程如下:
-
首先,在卷积层计算部分,有6个循环节点,加入了tile操作之后就有10个循环了。然后有一些循环是对称的,就可以共享OpenCL属性和循环层级。比如说\(loop_x\),\(loop_y\) ,所以可以合并这两个循环。同样的操作作用在tx,ty和i,j上。
-
接着探索所有循环顺序如下图d,接着给相应的节点进行属性赋值(比如循环展开,流水线等等)如下图的e.
-
最后其他的分支像权重,输入,输出分支以相同的方式生成。通过下图的f对不同分支的位置进行探索形成LoopTree.
Design Space Pruning(设计空间的剪枝)
LoopTree的生成过程会对所有循环节点的排列顺序进行探索,使用OpenCL提供的设计属性,还会使用Loop Tiling进行优化,每个存储访问分支也可以选择从DDR或者pipe。所以框架的设计空间很大,剪枝操作可以使得现在的计算能力能够承受。
- Node Reduction:通过减少LoopTree中的节点数量,减少循环层次。这可以通过多个节点合并实现
- Loop Pre-Order(循环提前排序):不是所有循环节点的顺序都对CNN有效,tn必须是n的后代。所以这些非法的排序可以去掉(Loopm, Looptm)、(Loopn, Looptn)、(Loopxy, Looptxy),设计空间就减少了8倍
- Loop Pipelining:流水循环中的循环将完全展开[48]。因此,没有必要对流水循环内部的循环进行属性查找。比如Loopij应用了流水线属性,那么,Looptm和Looptn被直接展开。设计空间减少了Tm ×Tn
- Early Termination Rule:LoopTree的生成分好几步如图4,当资源使用超过预算的时候后面的步骤就可以跳过了。使用不到一半DSP的配置也会被丢弃,因为它们不能有效地利用芯片资源
COARSE-GRAINED MODEL
粗粒度模型通过这四个操作(MAC computation, BRAM access, DDR access and pipe access)的执行时间对LoopTree的执行时间进行估算。
完美循环展开的必要性:
对于普通的管道循环的延迟的计算:
迭代的次数Tc减一,然后乘以迭代间隔II,最后加上完成所有语句所需要的时间D
在循环语句之间没有指定逻辑的嵌套循环被认为是完美的,内层的循环Tj就是完美循环,可以和Tcp合并计算循环延迟:Dinst是非完美循环中指令的执行持剑。
如果不将完美循环中的节点合并:那就是直接乘在外面:
相对误差为:当D和Tcp差不多的时候,相对误差还是比较大的,所以完美循环的展开是很有必要的
计算单元的执行时间计算
在卷积程序里,计算单元的执行时间主要用来进行MAC操作,在LoopTree中表现为蓝色的叶子节点。
含有MAC操作的循环节点迭代数表示为:
展开因子表示为:
计算单元的延迟可以计算为:
Cr为迭代次数,Ur为平铺因子,迭代延迟为Dmac,Cs为外层的循环迭代次数
DSP的使用情况由MAC操作决定,这是早期的一个重要终止条件,比如在LoopTree生成过程中的剪枝。他等于所有包含MAC操作的循环的展开因子相乘:
BRAM的利用和时序估计
BRAM的大小由BRAM和分支节点之间的循环节点决定:
var为循环变量,BRAM大小等于迭代次数相乘:
为了使迭代间隔II等于1,以便吞吐量最大化和延迟最小化,所以需要对BRAM进行partition分割,避免数据的访问冲突。
切割数的计算:就是将所有需要展开的循环中包含BRAM的变量的展开因子相乘,和Pmax表示开发板最大的端口数 取最小值
迭代间隔II可能会被端口数限制,那么迭代间隔就等于需要最多分割的变量除以端口数:
在流水线循环中可能有多个缓冲区,所以BRAM最后的II取各个缓冲区的最大值:
BRAM的数据缓存时间也可以以同样的方式计算:
DDR时间计算
DDR访问对突发事务和位宽非常敏感,所以测试了带宽和它们之间的关系。发现在至少64个突发事务和int16(512位)的位宽下,达到巅峰速度:
DDR的时间计算不仅与带宽有关,还有DDR访问的迭代间隔II,计算公式为:
单次迭代中DDR的访问次数:Nddr,除以DDR的分块数B,然后包含ddr访问循环的展开因子累乘
由于m_axi接口可以同时调度DDR读和写,所以取读和写的迭代间隔最大值:
如果DDR不是交错访问(Non-interleaved DDR Access)的,那么迭代间隔的计算就取,每个分块bank迭代间隔的最大值:
结合带宽模型和LoopTree,ddr的执行时间可以计算为:
DSIddr (data size per iteration),每次迭代数据大小除以带宽得到每次迭代的执行时间,再乘以迭代次数。
管道时间计算
由于每个管道一次只能读取一条数据,因此受管道约束的迭代间隔可估计为
包含管道存取的循环的展开因子相乘,然后和流水线中的管道访问次数相乘。
和BRAM一样,取所有管道访问的最大迭代间隔:
和BRAM相似,管道访问的执行时间计算为:
Putting It All Together 结合所有操作
将上述提到的所有计算方法放在一起评估LoopTree的性能表现。每个分支的迭代间隔II和流水线深度是通过包含的所有操作,也就是箭头指向它的操作计算得到的。II取每个操作的最大迭代间隔,流水线深度等于所有操作延迟之和,每个操作的延迟计算使用之前提到的公式。
整个LoopTree的延迟等于所有分支的延迟之和
Fine-Grained Model
LoopTree生成的设计空间经过粗粒度模型的筛选得到一批候选的LoopTree。OpenCL基于LoopTree模板生成源代码,输入到细粒度模型,对代码进行微调优化。
OpenCL的源代码输入到细粒度模型,被LLVM解析为中间件,然后构造控制流图CFG,过计算CFG的延迟来估计程序的延迟,基于LLVM中间件的性能预测实现周期级别的精确度。
论文的目的是辅助OpenCL对CNN进行设计,所以提出了四个性能指标来量化设计性能,识别设计瓶颈,就可以针对瓶颈进行参数调整。
- potential from increasing the bandwidth usage:
- potential from reducing the repeated DDR accesses
- overhead of the edge effect
- overhead of non-MAC operations like control logic and memory accesses
Experiment
基于上述提出的四个指标识别出的设计瓶颈,就可以手动对代码进行微调。
下图15的a,卷积程序中表示分块大小的Ptile很小,所以瓶颈在于分块的尺寸,将尺寸从增加到28时,性能提高了30.2%。Pbw很高,说明带宽没有得到充分利用,可以通过合并内存布局实现。控制逻辑的花费Poverhead可以通过多核设计隐藏。
对b中的池化程序的优化也是同样的操作,块大小的Ptile很小,改善带宽使用Pw和逻辑开销Poverhead的潜力大。所以可以通过增加并行性和使用合并内存布局优化。
\(C_r\) 循环的层数相乘 / 展开的层数\(U_r\) = 需要迭代的次数
\(C_r = 6, U_r = 1\)
迭代次数:6/1 = 6
\(C_r = 6, U_r = 2\)
迭代次数:6/2 = 3
本文来自博客园,作者:xiongyuqing,转载请注明原文链接:https://www.cnblogs.com/xiongyuqing/p/16843646.html