AVX图像算法优化系列二: 使用AVX2指令集加速查表算法。( 三 )


对于彩色的图像 , 就要稍微复杂一些了,因为涉及到RGB格式的排布,同时考虑一些对齐问题,最友好的方式就是一次性处理8个像素,24个字节,这一部分留给有兴趣的读者自行研究 。
在我本机的CPU中测试呢,灰度版本的查找表大概有20%的提速,彩色版本的要稍微多一些,大概有30%左右 。
这些提速其实不太明显,因为在整个过程中处理内存耗时较多,他并不是以计算为主要过程的算法 , 当我们某个算法中见也有查找时,并且为了计算查找表时 , 需要很多的数学运算去进行隐射的坐标计算时,这个时候这些隐射计算通常都是有浮点参与,或其他各种复杂的计算参与,这个时候用SIMD指令计算这些过程是能起到很大的加速作用的,在我们没有AVX2之前,使用SSE实现时,到了进行查表时通常的做法都是把前通过SSE计算得到的坐标的_m128i元素的每个值使用_mm_extract_epi32(这个是内在的SSE指令 , 不是用其他伪指令拼合的)提取出每个坐标值,然后在使用_mm_set相关的函数把查找表的返回值拼接成一个行的SSE变量,以便进行后续的计算,比如下面的代码:

AVX图像算法优化系列二: 使用AVX2指令集加速查表算法。

文章插图
这个时候使用AVX2的这个指令就方便了,如下所示:
AVX图像算法优化系列二: 使用AVX2指令集加速查表算法。

文章插图
注意到上面的Texture其实是个字节类型的数组 , 也就是一副图像,对应的C代码如下所示:
int SampleXF = IM_ClampI(ClipXF >> 16, 0, Width - 1);//试着拆分VX和VY的符号情况分开写,减少ClampI的次数,结果似乎区别不是特别大,因此优化意义不大int SampleXB = IM_ClampI(ClipXB >> 16, 0, Width - 1);int SampleYF = IM_ClampI(ClipYF >> 16, 0, Height - 1);int SampleYB = IM_ClampI(ClipYB >> 16, 0, Height - 1);unsigned char *SampleF = Texture + (SampleYF * Stride + SampleXF);unsigned char *SampleB = Texture + (SampleYB * Stride + SampleXB);Sum += SampleF[0] + SampleB[0];可见这里实际上是对字节类型进行查表,所以这里最后的那个scale参数我们取的是1,即中间的偏移是以字节为单位的,但是这里其实隐含着一个问题 , 即如果我们取样的是图片最右下角的那个位置的像素,因为要从那个位置开始读取四个字节的内存,除非图像原始格式是BGRA的,否则 , 必然会读取到超出图像内存外的内存数据,这个在普通的C语言中 , 已改会弹出一个系统错误框,蹦的一下说访问非法内存,但是我看用这个指令似乎目前还没有遇到这个错误,哪怕认为的输入一个会犯错误的坐标 。
如果是这样的话,得到的一个好处就是对于那些图像扭曲滤镜、缩放图像中哪些重新计算坐标的函数来说 , 不用临时构建一副同样数据的int类型图了,而可以直接放心的使用这个函数了 。
最后说明一点 , 经过在其他一些机器上测试,似乎有些初代即使支持AVX2的CPU,使用这些函数后相应的算法的执行速度反而有下降的可能性,不知道为什么 。
在我提供的SIMD指令优化的DEMO中,在 Adjust-->Exposure菜单下可以看到使用C语言和使用AVX进行查表优化的功能,有兴趣的作者可以自行比较下 。
AVX图像算法优化系列二: 使用AVX2指令集加速查表算法。

文章插图
很明显,在这里SSE优化选项是无法使用的 。
本文可执行Demo下载地址:  https://files.cnblogs.com/files/Imageshop/SSE_Optimization_Demo.rar,菜单中蓝色字体显示的部分为已经使用AVX加速的算法,如果您的硬件中不支持AVX2 , 可能这个DEMO你无法运行 。
如果想时刻关注本人的最新文章,也可关注公众号:
AVX图像算法优化系列二: 使用AVX2指令集加速查表算法。

文章插图

推荐阅读