HLS:关于channel方向上分块的理解

这是一篇解释的文章,主要是填补我在HLS的Conv和Pool部分时的一个坑!

首先,感谢一波ESELAB蓝同学,不断被询问下,我也理解了之前的这个点。原创好文。

1、首先,回顾下卷积中的一些概念。

在卷积的过程中,输入特征用feature_in表示,不分块的话,是一个三维的数据,即feature_in的长W、宽H和张数C。卷积核用kernel表示,不分块的话,是一个四维的数据,即kernel的长Kx、宽Ky、一个channel上的相同卷积核的数目K和不同卷积核的数目CHout。用下面的图片表示。
在这里插入图片描述
除了feature_in和kernel的维度定义外,还需要明白channel的概念,对于feature_in的channel数目,就是feature_in的张数,即C的大小。对于kernel的channel数目,就是不同的卷积核数目,即CHout的值。feature_in的一个channel上只有一张feature_in,但kernel的一个channel上可以有很多个kernel,以此来提取多张图的同一个特征。总体而言,多张feature_in与一个kernel进行卷积,其实就是把feature_in的多个channel输入到卷积核的一个channel中,最终运算得到一张feature map。至于多张feature_in最后为啥得到的是一张feature map,可以看下面的过程。这段有其他理解,不懂的可以看2021年05月16日的补充点,在最后面。
在这里插入图片描述
卷积层的基本运算流程为:C个channel的feature_in的第一个数据,与K个相同的kernel的第一个核数据,对应相乘,由于C和K是相等的,相乘后有C或K个结果,将这些结果相加,可以得到第一个数据卷积运算的第一步结果,再将Kx和Ky其他数据点,按类似的操作,对应位置乘和,根据Kx和Ky的大小,可以得到KxKy个数据。这些KxKy个数据直接相加,就是最终的feature map的第一个数据点。

2、紧接着,来看下不进行分块带来的一些问题。

根据上面提到的卷积运算,如果不进行分块,假设一次乘法或一次加法都消耗1T,那么不分块下,得到feature map的第一个数据,需要消耗的周期数为(C+1)·9+1=9C+10。

需要说明的是,要从CPU顺序运行的角度,来思考不分块下带来的问题,之后再想到分块并行下的好处,不能上来就认为块与块之前是并行计算的,否则,即使不分块也直接是消耗周期最小了,这是不合实际的。

从得到的结果,可以发现,消耗的周期数与C有关(C其实就是一个kernel的channel的相同kernel个数K,后面都用C表示),为了降低周期数,可以让C的值降下来,而C就是乘法的运算周期,可以用分块的方式,完成并行加速。

3、channel方向上的分块处理。
在这里插入图片描述

先说明下channel方向,这里的channel方向是针对feature_in和kernel分别而言的,如果对feature_in进行分块,feature_in就会变成四维数据,如果对kernel进行分块,kernel就会变成五维数据。虽然分别对feature_in和kernel分别而言,但分块的方式是一样的,这也很好理解,因为,需要做子块间的相乘,相乘时的尺寸要求就需要一样了。OK,说明完最基本的概念。那么对于feature_in的channel方向来分块,其实就是将feature_in的张数C进行平分,如果分成3个块,每个块的feature_in张数,就是C/3,不能整除先补0,这个之前HLS文章中有提到。另外,对于kernel的channel方向来分块,其实就是对一个kernel的channel通道上的所有kernel数据,做一个平分,来匹配feature_in的分块策略。

解释完channel方向上的问题后,看下为啥要进行分块,其实,对比之前不分块+CPU消耗周期的理解,这里很快就可以发现,如果做了分块,比如做个2分块,那么一个块的feature_in或kernel个数,就是C/2,而2个块间的乘法可以做到并行,那么最后,就只需要4.5C+10个周期了。

具体的对比可以看下面这图。在这图里,可以明显的发现相乘的周期缩短了两倍,提升了速度。总之,分块的策略是改变数据存放的方式,由不同的存放方式来完成计算的加速,后续有机会研究下NumPy那边的内存形式,这部分可能在那边也会得到巩固。
在这里插入图片描述
2021年的5月16日,来补充一点。

关于输入特征和卷积核的channel上的理解,很多文章和视频里提到的与本文中稍有差别。为此,我觉得使用他们的理解,反而可以更符合大众,去看懂更多的东西,因此,不得不补充下。

关于输入特征的channel,就是图中C的大小,表示feature_in的张数,这个是相同的。但对于kernel的channel,指的是一个卷积核中,使用的相同的kernel的数目,我想,这是为了跟feature_in相对应的,也是比较好理解的。但不同的卷积核,就不能用channel来表示了,为此,提出了kernel的深度,这个深度就是表示不同卷积核的数目。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学不懂啊阿田

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值