使用 NEON 优化 ARM 的卷积运算

Optimize convolution operation for ARM using NEON

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

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

现在,我正在像这样访问 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;                                 

                }                                                                                              
        }