-
缘起,今天在做从NNIE推理网络得到的结果blob(NCHW)数据地址进行数据提取时,涉及到了数据对齐,才发现搞了这么久的图像算法,竟然连图像在内存中实际存储过程中是(一般4,nnie为16)字节对齐的都没有意识到(补:因为opencv Mat是不对齐的,只是低版本的Iplimage是对齐的)。做了个调查,受教了。下面是转载文章,作者通过代码分析的很明白。此外笔者对卷积输出的四维blob与全连接输入的一维vector进行内存对齐的分析。
-
背景:以前都是使用opencv的Mat类型进行图像数据的操作,后面碰到函数对图像数据的输入类型为BYTE*,碰到图像复原显示后出现图像的扭曲或者重影。图像四字节对齐是如果图像宽不是4的倍数,那么低版本的opencv(iplimage)(其实大部分其他库也一样)会对每行数据进行填充(为了加快存储和读取,计算机读取数据以4字节为单位),使其填充为4的倍数,所以在获取每行图像首地址时的偏移量是widthstep(一定是4的倍数)而不一定是width(当width是4的倍数时,widthstep=width)。**对齐后的width称之为跨度(stride)**例如,
3*3的未填充图像
1 2 3
4 5 6
7 8 9
那么填充后为
1 2 3 @
4 5 6 @
7 8 9 @ -
番外:
- 图像在caffe或NNIE中特征提取时是按照NCHW顺序进行内存存储的,按照最低维W需要对齐的原则,需要在W的基础上将stride(图像跨度)对齐到指定字节的倍数,那么对于卷积的输出blob 数据同样是基于W维对齐的,这在将blob数据读到一维指针指向的数据是应该注意。
- 同理,除神经网络卷积输出NCHW数据需要对齐外,全连接输出的vector也是对齐的,且对应NCHW各维度的分别为1x1x1xsize,注意数据是在W上,并不是在channel 维上(这一点可以通过可视化神经网络各层输出的shape来验证),并且在W维度上依旧是指定字节对齐的,只不过此时对齐后的存储对一维数据的访问是没有影响的。例如fc层输出127char 型数据,按照16字节对齐会对齐到跨度为128,但数据只在这个最后维度上。