使用NEON优化ARM的卷积运算

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用NEON优化ARM的卷积运算相关的知识,希望对你有一定的参考价值。

有人可以指导我使用C中ARM Neon内在函数的优势来优化图像上滤波器的卷积吗?我已经在传统的C中实现了这一点,但是,我需要对代码进行时间优化,以便在支持NEON的ARM上实现更快的图像处理。对于使用NEON使用C的ARM上的算法实现,因特网上可用的资源非常有限。

我需要将3x3滤镜与图像进行卷积。我猜的主要问题是访问图像的3x3矩阵的循环约束。 NEON内在函数帮助我们一次加载8个字节的数据,但如何利用它来获取3x3矩阵? Convolution Example

现在,我正在访问像这样的3x3图像矩阵,

for(i=1;i<width;i++) // i = rows                                                                                                       
        {                                                                                                             
                if(i!=1)                                                                                                                       
                        fseek(fp, 1078+(width*(i-1)), SEEK_SET);                                                                               
                for(j=1;j<height-1;j++) // j = columns                                                                                         
                {                                                                                                                              
                        if(j!=1)                                                                                                               
                                fseek(fp, 1077 + (i*width) + j , SEEK_SET);                                                                    
                        for(k=0;k<9;k+=3)                                                                                                      
                        {                                                                                                                      
                                data[k] = getc(fp);                                                                                            
                                data[k+1] = getc(fp);                                                                                          
                                data[k+2] = getc(fp);                                                                                          
                                //fread(buf, sizeof(char), width - 3, fp);                                                                     
                                fseek(fp, width - 3, SEEK_CUR);                                                                                
                        }                                                                                                                      
                        pixel = vld1_u8(&data);                                                                                                
                        pixel_last = data[8];                                                                                     
                        result = vmul_u8(kernel,pixel);                                                                                        

                        for(k=0;k<8;k++)                                                                                                       
                                sum += result[k];                                                                                              

                        sum += pixel_last * kernel_last;                                                                                       
                        sum = sum/9;                                                                                                           
                        sum = sum > 255 ? 255 : sum;                                                                                           
                        imageData[i*width + j]= sum;                                                                                           

                }                                                                                                                              

        }                             
答案

@PaulR在上面的评论中给出了答案。在缓冲区中一次读取图像数据,然后应用滤波器算法将时序减少到近10倍。

这是我做的,

fread(imageData, sizeof(unsigned char), imgDataSize, fp);                                    

for(i=0;i<width;i++) // i = rows                                                                       
        {                                                                           
                start_1= clock();                                      
                for(j=0;j<height;j++) // j = columns                                    
                {                                                                                    
                        for(k=0;k<9;k+=3)                                                                      
                        {                                                           
                                data[k] = imageData[i*width + j];
                                data[k+1] = imageData[(i+1)*width + (j+1)];             
                                data[k+2] = imageData[(i+2)*width + (j+2)];                          
                        }                                                                                      
                        pixel = vld1_u8(&data);                                     
                        pixel_last = data[8];                                       
                        result = vmul_u8(kernel,pixel);                                                        

                        for(k=0;k<8;k++)                         
                                sum += result[k];                                       

                        sum += pixel_last * kernel_last;                                                       
                        sum = sum/9;                                                
                        sum = sum > 255 ? 255 : sum;             
                        newimageData[i*width + j]= sum;                                 

                }                                                                                              
        }                                                                                                      

以上是关于使用NEON优化ARM的卷积运算的主要内容,如果未能解决你的问题,请参考以下文章

Qualcomm Scorpion 双核 ARM NEON 代码有问题?

ARM NEON 图像转换优化

ARM 中的 NEON 实现

解决一个Ubuntu中编译NEON优化的OpenCV的错误

ARM平台NEON优化学习参考

关于 ARM NEON 周期的一些疑问