使用 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;
}
}
有人可以指导我利用 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;
}
}