# Bilinear interpolation using Neon intrinsics

I'm trying to do a Bilinear interpolation on the ARM Neon. However, I find that my vectorized code is slower than the regular one, on a BeagleBone Black. Any idea why this could happen?

I'm using gprof to debug and compiling with the following flags:

NonNeonFlags: g -Wall -pg -O3 -ffast-math
NeonFlags: \$(NonNeonFlags) -D__ARM__ -march=armv7-a -mtune=cortex-a8 -mfloat-abi=hard -mfpu=neon


interp.h

typedef struct InterpValues {
float32_t ab; //< a,b
float32_t a1b; //< a+1,b
float32_t ab1; //< a, b+1
float32_t a1b1; //< a+1, b+1
} InterpValues;

typedef struct InterpCoords {
float32_t x1; //< x1
float32_t x2; //< x2
} InterpCoords;


interp_neon.cpp

void interp_neon(InterpValues* values, InterpCoords* coords, float32_t* r, int n)
{
const float32_t INIT_ONE[4] = {1.0, 1.0, 1.0, 1.0};

float32x4x2_t x34;// = vld2q_f32(init_x1_x2);
float32x4_t aux;
float32x4_t vResult;
float32x4_t ONE = vld1q_f32(INIT_ONE);

for (int i=0;i<n;i+=4)
{
float32x4x4_t vValues = vld4q_f32((float32_t*) values);
float32x4x2_t vCoords = vld2q_f32((float32_t*) coords);

#define x1 vCoords.val[0]
#define x2 vCoords.val[1]
#define x3 x34.val[0]
#define x4 x34.val[1]
#define Iab vValues.val[0]
#define Ia1b vValues.val[1]
#define Iab1 vValues.val[2]
#define Ia1b1 vValues.val[3]

x3 = vmlsq_f32(ONE, x1, ONE);
x4 = vmlsq_f32(ONE, x2, ONE);

// Ia,b * x3 * x4
aux = vmulq_f32(x3, x4);
vResult = vmulq_f32(Iab, aux);

// Ia+1,b * x1 * x4
aux = vmulq_f32(x1, x4);
vResult = vmlaq_f32(vResult, Ia1b, aux);

// Ia,b+1 * x2 * x3
aux = vmulq_f32(x2, x3);
vResult = vmlaq_f32(vResult, Iab1, aux);

// Ia+1,b+1 * x1 * x2
aux = vmulq_f32(x1, x2);
vResult = vmlaq_f32(vResult, Ia1b1, aux);

vst1q_f32(r, vResult);

r += 4;
values += 4;
coords += 4;

#undef x1
#undef x2
#undef x3
#undef x4
#undef Iab
#undef Ia1b
#undef Iab1
#undef Ia1b1
}
}


interp.cpp

void interp(InterpValues* values, InterpCoords* coords, float32_t* r, int n)
{
for (int i=0;i<n;++i)
{
float32_t x3 = 1.0 - coords[i].x1;
float32_t x4 = 1.0 - coords[i].x2;
r[i] =
values[i].ab * x3 * x4 +
values[i].a1b * coords[i].x1 * x4 +
values[i].ab1 * coords[i].x2 * x3 +
values[i].a1b1 * coords[i].x1 * coords[i].x2;
}
}

• Why are you using .cpp file extensions for C? – nhgrif Feb 22 '16 at 0:53
• I'm using classes on some parts of the process. But your point is right, I could use only the c extension on this code. – Josejulio Feb 22 '16 at 3:04
• I got better results when moving from intrinsics to Neon ASM. So i guess I'm either using wrong the intrinsics or the gcc compiler is doing a bad job here. – Josejulio Jul 14 '16 at 22:15