C++ 使用霓虹灯内部特性加速浮标的高斯模糊
我想在arm中加速算法的某些部分(gaussianblur过滤器),我决定将SIMD与NEON Inquired一起使用。 但不幸的是,用NEON编写的代码比纯cpp代码要慢得多。 这些是纯cpp代码和NEON版本的代码。 有可能改进吗 纯cpp:C++ 使用霓虹灯内部特性加速浮标的高斯模糊,c++,image-processing,assembly,neon,gaussianblur,C++,Image Processing,Assembly,Neon,Gaussianblur,我想在arm中加速算法的某些部分(gaussianblur过滤器),我决定将SIMD与NEON Inquired一起使用。 但不幸的是,用NEON编写的代码比纯cpp代码要慢得多。 这些是纯cpp代码和NEON版本的代码。 有可能改进吗 纯cpp: inline void GaussianBlur_5x5_row(const float __restrict_arr *in, float __restrict_arr *out, const unsigned int cols) { //
inline void GaussianBlur_5x5_row(const float __restrict_arr *in, float __restrict_arr *out, const unsigned int cols)
{
//Left columns
out[0] = (in[0]+in[2])*0.054488685f + (in[0]+in[1])*0.24420135f + in[0]*0.40261996f;
out[1] = (in[0]+in[3])*0.054488685f + (in[0]+in[2])*0.24420135f + in[1]*0.40261996f;
//Middle columns
for (unsigned int j=2; j<cols-2; j+=1)
{
out[j] = (in[j-2]+in[j+2])*0.054488685f + (in[j-1]+in[j+1])*0.24420135f + in[j]*0.40261996f;
out[j+1] = (in[j-1]+in[j+3])*0.054488685f + (in[j]+in[j+2])*0.24420135f + in[j+1]*0.40261996f;
}
//Right columns
out[cols-2] = (in[cols-4]+in[cols-1])*0.054488685f + (in[cols-3]+in[cols-1])*0.24420135f + in[cols-2]*0.40261996f;
out[cols-1] = (in[cols-3]+in[cols-1])*0.054488685f + (in[cols-2]+in[cols-1])*0.24420135f + in[cols-1]*0.40261996f;
}
inline void GaussianBlur\u 5x5\u行(常量浮点限制到达,浮点限制到达,常量无符号整数列)
{
//左列
out[0]=(in[0]+in[2])*0.054488685f+(in[0]+in[1])*0.24420135f+in[0]*0.40261996f;
out[1]=(in[0]+in[3])*0.054488685f+(in[0]+in[2])*0.24420135f+in[1]*0.40261996f;
//中柱
对于(无符号整数j=2;j
出于软件工程和性能原因,这些应该是局部变量
当这些是全局变量时,生成的汇编代码中充斥着冗余的vstr
指令。(1)针对哪种特定的ARM体系结构?(2)正在使用哪个编译器,用于调用编译器的编译开关是什么?arm cortex a53是目标,对于使用gcc 8.3编译器和-o3 optimization Flag进行编译,我仍然无法获得要编译的代码。请在问题中添加完整的编译器命令行,以便其他人可以重现您的观察结果。foR编译这部分代码,你需要拥有所有的头文件,如果……可能的话,给我你的电子邮件地址,发送所有的,只是看看你的纯C++代码:“中间列”每个都计算了两次,这似乎相当浪费。循环是否应该说j+=2
?那么像coef_1
这样的常量也应该让编译器像处理字符串文本一样处理它们。非常量全局对常量来说也是可怕的,特别是当您在存储到未知float*
的循环中读取它们时。
#include <arm_neon.h>
//kernels coefficients for sigma =1 and kernel_size =5
float32x4_t coef_1 = { 0.054488685f , 0.122100675f , 0.20130998f , 0.122100675f };
float32x4_t coef_2 = { 0.122100675f , 0.20130998f , 0.122100675f, 0.054488685f };
float32x4_t load_1 ,
load_2 ,
load_3 ,
help_1 ,
help_2 ,
help_3 ;
float32x2_t a ,
dst_1 ,
dst_2 ;
inline void GaussianBlur5x5_row_NEON_128bit_2_itr( const float __restrict_arr *in, float __restrict_arr *out, const unsigned int cols)
{
//Left columns
out[0] = (in[0]+in[2])*0.054488685f + (in[0]+in[1])*0.24420135f + in[0]*0.40261996f;
out[1] = (in[0]+in[3])*0.054488685f + (in[0]+in[2])*0.24420135f + in[1]*0.40261996f;
//Middle columns
for (unsigned int j=2; j<cols-2; j+=2)
{
load_1 = vld1q_f32( &in[j-2] );
load_2 = vld1q_f32( &in[j-1] );
load_3 = vld1q_f32( &in[j ] );
help_1 = vmulq_f32( load_1 , coef_1 );
help_2 = vmulq_f32( load_2 , coef_2 );
help_3 = vaddq_f32( help_1 , help_2 );
a = vadd_f32 ( vget_high_f32( help_3 ) , vget_low_f32( help_3 ) );
dst_1 = vpadd_f32( a , a );
help_1 = vmulq_f32( load_2 , coef_1 );
help_2 = vmulq_f32( load_3 , coef_2 );
help_3 = vaddq_f32( help_1 , help_2 );
a = vadd_f32 ( vget_high_f32( help_3 ) , vget_low_f32( help_3 ) );
dst_2 = vpadd_f32( a , a );
out[j ] = dst_1[0];
out[j+1] = dst_2[0];
}
//Right columns
out[cols-2] = (in[cols-4]+in[cols-1])*0.054488685f + (in[cols-3]+in[cols-1])*0.24420135f + in[cols-2]*0.40261996f;
out[cols-1] = (in[cols-3]+in[cols-1])*0.054488685f + (in[cols-2]+in[cols-1])*0.24420135f + in[cols-1]*0.40261996f;
}
float32x4_t load_1 ,
load_2 ,
load_3 ,
help_1 ,
help_2 ,
help_3 ;
float32x2_t a ,
dst_1 ,
dst_2 ;